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.js CHANGED
@@ -43,7 +43,8 @@ function resolveOptions(options = {}) {
43
43
  apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
44
44
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
45
45
  customHeaders: options.customHeaders ?? {},
46
- environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST")
46
+ environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST"),
47
+ errorFormat: options.errorFormat ?? "problem-details"
47
48
  };
48
49
  }
49
50
  var DEFAULT_API_VERSION, DEFAULT_TIMEOUT;
@@ -99,6 +100,9 @@ var init_ksef_api_error = __esm({
99
100
  const message = details?.length ? details.map((d) => d.exceptionDescription ?? "").filter(Boolean).join("; ") || `KSeF API error: HTTP ${statusCode}` : `KSeF API error: HTTP ${statusCode}`;
100
101
  return new _KSeFApiError(message, statusCode, body);
101
102
  }
103
+ toProblemFields() {
104
+ return { detail: this.message };
105
+ }
102
106
  };
103
107
  }
104
108
  });
@@ -110,17 +114,20 @@ var init_ksef_rate_limit_error = __esm({
110
114
  "use strict";
111
115
  init_ksef_api_error();
112
116
  KSeFRateLimitError = class _KSeFRateLimitError extends KSeFApiError {
117
+ statusCode = 429;
113
118
  retryAfterSeconds;
114
119
  retryAfterDate;
115
120
  recommendedDelay;
116
- constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate) {
121
+ problem;
122
+ constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate, problem) {
117
123
  super(message, statusCode, errorResponse);
118
124
  this.name = "KSeFRateLimitError";
119
125
  this.retryAfterSeconds = retryAfterSeconds;
120
126
  this.retryAfterDate = retryAfterDate;
121
127
  this.recommendedDelay = retryAfterSeconds ?? 60;
128
+ this.problem = problem;
122
129
  }
123
- static fromRetryAfterHeader(statusCode, retryAfterHeader, body) {
130
+ static fromRetryAfterHeader(statusCode, retryAfterHeader, body, problem) {
124
131
  let retryAfterSeconds;
125
132
  let retryAfterDate;
126
133
  if (retryAfterHeader) {
@@ -135,8 +142,16 @@ var init_ksef_rate_limit_error = __esm({
135
142
  }
136
143
  }
137
144
  }
138
- const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : "Rate limited by KSeF API";
139
- return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate);
145
+ const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : problem?.detail ?? "Rate limited by KSeF API";
146
+ return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate, problem);
147
+ }
148
+ toProblemFields() {
149
+ return {
150
+ detail: this.problem?.detail,
151
+ traceId: this.problem?.traceId,
152
+ instance: this.problem?.instance,
153
+ timestamp: this.problem?.timestamp
154
+ };
140
155
  }
141
156
  };
142
157
  }
@@ -147,21 +162,29 @@ var KSeFUnauthorizedError;
147
162
  var init_ksef_unauthorized_error = __esm({
148
163
  "src/errors/ksef-unauthorized-error.ts"() {
149
164
  "use strict";
150
- init_ksef_error();
151
- KSeFUnauthorizedError = class extends KSeFError {
165
+ init_ksef_api_error();
166
+ KSeFUnauthorizedError = class extends KSeFApiError {
152
167
  statusCode = 401;
153
168
  detail;
154
169
  traceId;
155
170
  instance;
156
171
  timestamp;
157
172
  constructor(problemDetails) {
158
- super(problemDetails.detail || "Unauthorized");
173
+ super(problemDetails.detail || "Unauthorized", 401);
159
174
  this.name = "KSeFUnauthorizedError";
160
175
  this.detail = problemDetails.detail;
161
176
  this.traceId = problemDetails.traceId;
162
177
  this.instance = problemDetails.instance;
163
178
  this.timestamp = problemDetails.timestamp;
164
179
  }
180
+ toProblemFields() {
181
+ return {
182
+ detail: this.detail,
183
+ traceId: this.traceId,
184
+ instance: this.instance,
185
+ timestamp: this.timestamp
186
+ };
187
+ }
165
188
  };
166
189
  }
167
190
  });
@@ -171,8 +194,8 @@ var KSeFForbiddenError;
171
194
  var init_ksef_forbidden_error = __esm({
172
195
  "src/errors/ksef-forbidden-error.ts"() {
173
196
  "use strict";
174
- init_ksef_error();
175
- KSeFForbiddenError = class extends KSeFError {
197
+ init_ksef_api_error();
198
+ KSeFForbiddenError = class extends KSeFApiError {
176
199
  statusCode = 403;
177
200
  detail;
178
201
  reasonCode;
@@ -181,7 +204,7 @@ var init_ksef_forbidden_error = __esm({
181
204
  traceId;
182
205
  timestamp;
183
206
  constructor(problemDetails) {
184
- super(problemDetails.detail || "Forbidden");
207
+ super(problemDetails.detail || "Forbidden", 403);
185
208
  this.name = "KSeFForbiddenError";
186
209
  this.detail = problemDetails.detail;
187
210
  this.reasonCode = problemDetails.reasonCode;
@@ -190,6 +213,16 @@ var init_ksef_forbidden_error = __esm({
190
213
  this.traceId = problemDetails.traceId;
191
214
  this.timestamp = problemDetails.timestamp;
192
215
  }
216
+ toProblemFields() {
217
+ return {
218
+ detail: this.detail,
219
+ reasonCode: this.reasonCode,
220
+ security: this.security,
221
+ traceId: this.traceId,
222
+ instance: this.instance,
223
+ timestamp: this.timestamp
224
+ };
225
+ }
193
226
  };
194
227
  }
195
228
  });
@@ -199,21 +232,64 @@ var KSeFGoneError;
199
232
  var init_ksef_gone_error = __esm({
200
233
  "src/errors/ksef-gone-error.ts"() {
201
234
  "use strict";
202
- init_ksef_error();
203
- KSeFGoneError = class extends KSeFError {
235
+ init_ksef_api_error();
236
+ KSeFGoneError = class extends KSeFApiError {
204
237
  statusCode = 410;
205
238
  detail;
206
239
  instance;
207
240
  traceId;
208
241
  timestamp;
209
242
  constructor(problemDetails) {
210
- super(problemDetails.detail || "Operation status no longer available (retention expired)");
243
+ super(problemDetails.detail || "Operation status no longer available (retention expired)", 410);
211
244
  this.name = "KSeFGoneError";
212
245
  this.detail = problemDetails.detail;
213
246
  this.instance = problemDetails.instance;
214
247
  this.traceId = problemDetails.traceId;
215
248
  this.timestamp = problemDetails.timestamp;
216
249
  }
250
+ toProblemFields() {
251
+ return {
252
+ detail: this.detail,
253
+ traceId: this.traceId,
254
+ instance: this.instance,
255
+ timestamp: this.timestamp
256
+ };
257
+ }
258
+ };
259
+ }
260
+ });
261
+
262
+ // src/errors/ksef-bad-request-error.ts
263
+ var KSeFBadRequestError;
264
+ var init_ksef_bad_request_error = __esm({
265
+ "src/errors/ksef-bad-request-error.ts"() {
266
+ "use strict";
267
+ init_ksef_api_error();
268
+ KSeFBadRequestError = class extends KSeFApiError {
269
+ statusCode = 400;
270
+ detail;
271
+ instance;
272
+ errors;
273
+ traceId;
274
+ timestamp;
275
+ constructor(problemDetails) {
276
+ super(problemDetails.detail || problemDetails.title || "Bad Request", 400);
277
+ this.name = "KSeFBadRequestError";
278
+ this.detail = problemDetails.detail;
279
+ this.instance = problemDetails.instance;
280
+ this.errors = problemDetails.errors ?? [];
281
+ this.traceId = problemDetails.traceId;
282
+ this.timestamp = problemDetails.timestamp;
283
+ }
284
+ toProblemFields() {
285
+ return {
286
+ detail: this.detail,
287
+ errors: this.errors.length ? this.errors : void 0,
288
+ traceId: this.traceId,
289
+ instance: this.instance,
290
+ timestamp: this.timestamp
291
+ };
292
+ }
217
293
  };
218
294
  }
219
295
  });
@@ -319,6 +395,16 @@ var init_ksef_batch_timeout_error = __esm({
319
395
  }
320
396
  });
321
397
 
398
+ // src/errors/assert-never.ts
399
+ function assertNever(value) {
400
+ throw new Error(`Unexpected value: ${String(value)}`);
401
+ }
402
+ var init_assert_never = __esm({
403
+ "src/errors/assert-never.ts"() {
404
+ "use strict";
405
+ }
406
+ });
407
+
322
408
  // src/errors/index.ts
323
409
  var init_errors = __esm({
324
410
  "src/errors/index.ts"() {
@@ -329,11 +415,13 @@ var init_errors = __esm({
329
415
  init_ksef_unauthorized_error();
330
416
  init_ksef_forbidden_error();
331
417
  init_ksef_gone_error();
418
+ init_ksef_bad_request_error();
332
419
  init_ksef_auth_status_error();
333
420
  init_ksef_session_expired_error();
334
421
  init_ksef_validation_error();
335
422
  init_ksef_batch_timeout_error();
336
423
  init_error_codes();
424
+ init_assert_never();
337
425
  }
338
426
  });
339
427
 
@@ -582,6 +670,27 @@ var init_presigned_url_policy = __esm({
582
670
 
583
671
  // src/http/rest-client.ts
584
672
  import { consola } from "consola";
673
+ function isBadRequestProblem(value) {
674
+ if (typeof value !== "object" || value === null) return false;
675
+ const v = value;
676
+ if (typeof v.title !== "string") return false;
677
+ if (v.status !== void 0 && typeof v.status !== "number") return false;
678
+ if (v.errors !== void 0) {
679
+ if (!Array.isArray(v.errors)) return false;
680
+ for (const item of v.errors) {
681
+ if (typeof item !== "object" || item === null) return false;
682
+ const detail = item;
683
+ if (typeof detail.code !== "number") return false;
684
+ if (typeof detail.description !== "string") return false;
685
+ }
686
+ }
687
+ return true;
688
+ }
689
+ function isTooManyRequestsProblem(value) {
690
+ if (typeof value !== "object" || value === null) return false;
691
+ const v = value;
692
+ 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");
693
+ }
585
694
  var RestClient;
586
695
  var init_rest_client = __esm({
587
696
  "src/http/rest-client.ts"() {
@@ -591,6 +700,7 @@ var init_rest_client = __esm({
591
700
  init_ksef_unauthorized_error();
592
701
  init_ksef_forbidden_error();
593
702
  init_ksef_gone_error();
703
+ init_ksef_bad_request_error();
594
704
  init_ksef_batch_timeout_error();
595
705
  init_error_codes();
596
706
  init_route_builder();
@@ -679,6 +789,10 @@ var init_rest_client = __esm({
679
789
  ...this.options.customHeaders,
680
790
  ...request.getHeaders()
681
791
  };
792
+ const hasHeader = (name) => Object.keys(headers).some((header) => header.toLowerCase() === name.toLowerCase());
793
+ if (this.options.errorFormat !== "legacy" && !hasHeader("x-error-format")) {
794
+ headers["X-Error-Format"] = "problem-details";
795
+ }
682
796
  if (!headers["Authorization"] && this.authManager) {
683
797
  const token = overrideToken ?? this.authManager.getAccessToken();
684
798
  if (token) {
@@ -717,19 +831,40 @@ var init_rest_client = __esm({
717
831
  async ensureSuccess(response) {
718
832
  if (response.ok) return;
719
833
  const text = await response.text().catch(() => "");
834
+ let jsonCache = null;
720
835
  const parseJson = () => {
721
- try {
722
- return JSON.parse(text);
723
- } catch {
724
- return void 0;
836
+ if (jsonCache === null) {
837
+ try {
838
+ jsonCache = { value: JSON.parse(text) };
839
+ } catch {
840
+ jsonCache = { value: void 0 };
841
+ }
725
842
  }
843
+ return jsonCache.value;
726
844
  };
727
- if (response.status === 429) {
845
+ const tryParseProblem = (guard) => {
728
846
  const parsed = parseJson();
847
+ return parsed !== void 0 && guard(parsed) ? parsed : void 0;
848
+ };
849
+ if (response.status === 400) {
850
+ const problem = tryParseProblem(isBadRequestProblem);
851
+ if (problem) {
852
+ throw new KSeFBadRequestError(problem);
853
+ }
854
+ const legacy = parseJson();
855
+ if (hasErrorCode(legacy, KSeFErrorCode.BatchTimeout)) {
856
+ throw KSeFBatchTimeoutError.fromResponse(400, legacy);
857
+ }
858
+ throw KSeFApiError.fromResponse(400, legacy);
859
+ }
860
+ if (response.status === 429) {
861
+ const problem = tryParseProblem(isTooManyRequestsProblem);
862
+ const legacy = problem ? void 0 : parseJson();
729
863
  throw KSeFRateLimitError.fromRetryAfterHeader(
730
864
  response.status,
731
865
  response.headers.get("Retry-After"),
732
- parsed
866
+ legacy,
867
+ problem
733
868
  );
734
869
  }
735
870
  if (response.status === 401) {
@@ -2678,6 +2813,115 @@ var init_schema_registry = __esm({
2678
2813
  }
2679
2814
  });
2680
2815
 
2816
+ // src/validation/char-validity.ts
2817
+ function validateCharValidity(xml) {
2818
+ return [...findProcessingInstructions(xml), ...findDiscouragedUnicode(xml)];
2819
+ }
2820
+ function findProcessingInstructionTokens(xml) {
2821
+ const tokens = [];
2822
+ for (let i = 0; i < xml.length; ) {
2823
+ if (xml.startsWith("<!--", i)) {
2824
+ const end = xml.indexOf("-->", i + 4);
2825
+ i = end === -1 ? xml.length : end + 3;
2826
+ continue;
2827
+ }
2828
+ if (xml.startsWith("<![CDATA[", i)) {
2829
+ const end = xml.indexOf("]]>", i + 9);
2830
+ i = end === -1 ? xml.length : end + 3;
2831
+ continue;
2832
+ }
2833
+ if (xml.startsWith("<?", i)) {
2834
+ const end = xml.indexOf("?>", i + 2);
2835
+ if (end === -1) break;
2836
+ tokens.push({ token: xml.slice(i, end + 2), index: i });
2837
+ i = end + 2;
2838
+ continue;
2839
+ }
2840
+ i += 1;
2841
+ }
2842
+ return tokens;
2843
+ }
2844
+ function findProcessingInstructions(xml) {
2845
+ const errors = [];
2846
+ const matches = findProcessingInstructionTokens(xml);
2847
+ if (matches.length === 0) return errors;
2848
+ const firstMatch = matches[0];
2849
+ const firstTarget = firstMatch.token.match(PI_TARGET_RE)?.[1];
2850
+ const hasBom = xml.charCodeAt(0) === 65279;
2851
+ const prologPosition = hasBom ? 1 : 0;
2852
+ const firstIsProlog = firstMatch.index === prologPosition && firstTarget === "xml";
2853
+ for (let i = 0; i < matches.length; i++) {
2854
+ if (i === 0 && firstIsProlog) continue;
2855
+ const m = matches[i];
2856
+ const target = m.token.match(PI_TARGET_RE)?.[1] ?? "?";
2857
+ errors.push({
2858
+ code: "XML_PROCESSING_INSTRUCTION",
2859
+ message: `Processing instruction <?${target}?> at offset ${m.index} is not allowed (only <?xml ... ?> prolog is permitted)`,
2860
+ path: `offset:${m.index}`
2861
+ });
2862
+ }
2863
+ return errors;
2864
+ }
2865
+ function findDiscouragedUnicode(xml) {
2866
+ const errors = [];
2867
+ const seenRanges = /* @__PURE__ */ new Set();
2868
+ let utf16Offset = 0;
2869
+ for (const ch of xml) {
2870
+ const cp = ch.codePointAt(0);
2871
+ const idx = rangeIndex(cp);
2872
+ if (idx >= 0 && !seenRanges.has(idx)) {
2873
+ seenRanges.add(idx);
2874
+ errors.push({
2875
+ code: "XML_DISCOURAGED_UNICODE",
2876
+ 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)`,
2877
+ path: `offset:${utf16Offset}`
2878
+ });
2879
+ }
2880
+ utf16Offset += ch.length;
2881
+ }
2882
+ return errors;
2883
+ }
2884
+ function rangeIndex(cp) {
2885
+ let lo = 0;
2886
+ let hi = DISCOURAGED_UNICODE_RANGES.length - 1;
2887
+ while (lo <= hi) {
2888
+ const mid = lo + hi >> 1;
2889
+ const [start, end] = DISCOURAGED_UNICODE_RANGES[mid];
2890
+ if (cp < start) hi = mid - 1;
2891
+ else if (cp > end) lo = mid + 1;
2892
+ else return mid;
2893
+ }
2894
+ return -1;
2895
+ }
2896
+ var DISCOURAGED_UNICODE_RANGES, PI_TARGET_RE;
2897
+ var init_char_validity = __esm({
2898
+ "src/validation/char-validity.ts"() {
2899
+ "use strict";
2900
+ DISCOURAGED_UNICODE_RANGES = [
2901
+ [127, 132],
2902
+ [134, 159],
2903
+ [64976, 65007],
2904
+ [131070, 131071],
2905
+ [196606, 196607],
2906
+ [262142, 262143],
2907
+ [327678, 327679],
2908
+ [393214, 393215],
2909
+ [458750, 458751],
2910
+ [524286, 524287],
2911
+ [589822, 589823],
2912
+ [655358, 655359],
2913
+ [720894, 720895],
2914
+ [786430, 786431],
2915
+ [851966, 851967],
2916
+ [917502, 917503],
2917
+ [983038, 983039],
2918
+ [1048574, 1048575],
2919
+ [1114110, 1114111]
2920
+ ];
2921
+ PI_TARGET_RE = /^<\?(\S+)/;
2922
+ }
2923
+ });
2924
+
2681
2925
  // src/validation/invoice-validator.ts
2682
2926
  var invoice_validator_exports = {};
2683
2927
  __export(invoice_validator_exports, {
@@ -2830,6 +3074,12 @@ function collectDateErrors(obj, rootElement, errors) {
2830
3074
  }
2831
3075
  }
2832
3076
  async function validate(xml, options) {
3077
+ if (!options?.skipCharValidity) {
3078
+ const l1aErrors = validateCharValidity(xml);
3079
+ if (l1aErrors.length > 0) {
3080
+ return { valid: false, schemaType: null, errors: l1aErrors };
3081
+ }
3082
+ }
2833
3083
  const parsed = xml && xml.trim() ? xmlToObject(xml) : void 0;
2834
3084
  const l1 = validateWellFormedness(xml, parsed);
2835
3085
  if (!l1.valid) return l1;
@@ -2856,6 +3106,7 @@ var init_invoice_validator = __esm({
2856
3106
  "use strict";
2857
3107
  init_xml_to_object();
2858
3108
  init_schema_registry();
3109
+ init_char_validity();
2859
3110
  init_patterns();
2860
3111
  }
2861
3112
  });
@@ -3320,9 +3571,10 @@ var PermissionsService;
3320
3571
  var init_permissions = __esm({
3321
3572
  "src/services/permissions.ts"() {
3322
3573
  "use strict";
3574
+ init_ksef_validation_error();
3323
3575
  init_rest_request();
3324
3576
  init_routes();
3325
- PermissionsService = class {
3577
+ PermissionsService = class _PermissionsService {
3326
3578
  restClient;
3327
3579
  constructor(restClient) {
3328
3580
  this.restClient = restClient;
@@ -3380,6 +3632,7 @@ var init_permissions = __esm({
3380
3632
  }
3381
3633
  // Search methods
3382
3634
  async queryPersonalGrants(options, pageOffset, pageSize) {
3635
+ _PermissionsService.validateContextIdentifier(options?.contextIdentifier);
3383
3636
  const req = RestRequest.post(Routes.Permissions.Query.personalGrants).body(options ?? {});
3384
3637
  if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
3385
3638
  if (pageSize !== void 0) req.query("pageSize", String(pageSize));
@@ -3408,6 +3661,7 @@ var init_permissions = __esm({
3408
3661
  return response.body;
3409
3662
  }
3410
3663
  async queryEntitiesGrants(options, pageOffset, pageSize) {
3664
+ _PermissionsService.validateContextIdentifier(options?.contextIdentifier);
3411
3665
  const req = RestRequest.post(Routes.Permissions.Query.entitiesGrants).body(options ?? {});
3412
3666
  if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
3413
3667
  if (pageSize !== void 0) req.query("pageSize", String(pageSize));
@@ -3446,17 +3700,90 @@ var init_permissions = __esm({
3446
3700
  const response = await this.restClient.execute(req);
3447
3701
  return response.body;
3448
3702
  }
3703
+ static validateContextIdentifier(ctx) {
3704
+ if (!ctx) return;
3705
+ if (ctx.type === "InternalId") {
3706
+ const len = ctx.value.length;
3707
+ if (len < 10 || len > 16) {
3708
+ throw KSeFValidationError.fromField(
3709
+ "contextIdentifier.value",
3710
+ `InternalId must be 10-16 characters, got ${len}`
3711
+ );
3712
+ }
3713
+ }
3714
+ }
3449
3715
  };
3450
3716
  }
3451
3717
  });
3452
3718
 
3719
+ // src/utils/jwt.ts
3720
+ function decodeJwtPayload(token) {
3721
+ const parts = token.split(".");
3722
+ if (parts.length !== 3) return null;
3723
+ try {
3724
+ const payload = parts[1];
3725
+ const json = Buffer.from(payload, "base64url").toString("utf-8");
3726
+ return JSON.parse(json);
3727
+ } catch {
3728
+ return null;
3729
+ }
3730
+ }
3731
+ function tryParseJson(value) {
3732
+ if (typeof value !== "string") return void 0;
3733
+ try {
3734
+ return JSON.parse(value);
3735
+ } catch {
3736
+ return void 0;
3737
+ }
3738
+ }
3739
+ function tryParseJsonArray(value) {
3740
+ if (typeof value !== "string") return void 0;
3741
+ try {
3742
+ const parsed = JSON.parse(value);
3743
+ return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
3744
+ } catch {
3745
+ return void 0;
3746
+ }
3747
+ }
3748
+ function parseKSeFTokenContext(token) {
3749
+ const raw = decodeJwtPayload(token);
3750
+ if (!raw) return null;
3751
+ return {
3752
+ type: typeof raw["typ"] === "string" ? raw["typ"] : void 0,
3753
+ contextIdentifierType: typeof raw["cit"] === "string" ? raw["cit"] : void 0,
3754
+ contextIdentifierValue: typeof raw["civ"] === "string" ? raw["civ"] : void 0,
3755
+ authMethod: typeof raw["aum"] === "string" ? raw["aum"] : void 0,
3756
+ permissions: tryParseJsonArray(raw["per"]),
3757
+ subjectDetails: tryParseJson(raw["sud"]),
3758
+ authorSubjectIdentifier: tryParseJson(raw["asi"]),
3759
+ issuedAt: typeof raw["iat"] === "number" ? raw["iat"] : void 0,
3760
+ expiresAt: typeof raw["exp"] === "number" ? raw["exp"] : void 0
3761
+ };
3762
+ }
3763
+ var init_jwt = __esm({
3764
+ "src/utils/jwt.ts"() {
3765
+ "use strict";
3766
+ }
3767
+ });
3768
+
3453
3769
  // src/services/tokens.ts
3454
- var TokenService;
3770
+ function toTokenAuthorIdentifierType(value) {
3771
+ return TOKEN_AUTHOR_IDENTIFIER_TYPES.has(value) ? value : void 0;
3772
+ }
3773
+ var TOKEN_AUTHOR_IDENTIFIER_TYPES, TokenService;
3455
3774
  var init_tokens = __esm({
3456
3775
  "src/services/tokens.ts"() {
3457
3776
  "use strict";
3458
3777
  init_rest_request();
3459
3778
  init_routes();
3779
+ init_jwt();
3780
+ init_ksef_api_error();
3781
+ init_ksef_error();
3782
+ TOKEN_AUTHOR_IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
3783
+ "Nip",
3784
+ "Pesel",
3785
+ "Fingerprint"
3786
+ ]);
3460
3787
  TokenService = class {
3461
3788
  restClient;
3462
3789
  constructor(restClient) {
@@ -3491,6 +3818,73 @@ var init_tokens = __esm({
3491
3818
  const req = RestRequest.delete(Routes.Tokens.byReference(ref));
3492
3819
  await this.restClient.executeVoid(req);
3493
3820
  }
3821
+ /**
3822
+ * Resolves the reference number of the token currently in use for authentication.
3823
+ * The only JWT payload field treated as authoritative is the KSeF-specific `trn`
3824
+ * (token reference number). Standard RFC 7519 claims such as `jti` are NOT a safe
3825
+ * fallback — a `jti` that differs from the KSeF reference would cause a DELETE to
3826
+ * hit a non-existent path, which `revokeSelf` treats as already-revoked, falsely
3827
+ * reporting success while leaving the token active on the server. When `trn` is
3828
+ * absent, we fall back to `GET /tokens` filtered by author and context; requires
3829
+ * exactly one active match and returns undefined when ambiguous.
3830
+ */
3831
+ async findSelfReferenceNumber(accessToken) {
3832
+ if (!accessToken) return void 0;
3833
+ const payload = decodeJwtPayload(accessToken);
3834
+ if (payload && typeof payload["trn"] === "string" && payload["trn"].length > 0) {
3835
+ return payload["trn"];
3836
+ }
3837
+ const ctx = parseKSeFTokenContext(accessToken);
3838
+ const author = ctx?.authorSubjectIdentifier;
3839
+ if (!author?.type || !author.value) return void 0;
3840
+ if (!ctx?.contextIdentifierType || !ctx?.contextIdentifierValue) return void 0;
3841
+ const authorType = toTokenAuthorIdentifierType(author.type);
3842
+ if (!authorType) return void 0;
3843
+ let continuationToken;
3844
+ let match;
3845
+ do {
3846
+ const list = await this.queryTokens({
3847
+ status: ["Active"],
3848
+ authorIdentifier: author.value,
3849
+ authorIdentifierType: authorType,
3850
+ pageSize: 50,
3851
+ continuationToken
3852
+ });
3853
+ for (const t of list.tokens) {
3854
+ if (t.status === "Active" && t.contextIdentifier?.value === ctx.contextIdentifierValue && t.contextIdentifier?.type === ctx.contextIdentifierType) {
3855
+ if (match) return void 0;
3856
+ match = t.referenceNumber;
3857
+ }
3858
+ }
3859
+ continuationToken = list.continuationToken ?? void 0;
3860
+ } while (continuationToken);
3861
+ return match;
3862
+ }
3863
+ /**
3864
+ * Revokes the token currently used for authentication.
3865
+ * Treats 404/409/410 on DELETE as "already revoked" and returns successfully with
3866
+ * `alreadyRevoked: true` so callers can still clear local state.
3867
+ */
3868
+ async revokeSelf(opts = {}) {
3869
+ let ref = opts.referenceNumber;
3870
+ if (!ref && opts.accessToken) {
3871
+ ref = await this.findSelfReferenceNumber(opts.accessToken);
3872
+ }
3873
+ if (!ref) {
3874
+ throw new KSeFError(
3875
+ "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."
3876
+ );
3877
+ }
3878
+ try {
3879
+ await this.revokeToken(ref);
3880
+ return { referenceNumber: ref, alreadyRevoked: false };
3881
+ } catch (err) {
3882
+ if (err instanceof KSeFApiError && (err.statusCode === 404 || err.statusCode === 409 || err.statusCode === 410)) {
3883
+ return { referenceNumber: ref, alreadyRevoked: true };
3884
+ }
3885
+ throw err;
3886
+ }
3887
+ }
3494
3888
  };
3495
3889
  }
3496
3890
  });
@@ -4119,8 +4513,8 @@ function computeRootDigest(doc) {
4119
4513
  return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
4120
4514
  }
4121
4515
  function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
4122
- const parser = new DOMParser2();
4123
- const qpDoc = parser.parseFromString(qualifyingPropertiesXml, "text/xml");
4516
+ const parser2 = new DOMParser2();
4517
+ const qpDoc = parser2.parseFromString(qualifyingPropertiesXml, "text/xml");
4124
4518
  const signedProps = findElementByLocalName(qpDoc.documentElement, "SignedProperties");
4125
4519
  if (!signedProps) {
4126
4520
  throw new Error("SignedProperties element not found in QualifyingProperties");
@@ -4272,8 +4666,8 @@ var init_signature_service = __esm({
4272
4666
  const isEc = privateKey.asymmetricKeyType === "ec";
4273
4667
  const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
4274
4668
  const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
4275
- const parser = new DOMParser2();
4276
- const doc = parser.parseFromString(xml, "text/xml");
4669
+ const parser2 = new DOMParser2();
4670
+ const doc = parser2.parseFromString(xml, "text/xml");
4277
4671
  const root = doc.documentElement;
4278
4672
  if (!root) {
4279
4673
  throw new Error("XML document has no root element");
@@ -4293,7 +4687,7 @@ var init_signature_service = __esm({
4293
4687
  rootDigest,
4294
4688
  signedPropertiesDigest
4295
4689
  );
4296
- const signedInfoDoc = parser.parseFromString(signedInfoXml, "text/xml");
4690
+ const signedInfoDoc = parser2.parseFromString(signedInfoXml, "text/xml");
4297
4691
  const canonicalSignedInfo = canonicalize(signedInfoDoc.documentElement);
4298
4692
  const signatureValue = computeSignatureValue(
4299
4693
  canonicalSignedInfo,
@@ -4306,7 +4700,7 @@ var init_signature_service = __esm({
4306
4700
  certBase64,
4307
4701
  qualifyingPropertiesXml
4308
4702
  );
4309
- const signatureDoc = parser.parseFromString(signatureXml, "text/xml");
4703
+ const signatureDoc = parser2.parseFromString(signatureXml, "text/xml");
4310
4704
  const importedNode = doc.importNode(signatureDoc.documentElement, true);
4311
4705
  root.appendChild(importedNode);
4312
4706
  return new XMLSerializer().serializeToString(doc);
@@ -5215,6 +5609,7 @@ var PERMISSION_DESCRIPTION_MAX_LENGTH = 256;
5215
5609
  init_xml_to_object();
5216
5610
  init_schema_registry();
5217
5611
  init_invoice_validator();
5612
+ init_char_validity();
5218
5613
 
5219
5614
  // src/models/index.ts
5220
5615
  init_document_structures();
@@ -5906,51 +6301,7 @@ function escapeXml2(str) {
5906
6301
 
5907
6302
  // src/utils/index.ts
5908
6303
  init_zip();
5909
-
5910
- // src/utils/jwt.ts
5911
- function decodeJwtPayload(token) {
5912
- const parts = token.split(".");
5913
- if (parts.length !== 3) return null;
5914
- try {
5915
- const payload = parts[1];
5916
- const json = Buffer.from(payload, "base64url").toString("utf-8");
5917
- return JSON.parse(json);
5918
- } catch {
5919
- return null;
5920
- }
5921
- }
5922
- function tryParseJson(value) {
5923
- if (typeof value !== "string") return void 0;
5924
- try {
5925
- return JSON.parse(value);
5926
- } catch {
5927
- return void 0;
5928
- }
5929
- }
5930
- function tryParseJsonArray(value) {
5931
- if (typeof value !== "string") return void 0;
5932
- try {
5933
- const parsed = JSON.parse(value);
5934
- return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
5935
- } catch {
5936
- return void 0;
5937
- }
5938
- }
5939
- function parseKSeFTokenContext(token) {
5940
- const raw = decodeJwtPayload(token);
5941
- if (!raw) return null;
5942
- return {
5943
- type: typeof raw["typ"] === "string" ? raw["typ"] : void 0,
5944
- contextIdentifierType: typeof raw["cit"] === "string" ? raw["cit"] : void 0,
5945
- contextIdentifierValue: typeof raw["civ"] === "string" ? raw["civ"] : void 0,
5946
- authMethod: typeof raw["aum"] === "string" ? raw["aum"] : void 0,
5947
- permissions: tryParseJsonArray(raw["per"]),
5948
- subjectDetails: tryParseJson(raw["sud"]),
5949
- authorSubjectIdentifier: tryParseJson(raw["asi"]),
5950
- issuedAt: typeof raw["iat"] === "number" ? raw["iat"] : void 0,
5951
- expiresAt: typeof raw["exp"] === "number" ? raw["exp"] : void 0
5952
- };
5953
- }
6304
+ init_jwt();
5954
6305
 
5955
6306
  // src/utils/hash.ts
5956
6307
  import crypto6 from "crypto";
@@ -6146,6 +6497,524 @@ function nonEmptyString(value) {
6146
6497
  return typeof value === "string" && value.length > 0 ? value : void 0;
6147
6498
  }
6148
6499
 
6500
+ // src/xml/xml-engine.ts
6501
+ import { XMLBuilder, XMLParser as XMLParser3 } from "fast-xml-parser";
6502
+ var XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>\n';
6503
+ var parser = new XMLParser3({
6504
+ ignoreAttributes: false,
6505
+ preserveOrder: true,
6506
+ attributeNamePrefix: "@_",
6507
+ textNodeName: "#text",
6508
+ allowBooleanAttributes: true,
6509
+ // Preserve leading zeros and keep everything as strings — KSeF fields like
6510
+ // KRS (`\d{10}`) and NIP (`\d{10}`) would otherwise be lossy through parse.
6511
+ parseTagValue: false,
6512
+ parseAttributeValue: false,
6513
+ trimValues: false
6514
+ });
6515
+ var builder = new XMLBuilder({
6516
+ ignoreAttributes: false,
6517
+ preserveOrder: true,
6518
+ attributeNamePrefix: "@_",
6519
+ textNodeName: "#text",
6520
+ format: false,
6521
+ suppressBooleanAttributes: false,
6522
+ suppressEmptyNode: false,
6523
+ processEntities: true
6524
+ });
6525
+ function createObjectBuilder(pretty = false) {
6526
+ return new XMLBuilder({
6527
+ ignoreAttributes: false,
6528
+ preserveOrder: false,
6529
+ attributeNamePrefix: "@_",
6530
+ textNodeName: "#text",
6531
+ format: pretty,
6532
+ suppressBooleanAttributes: false,
6533
+ suppressEmptyNode: false,
6534
+ processEntities: true
6535
+ });
6536
+ }
6537
+ function prependDeclaration(xml) {
6538
+ return xml.startsWith("<?xml") ? xml : `${XML_DECLARATION}${xml}`;
6539
+ }
6540
+ function parseXml(xml) {
6541
+ return parser.parse(xml);
6542
+ }
6543
+ function buildXml(document) {
6544
+ return prependDeclaration(builder.build(document));
6545
+ }
6546
+ function buildXmlFromObject(document, options) {
6547
+ return prependDeclaration(createObjectBuilder(options?.pretty).build(document));
6548
+ }
6549
+ function stripBom(input) {
6550
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
6551
+ }
6552
+
6553
+ // src/xml/order-map.ts
6554
+ var ORDER_MAP = {
6555
+ Faktura: ["Naglowek", "Podmiot1", "Podmiot2", "Podmiot3", "Fa", "Stopka"],
6556
+ Naglowek: ["KodFormularza", "WariantFormularza", "DataWytworzeniaFa", "SystemInfo"],
6557
+ Podmiot1: [
6558
+ "PrefiksPodatnika",
6559
+ "NrEORI",
6560
+ "DaneIdentyfikacyjne",
6561
+ "Adres",
6562
+ "AdresKoresp",
6563
+ "DaneKontaktowe",
6564
+ "StatusInfoPodatnika"
6565
+ ],
6566
+ Podmiot2: [
6567
+ "NrEORI",
6568
+ "DaneIdentyfikacyjne",
6569
+ "Adres",
6570
+ "AdresKoresp",
6571
+ "DaneKontaktowe",
6572
+ "NrKlienta",
6573
+ "IDNabywcy",
6574
+ "JST",
6575
+ "GV"
6576
+ ],
6577
+ Podmiot3: [
6578
+ "IDNabywcy",
6579
+ "NrEORI",
6580
+ "DaneIdentyfikacyjne",
6581
+ "Adres",
6582
+ "AdresKoresp",
6583
+ "DaneKontaktowe",
6584
+ "Rola",
6585
+ "Udzial"
6586
+ ],
6587
+ DaneIdentyfikacyjne: [
6588
+ "NIP",
6589
+ "IDWew",
6590
+ "KodUE",
6591
+ "NrVatUE",
6592
+ "KodKraju",
6593
+ "NrID",
6594
+ "BrakID",
6595
+ "Nazwa",
6596
+ "Identyfikator",
6597
+ "KRS"
6598
+ ],
6599
+ Adres: ["KodKraju", "AdresL1", "AdresL2", "AdresL3"],
6600
+ DaneKontaktowe: ["Email", "Telefon"],
6601
+ Fa: [
6602
+ "KodWaluty",
6603
+ "P_1",
6604
+ "P_1M",
6605
+ "P_2",
6606
+ "WZ",
6607
+ "P_6",
6608
+ "OkresFa",
6609
+ // Multi-rate interleave per VAT group — DO NOT flatten into P_13_* block then P_14_* block.
6610
+ // See smekcio TS d1ec8fe and the "multi-rate interleave" regression test.
6611
+ "P_13_1",
6612
+ "P_14_1",
6613
+ "P_14_1W",
6614
+ "P_13_2",
6615
+ "P_14_2",
6616
+ "P_14_2W",
6617
+ "P_13_3",
6618
+ "P_14_3",
6619
+ "P_14_3W",
6620
+ "P_13_4",
6621
+ "P_14_4",
6622
+ "P_14_4W",
6623
+ "P_13_5",
6624
+ "P_14_5",
6625
+ "P_13_6_1",
6626
+ "P_13_6_2",
6627
+ "P_13_6_3",
6628
+ "P_13_7",
6629
+ "P_13_8",
6630
+ "P_13_9",
6631
+ "P_13_10",
6632
+ "P_13_11",
6633
+ "P_15",
6634
+ "KursWalutyZ",
6635
+ "Adnotacje",
6636
+ "RodzajFaktury",
6637
+ "PrzyczynaKorekty",
6638
+ "TypKorekty",
6639
+ "DaneFaKorygowanej",
6640
+ "OkresFaKorygowanej",
6641
+ "NrFaKorygowany",
6642
+ "Podmiot1K",
6643
+ "Podmiot2K",
6644
+ "Podmiot3K",
6645
+ "ZaliczkaCzesciowa",
6646
+ "FP",
6647
+ "TP",
6648
+ "DodatkowyOpis",
6649
+ "FakturaZaliczkowa",
6650
+ "ZwrotAkcyzy",
6651
+ "FaWiersz",
6652
+ "FaWiersze",
6653
+ "Rozliczenie",
6654
+ "Platnosc"
6655
+ ],
6656
+ Adnotacje: ["P_16", "P_17", "P_18", "P_18A", "Zwolnienie", "NoweSrodkiTransportu", "P_23", "PMarzy"],
6657
+ OkresFa: ["P_6_Od", "P_6_Do"],
6658
+ FaWiersz: [
6659
+ "NrWierszaFa",
6660
+ "UU_ID",
6661
+ "P_6A",
6662
+ "P_7",
6663
+ "Indeks",
6664
+ "GTIN",
6665
+ "PKWiU",
6666
+ "CN",
6667
+ "PKOB",
6668
+ "P_8A",
6669
+ "P_8B",
6670
+ "P_9A",
6671
+ "P_9B",
6672
+ "P_10",
6673
+ "P_11",
6674
+ "P_11A",
6675
+ "P_11Vat",
6676
+ "P_12",
6677
+ "P_12_XII",
6678
+ "P_12_Zal_15",
6679
+ "KwotaAkcyzy",
6680
+ "GTU",
6681
+ "Procedura",
6682
+ "KursWaluty",
6683
+ "StanPrzed"
6684
+ ]
6685
+ };
6686
+ function comparePKey(a, b) {
6687
+ const normalize = (value) => value.replace(/^P_/, "").split("_").map((part) => Number.isNaN(Number(part)) ? part : Number(part));
6688
+ const aParts = normalize(a);
6689
+ const bParts = normalize(b);
6690
+ const max = Math.max(aParts.length, bParts.length);
6691
+ for (let i = 0; i < max; i += 1) {
6692
+ const left = aParts[i];
6693
+ const right = bParts[i];
6694
+ if (left === void 0) return -1;
6695
+ if (right === void 0) return 1;
6696
+ if (typeof left === "number" && typeof right === "number") {
6697
+ if (left !== right) return left - right;
6698
+ continue;
6699
+ }
6700
+ const leftStr = String(left);
6701
+ const rightStr = String(right);
6702
+ if (leftStr !== rightStr) return leftStr < rightStr ? -1 : 1;
6703
+ }
6704
+ return 0;
6705
+ }
6706
+ function isObject(value) {
6707
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6708
+ }
6709
+ function normalizeValueForKey(key, value) {
6710
+ if (Array.isArray(value)) {
6711
+ return value.map(
6712
+ (item) => isObject(item) ? orderXmlObject(item, key) : normalizeValue(item)
6713
+ );
6714
+ }
6715
+ if (isObject(value)) return orderXmlObject(value, key);
6716
+ return value;
6717
+ }
6718
+ function normalizeValue(value) {
6719
+ if (Array.isArray(value)) return value.map((item) => normalizeValue(item));
6720
+ if (isObject(value)) return orderXmlObject(value);
6721
+ return value;
6722
+ }
6723
+ function orderXmlObject(value, contextKey) {
6724
+ const order = contextKey ? ORDER_MAP[contextKey] : void 0;
6725
+ const keys = Object.keys(value);
6726
+ const used = /* @__PURE__ */ new Set();
6727
+ const ordered = {};
6728
+ if (order) {
6729
+ for (const key of order) {
6730
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
6731
+ const item = value[key];
6732
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6733
+ used.add(key);
6734
+ }
6735
+ }
6736
+ }
6737
+ const pKeys = keys.filter((key) => !used.has(key) && key.startsWith("P_")).sort(comparePKey);
6738
+ for (const key of pKeys) {
6739
+ const item = value[key];
6740
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6741
+ used.add(key);
6742
+ }
6743
+ for (const key of keys) {
6744
+ if (used.has(key)) continue;
6745
+ const item = value[key];
6746
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6747
+ }
6748
+ return ordered;
6749
+ }
6750
+
6751
+ // src/xml/faktura-builder.ts
6752
+ var FAKTURA_NAMESPACE = {
6753
+ FA2: "http://crd.gov.pl/wzor/2023/06/29/12648/",
6754
+ FA3: "http://crd.gov.pl/wzor/2025/06/25/13775/"
6755
+ };
6756
+ var ETD_NAMESPACE = {
6757
+ FA2: "http://crd.gov.pl/xml/schematy/2020/10/08/eDokumenty",
6758
+ FA3: "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2022/01/05/eD/DefinicjeTypy/"
6759
+ };
6760
+ function toKodFormularza(formCode) {
6761
+ return {
6762
+ "@_kodSystemowy": formCode.systemCode,
6763
+ "@_wersjaSchemy": formCode.schemaVersion,
6764
+ "#text": formCode.value
6765
+ };
6766
+ }
6767
+ function isFormCodeShape(value) {
6768
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
6769
+ const candidate = value;
6770
+ return typeof candidate.systemCode === "string" && typeof candidate.schemaVersion === "string" && typeof candidate.value === "string";
6771
+ }
6772
+ function isObject2(value) {
6773
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6774
+ }
6775
+ function normalizeTopLevelChild(key, value) {
6776
+ if (key === "Naglowek" && isObject2(value)) {
6777
+ return normalizeNaglowek(value);
6778
+ }
6779
+ if (Array.isArray(value)) {
6780
+ return value.map((item) => isObject2(item) ? orderXmlObject(item, key) : item);
6781
+ }
6782
+ if (isObject2(value)) return orderXmlObject(value, key);
6783
+ return value;
6784
+ }
6785
+ function normalizeNaglowek(value) {
6786
+ const result = {};
6787
+ for (const [key, item] of Object.entries(value)) {
6788
+ if (item === void 0) continue;
6789
+ if (key === "KodFormularza" && isFormCodeShape(item)) {
6790
+ result[key] = toKodFormularza(item);
6791
+ continue;
6792
+ }
6793
+ if (Array.isArray(item)) {
6794
+ result[key] = item.map(
6795
+ (entry) => isObject2(entry) ? orderXmlObject(entry, key) : entry
6796
+ );
6797
+ continue;
6798
+ }
6799
+ if (isObject2(item)) {
6800
+ result[key] = orderXmlObject(item, key);
6801
+ continue;
6802
+ }
6803
+ result[key] = item;
6804
+ }
6805
+ return result;
6806
+ }
6807
+ function normalizeTopLevel(input) {
6808
+ const result = {};
6809
+ for (const [key, value] of Object.entries(input)) {
6810
+ if (value === void 0) continue;
6811
+ result[key] = normalizeTopLevelChild(key, value);
6812
+ }
6813
+ return result;
6814
+ }
6815
+ function buildFakturaXml(faktura, options = {}) {
6816
+ const schema = options.schema ?? "FA3";
6817
+ const fakturaNamespace = options.fakturaNamespace ?? FAKTURA_NAMESPACE[schema];
6818
+ const etdNamespace = options.etdNamespace ?? ETD_NAMESPACE[schema];
6819
+ const normalized = normalizeTopLevel(faktura);
6820
+ const ordered = orderXmlObject(normalized, "Faktura");
6821
+ const document = {
6822
+ Faktura: {
6823
+ ...ordered,
6824
+ "@_xmlns": fakturaNamespace,
6825
+ "@_xmlns:etd": etdNamespace
6826
+ }
6827
+ };
6828
+ return buildXmlFromObject(document, { pretty: options.pretty });
6829
+ }
6830
+ function isFakturaInput(input) {
6831
+ if (!isObject2(input)) return false;
6832
+ const candidate = input;
6833
+ if (!Object.prototype.hasOwnProperty.call(candidate, "Naglowek")) return false;
6834
+ if (!Object.prototype.hasOwnProperty.call(candidate, "Fa")) return false;
6835
+ return isObject2(candidate.Naglowek) && isObject2(candidate.Fa);
6836
+ }
6837
+
6838
+ // src/xml/pef-builder.ts
6839
+ init_ksef_validation_error();
6840
+ var PEF_NAMESPACE = {
6841
+ PEF: "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
6842
+ PEF_KOR: "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
6843
+ };
6844
+ var UBL_EXT_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2";
6845
+ var UBL_CBC_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
6846
+ var UBL_CAC_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
6847
+ var UBL_CBC_PL_NS = "urn:pl:extended:CommonBasicComponents-2";
6848
+ var UBL_CAC_PL_NS = "urn:pl:extended:CommonAggregateComponents-2";
6849
+ function isPefUblDocumentInput(input) {
6850
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return false;
6851
+ const obj = input;
6852
+ const invoice = obj.Invoice;
6853
+ const creditNote = obj.CreditNote;
6854
+ const hasInvoice = typeof invoice === "object" && invoice !== null && !Array.isArray(invoice);
6855
+ const hasCreditNote = typeof creditNote === "object" && creditNote !== null && !Array.isArray(creditNote);
6856
+ return hasInvoice !== hasCreditNote;
6857
+ }
6858
+ function inferSchema(input) {
6859
+ return "Invoice" in input ? "PEF" : "PEF_KOR";
6860
+ }
6861
+ function isNonArrayObject(value) {
6862
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6863
+ }
6864
+ function assertPefShape(input) {
6865
+ if (!isNonArrayObject(input)) {
6866
+ throw new KSeFValidationError("PEF input must be a non-array object.");
6867
+ }
6868
+ const hasInvoiceKey = "Invoice" in input;
6869
+ const hasCreditNoteKey = "CreditNote" in input;
6870
+ if (hasInvoiceKey && hasCreditNoteKey) {
6871
+ throw new KSeFValidationError(
6872
+ "PEF input must contain exactly one of `Invoice` or `CreditNote`, not both."
6873
+ );
6874
+ }
6875
+ if (!hasInvoiceKey && !hasCreditNoteKey) {
6876
+ throw new KSeFValidationError(
6877
+ "PEF input must contain either an `Invoice` or a `CreditNote` root element."
6878
+ );
6879
+ }
6880
+ const rootKey = hasInvoiceKey ? "Invoice" : "CreditNote";
6881
+ if (!isNonArrayObject(input[rootKey])) {
6882
+ throw new KSeFValidationError(
6883
+ `PEF \`${rootKey}\` value must be a non-array object.`
6884
+ );
6885
+ }
6886
+ }
6887
+ function buildPefXml(input, options = {}) {
6888
+ assertPefShape(input);
6889
+ const inferred = inferSchema(input);
6890
+ const schema = options.schema ?? input.schema ?? inferred;
6891
+ if (schema !== inferred) {
6892
+ throw new KSeFValidationError(
6893
+ `PEF schema mismatch: expected ${inferred} based on root element, got ${schema}.`
6894
+ );
6895
+ }
6896
+ const commonNamespaces = {
6897
+ "@_xmlns:ext": UBL_EXT_NS,
6898
+ "@_xmlns:cbc": UBL_CBC_NS,
6899
+ "@_xmlns:cac": UBL_CAC_NS,
6900
+ "@_xmlns:cbc-pl": UBL_CBC_PL_NS,
6901
+ "@_xmlns:cac-pl": UBL_CAC_PL_NS
6902
+ };
6903
+ const document = "Invoice" in input ? {
6904
+ Invoice: {
6905
+ ...input.Invoice,
6906
+ "@_xmlns": PEF_NAMESPACE.PEF,
6907
+ ...commonNamespaces
6908
+ }
6909
+ } : {
6910
+ CreditNote: {
6911
+ ...input.CreditNote,
6912
+ "@_xmlns": PEF_NAMESPACE.PEF_KOR,
6913
+ ...commonNamespaces
6914
+ }
6915
+ };
6916
+ return buildXmlFromObject(document, { pretty: options.pretty });
6917
+ }
6918
+
6919
+ // src/xml/invoice-serializer.ts
6920
+ init_ksef_validation_error();
6921
+ var FAKTURA_SCHEMAS = /* @__PURE__ */ new Set(["FA2", "FA3"]);
6922
+ var PEF_SCHEMAS = /* @__PURE__ */ new Set(["PEF", "PEF_KOR"]);
6923
+ function isNonArrayObject2(value) {
6924
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6925
+ }
6926
+ function classifyUnknownObject(input) {
6927
+ const looksLikeFaktura = "Naglowek" in input || "Fa" in input || "Podmiot1" in input || "Podmiot2" in input;
6928
+ const hasInvoice = "Invoice" in input;
6929
+ const hasCreditNote = "CreditNote" in input;
6930
+ if (hasInvoice && hasCreditNote) {
6931
+ return new KSeFValidationError(
6932
+ "Input must contain exactly one of `Invoice` or `CreditNote`, not both."
6933
+ );
6934
+ }
6935
+ if (hasInvoice !== hasCreditNote) {
6936
+ const rootKey = hasInvoice ? "Invoice" : "CreditNote";
6937
+ if (!isNonArrayObject2(input[rootKey])) {
6938
+ return KSeFValidationError.fromField(
6939
+ rootKey,
6940
+ `PEF \`${rootKey}\` value must be a non-array object.`
6941
+ );
6942
+ }
6943
+ }
6944
+ if (looksLikeFaktura) {
6945
+ const missing = [];
6946
+ if (!("Naglowek" in input)) missing.push("Naglowek");
6947
+ if (!("Fa" in input)) missing.push("Fa");
6948
+ if (missing.length > 0) {
6949
+ return KSeFValidationError.fromField(
6950
+ missing[0],
6951
+ `Faktura input is missing required top-level key(s): ${missing.join(", ")}.`
6952
+ );
6953
+ }
6954
+ for (const key of ["Naglowek", "Fa"]) {
6955
+ if (!isNonArrayObject2(input[key])) {
6956
+ return KSeFValidationError.fromField(
6957
+ key,
6958
+ `Faktura \`${key}\` value must be a non-null, non-array object.`
6959
+ );
6960
+ }
6961
+ }
6962
+ return new KSeFValidationError(
6963
+ "Faktura-like input failed shape validation: `Naglowek` and `Fa` must be own enumerable properties on the input object."
6964
+ );
6965
+ }
6966
+ return new KSeFValidationError(
6967
+ "Unsupported invoice input shape: expected `FakturaInput` (with `Naglowek` + `Fa`) or `PefUblDocumentInput` (with `Invoice` or `CreditNote`)."
6968
+ );
6969
+ }
6970
+ function serializeInvoiceXml(input, options) {
6971
+ if (Buffer.isBuffer(input)) return input;
6972
+ if (typeof input === "string") {
6973
+ return Buffer.from(stripBom(input), "utf8");
6974
+ }
6975
+ if (Array.isArray(input)) {
6976
+ return Buffer.from(stripBom(buildXml(input)), "utf8");
6977
+ }
6978
+ if (input && typeof input === "object") {
6979
+ const schema = options?.schema;
6980
+ if (isPefUblDocumentInput(input)) {
6981
+ if (schema && !PEF_SCHEMAS.has(schema)) {
6982
+ throw new KSeFValidationError(
6983
+ `schema option ${schema} is not compatible with a PEF / PEF_KOR input.`
6984
+ );
6985
+ }
6986
+ const pefSchema = schema === "PEF" || schema === "PEF_KOR" ? schema : void 0;
6987
+ const xml = buildPefXml(input, {
6988
+ schema: pefSchema,
6989
+ pretty: options?.pretty
6990
+ });
6991
+ return Buffer.from(stripBom(xml), "utf8");
6992
+ }
6993
+ if (isFakturaInput(input)) {
6994
+ if (schema && !FAKTURA_SCHEMAS.has(schema)) {
6995
+ throw new KSeFValidationError(
6996
+ `schema option ${schema} is not compatible with a Faktura input.`
6997
+ );
6998
+ }
6999
+ const fakturaSchema = schema === "FA2" || schema === "FA3" ? schema : void 0;
7000
+ const xml = buildFakturaXml(input, {
7001
+ schema: fakturaSchema,
7002
+ fakturaNamespace: options?.fakturaNamespace,
7003
+ etdNamespace: options?.etdNamespace,
7004
+ pretty: options?.pretty
7005
+ });
7006
+ return Buffer.from(stripBom(xml), "utf8");
7007
+ }
7008
+ throw classifyUnknownObject(input);
7009
+ }
7010
+ throw new KSeFValidationError(
7011
+ "Unsupported invoice input type: expected Buffer, string, XmlDocument, FakturaInput, or PefUblDocumentInput."
7012
+ );
7013
+ }
7014
+ function buildRawXmlString(document, options) {
7015
+ return buildXmlFromObject(document, options);
7016
+ }
7017
+
6149
7018
  // src/workflows/online-session-workflow.ts
6150
7019
  init_invoice_validator();
6151
7020
  init_ksef_validation_error();
@@ -6874,10 +7743,13 @@ export {
6874
7743
  CertificateService,
6875
7744
  CryptographyService,
6876
7745
  DEFAULT_FORM_CODE,
7746
+ DISCOURAGED_UNICODE_RANGES,
6877
7747
  DefaultAuthManager,
6878
7748
  ENFORCE_XADES_COMPLIANCE,
7749
+ ETD_NAMESPACE,
6879
7750
  EntityPermissionGrantBuilder,
6880
7751
  Environment,
7752
+ FAKTURA_NAMESPACE,
6881
7753
  FORM_CODES,
6882
7754
  FORM_CODE_KEYS,
6883
7755
  FileHwmStore,
@@ -6894,6 +7766,7 @@ export {
6894
7766
  KSEF_FEATURE_HEADER,
6895
7767
  KSeFApiError,
6896
7768
  KSeFAuthStatusError,
7769
+ KSeFBadRequestError,
6897
7770
  KSeFBatchTimeoutError,
6898
7771
  KSeFClient,
6899
7772
  KSeFError,
@@ -6911,8 +7784,10 @@ export {
6911
7784
  LimitsService,
6912
7785
  Nip,
6913
7786
  NipVatUe,
7787
+ ORDER_MAP,
6914
7788
  OfflineInvoiceWorkflow,
6915
7789
  OnlineSessionService,
7790
+ PEF_NAMESPACE,
6916
7791
  PERMISSION_DESCRIPTION_MAX_LENGTH,
6917
7792
  PERMISSION_DESCRIPTION_MIN_LENGTH,
6918
7793
  PeppolId,
@@ -6942,14 +7817,21 @@ export {
6942
7817
  VatUe,
6943
7818
  VerificationLinkService,
6944
7819
  addBusinessDays,
7820
+ assertNever,
6945
7821
  authenticateWithCertificate,
6946
7822
  authenticateWithExternalSignature,
6947
7823
  authenticateWithPkcs12,
6948
7824
  authenticateWithToken,
6949
7825
  batchValidationDetails,
7826
+ buildFakturaXml,
7827
+ buildPefXml,
7828
+ buildRawXmlString,
6950
7829
  buildUnsignedAuthTokenRequestXml,
7830
+ buildXml,
7831
+ buildXmlFromObject,
6951
7832
  calculateBackoff,
6952
7833
  calculateOfflineDeadline,
7834
+ comparePKey,
6953
7835
  createZip,
6954
7836
  decodeJwtPayload,
6955
7837
  deduplicateByKsefNumber,
@@ -6968,6 +7850,9 @@ export {
6968
7850
  getTimeUntilDeadline,
6969
7851
  incrementalExportAndDownload,
6970
7852
  isExpired,
7853
+ isFakturaInput,
7854
+ isFormCodeShape,
7855
+ isPefUblDocumentInput,
6971
7856
  isPolishHoliday,
6972
7857
  isRetryableError,
6973
7858
  isRetryableStatus,
@@ -6989,16 +7874,21 @@ export {
6989
7874
  nextBusinessDay,
6990
7875
  openOnlineSession,
6991
7876
  openSendAndClose,
7877
+ orderXmlObject,
6992
7878
  parseFormCode,
6993
7879
  parseKSeFTokenContext,
6994
7880
  parseRetryAfter,
6995
7881
  parseUpoXml,
7882
+ parseXml,
6996
7883
  pollUntil,
6997
7884
  resolveOptions,
6998
7885
  resumeOnlineSession,
6999
7886
  runWithConcurrency,
7887
+ serializeInvoiceXml,
7000
7888
  sha256Base642 as sha256Base64,
7001
7889
  sleep,
7890
+ stripBom,
7891
+ toKodFormularza,
7002
7892
  unzip,
7003
7893
  updateContinuationPoint,
7004
7894
  uploadBatch,
@@ -7008,6 +7898,7 @@ export {
7008
7898
  validate,
7009
7899
  validateBatch,
7010
7900
  validateBusinessRules,
7901
+ validateCharValidity,
7011
7902
  validateFormCodeForSession,
7012
7903
  validatePresignedUrl,
7013
7904
  validateSchema,