@beliq/sdk 0.4.2 → 0.4.5

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/CHANGELOG.md CHANGED
@@ -4,6 +4,67 @@
4
4
  resolves 0.4.x and never reaches 0.5.0. Additive spec syncs ship as patches for
5
5
  that reason, and a minor is reserved for a change that needs consumers to opt in.
6
6
 
7
+ ## 0.4.5 - 2026-10-03
8
+
9
+ - `LIVE_GENERATE_STANDARDS` carries all eight standards `POST /v1/generate`
10
+ accepts, where it had carried four. The four added are the national XSD
11
+ formats: `fatturapa`, `facturae`, `eslog` and `ksef`. Each is Schema-checked,
12
+ meaning structure only and no business rules, because its authority publishes
13
+ no machine-readable rule pack, and `GET /v1/rulesets` carries the badge.
14
+ `LIVE_PROFILES_BY_STANDARD` gains the one profile each allows: `ordinaria`
15
+ for `fatturapa` and `facturae`, `eracun` for `eslog`, `fa3` for `ksef`. The
16
+ map stays narrower than the engine in one place, the Factur-X `minimum` and
17
+ `basic` profiles, for FNFE-MPE source gating. `LIVE_GENERATE_PRESETS` is
18
+ unchanged at five entries: it mirrors what beliq.eu's own generator offers.
19
+ - The vendored `openapi.json` carries the corrected `/v1/validate` description.
20
+ It had said that matching a verdict's `rulesetArtifacts` rows against the
21
+ `GET /v1/rulesets` catalog covers publicly-supported formats only, and that a
22
+ national format's components are kept off the catalog. Both were false: the
23
+ catalog publishes every format beliq carries and the component rows each
24
+ ruleset is built from.
25
+
26
+ ## 0.4.4 - 2026-10-02
27
+
28
+ - Invoices carry additional supporting documents (BG-24) as
29
+ `supportingDocuments`, at most 50 of them: `id` (BT-122), which BR-52
30
+ requires, `description` (BT-123), `externalLocation` (BT-124) and
31
+ `attachment` (BT-125) with the file as base64 `content`, its `mimeCode` and
32
+ its `filename`. An entry can carry a URL, a file, both or neither. Output is
33
+ a CII `ram:AdditionalReferencedDocument` with type code 916, from the
34
+ Factur-X EN16931 profile up, and a UBL `cac:AdditionalDocumentReference`
35
+ with no document type code (UBL-SR-43 admits none here). Factur-X MINIMUM,
36
+ BASIC_WL and BASIC have no slot for it and drop it after the same checks, as
37
+ do the fatturapa, facturae, eslog and ksef targets. Content that is not
38
+ base64, or that decodes to no bytes, is a 400. On XRechnung BR-DE-22 refuses
39
+ two attachments sharing a `filename`, and DE-R-022 does the same on Peppol
40
+ BIS between two German parties; both compare names as written, so names
41
+ differing only in case pass. An attachment counts toward the 1 MiB body
42
+ limit of `POST /v1/generate`, and base64 takes four bytes for every three of
43
+ the file.
44
+ - The `format` query parameter of `/v1/parse` now describes itself: it is
45
+ checked against the allowed values and otherwise ignored, because the syntax
46
+ is always read from the document itself. `/v1/parse` shares the invoice
47
+ shape and fills neither `supportingDocuments` nor the fields 0.4.3 added.
48
+
49
+ ## 0.4.3 - 2026-09-26
50
+
51
+ Never published to npm: the release job refused the tag, because `package.json`
52
+ read 0.4.2 at the commit it pointed at. 0.4.4 is the first release that carries
53
+ the changes below.
54
+
55
+ - Invoices can name a payee (BG-10) and a tax representative (BG-11), as
56
+ `payee` and `taxRepresentative`, and state `paidAmount` (BT-113) and
57
+ `roundingAmount` (BT-114), from which the API derives the amount due
58
+ (BT-115). A payee with the seller's name or registration identifier is a
59
+ 400. With a payee, UBL output writes `paymentMeans.creditorId` (BT-90) on
60
+ the payee rather than the seller.
61
+ - `typeCode` (BT-3) sets the document type code within `documentType`, such as
62
+ `384` for a corrected invoice. A code from the other document type's half of
63
+ BR-CL-01 is a 400, and the fatturapa, facturae and eslog targets answer 422
64
+ `DOCUMENT_TYPE_STANDARD_MISMATCH`.
65
+ - `precedingInvoiceReference` (BG-3) is written on invoices as well as credit
66
+ notes. `/v1/parse` shares the invoice shape and fills none of the new fields.
67
+
7
68
  ## 0.4.2 - 2026-09-23
8
69
 
9
70
  - Invoices carry allowances and charges at document level (BG-20, BG-21) and
@@ -63,7 +124,7 @@ that reason, and a minor is reserved for a change that needs consumers to opt in
63
124
  - A per-attempt deadline, and transient failures are retried.
64
125
  - The transport defaults are exported from the package entry point, so a caller
65
126
  can read the timeout and retry values the SDK ships with.
66
- - The vendored `openapi.json` is asserted byte-identical to what beliq-api
127
+ - The vendored `openapi.json` is asserted byte-identical to what the API
67
128
  generates, and the drift check is directional in the code rather than only in
68
129
  its comment. Ten Peppol emit error codes, the 413 responses, the verdict
69
130
  verification tier and the `/v1/me` response shape are typed; two error codes
package/README.md CHANGED
@@ -171,7 +171,7 @@ try {
171
171
  `src/generated/schema.ts` is generated from a vendored copy of the published OpenAPI spec (`openapi.json`).
172
172
 
173
173
  ```bash
174
- npm run sync:spec # refresh openapi.json from beliq-api / the live spec
174
+ npm run sync:spec # refresh openapi.json from the live spec (or BELIQ_OPENAPI_PATH)
175
175
  npm run gen:types # regenerate src/generated/schema.ts
176
176
  npm run openapi:check # CI drift guard: fails if the generated types are stale
177
177
  ```
@@ -20,7 +20,13 @@ declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
20
20
  declare const DEFAULT_TIMEOUT_MS = 90000;
21
21
  /** Extra attempts after the first, for 429 / 502 / 503 only. */
22
22
  declare const DEFAULT_MAX_RETRIES = 3;
23
- declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
23
+ /**
24
+ * Every `standard` POST /v1/generate accepts, in the order its enum lists them.
25
+ * The four national formats are Schema-checked: their authority publishes a
26
+ * schema and no machine-readable business rules, so beliq checks structure and
27
+ * says so. GET /v1/rulesets carries each one's badge.
28
+ */
29
+ declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis", "fatturapa", "facturae", "eslog", "ksef"];
24
30
  /** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
25
31
  interface GeneratePreset {
26
32
  id: string;
@@ -50,16 +56,15 @@ declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extend
50
56
  *
51
57
  * `profile` is not a free enum: the engine pins it per standard and answers a
52
58
  * pair outside the table with `422 PROFILE_STANDARD_MISMATCH`
53
- * (beliq-engine `app/routes/generate.py`, ALLOWED_PROFILES_FOR_STANDARD). A
59
+ * (the engine's ALLOWED_PROFILES_FOR_STANDARD table). A
54
60
  * surface that offers one flat profile list therefore offers values that cannot
55
61
  * succeed: none of the Factur-X granularity values is legal for `xrechnung` or
56
62
  * `peppol-bis`, and `extended-ctc-fr` is the AFNOR XP Z12-012 France CTC overlay
57
63
  * with no ZUGFeRD-branded counterpart.
58
64
  *
59
- * Narrower than the engine's own table in two places, both deliberate: the
60
- * `minimum` and `basic` Factur-X profiles are engine-supported but withheld
61
- * (FNFE-MPE source gating, mirroring beliq-types SUPPORTED_FACTURX_PROFILE_IDS),
62
- * and the standards outside LIVE_GENERATE_STANDARDS are absent entirely.
65
+ * It carries every standard the API accepts. It stays narrower than the
66
+ * engine's table in one place: the `minimum` and `basic` Factur-X profiles are
67
+ * engine-supported but not offered here (FNFE-MPE source gating).
63
68
  *
64
69
  * `scripts/check-profile-drift.mjs` compares this against the engine's table.
65
70
  */
@@ -68,6 +73,10 @@ declare const LIVE_PROFILES_BY_STANDARD: {
68
73
  readonly 'peppol-bis': readonly ["peppol", "romania-ro-cius", "netherlands-nlcius"];
69
74
  readonly zugferd: readonly ["basicwl", "en16931", "extended"];
70
75
  readonly facturx: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
76
+ readonly fatturapa: readonly ["ordinaria"];
77
+ readonly facturae: readonly ["ordinaria"];
78
+ readonly eslog: readonly ["eracun"];
79
+ readonly ksef: readonly ["fa3"];
71
80
  };
72
81
  /** The profiles a caller may choose for `standard`; empty for an unknown standard. */
73
82
  declare function profilesForStandard(standard: string): readonly string[];
@@ -20,7 +20,13 @@ declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
20
20
  declare const DEFAULT_TIMEOUT_MS = 90000;
21
21
  /** Extra attempts after the first, for 429 / 502 / 503 only. */
22
22
  declare const DEFAULT_MAX_RETRIES = 3;
23
- declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
23
+ /**
24
+ * Every `standard` POST /v1/generate accepts, in the order its enum lists them.
25
+ * The four national formats are Schema-checked: their authority publishes a
26
+ * schema and no machine-readable business rules, so beliq checks structure and
27
+ * says so. GET /v1/rulesets carries each one's badge.
28
+ */
29
+ declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis", "fatturapa", "facturae", "eslog", "ksef"];
24
30
  /** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
25
31
  interface GeneratePreset {
26
32
  id: string;
@@ -50,16 +56,15 @@ declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extend
50
56
  *
51
57
  * `profile` is not a free enum: the engine pins it per standard and answers a
52
58
  * pair outside the table with `422 PROFILE_STANDARD_MISMATCH`
53
- * (beliq-engine `app/routes/generate.py`, ALLOWED_PROFILES_FOR_STANDARD). A
59
+ * (the engine's ALLOWED_PROFILES_FOR_STANDARD table). A
54
60
  * surface that offers one flat profile list therefore offers values that cannot
55
61
  * succeed: none of the Factur-X granularity values is legal for `xrechnung` or
56
62
  * `peppol-bis`, and `extended-ctc-fr` is the AFNOR XP Z12-012 France CTC overlay
57
63
  * with no ZUGFeRD-branded counterpart.
58
64
  *
59
- * Narrower than the engine's own table in two places, both deliberate: the
60
- * `minimum` and `basic` Factur-X profiles are engine-supported but withheld
61
- * (FNFE-MPE source gating, mirroring beliq-types SUPPORTED_FACTURX_PROFILE_IDS),
62
- * and the standards outside LIVE_GENERATE_STANDARDS are absent entirely.
65
+ * It carries every standard the API accepts. It stays narrower than the
66
+ * engine's table in one place: the `minimum` and `basic` Factur-X profiles are
67
+ * engine-supported but not offered here (FNFE-MPE source gating).
63
68
  *
64
69
  * `scripts/check-profile-drift.mjs` compares this against the engine's table.
65
70
  */
@@ -68,6 +73,10 @@ declare const LIVE_PROFILES_BY_STANDARD: {
68
73
  readonly 'peppol-bis': readonly ["peppol", "romania-ro-cius", "netherlands-nlcius"];
69
74
  readonly zugferd: readonly ["basicwl", "en16931", "extended"];
70
75
  readonly facturx: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
76
+ readonly fatturapa: readonly ["ordinaria"];
77
+ readonly facturae: readonly ["ordinaria"];
78
+ readonly eslog: readonly ["eracun"];
79
+ readonly ksef: readonly ["fa3"];
71
80
  };
72
81
  /** The profiles a caller may choose for `standard`; empty for an unknown standard. */
73
82
  declare function profilesForStandard(standard: string): readonly string[];
package/dist/helpers.cjs CHANGED
@@ -165,7 +165,16 @@ function buildRequest(params) {
165
165
 
166
166
  // src/constants.ts
167
167
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
168
- var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
168
+ var LIVE_GENERATE_STANDARDS = [
169
+ "xrechnung",
170
+ "zugferd",
171
+ "facturx",
172
+ "peppol-bis",
173
+ "fatturapa",
174
+ "facturae",
175
+ "eslog",
176
+ "ksef"
177
+ ];
169
178
  var LIVE_GENERATE_PRESETS = [
170
179
  { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
171
180
  { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
@@ -178,7 +187,11 @@ var LIVE_PROFILES_BY_STANDARD = {
178
187
  xrechnung: ["xrechnung"],
179
188
  "peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
180
189
  zugferd: ["basicwl", "en16931", "extended"],
181
- facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
190
+ facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"],
191
+ fatturapa: ["ordinaria"],
192
+ facturae: ["ordinaria"],
193
+ eslog: ["eracun"],
194
+ ksef: ["fa3"]
182
195
  };
183
196
  function profilesForStandard(standard) {
184
197
  return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
@@ -1,5 +1,5 @@
1
- import { P as PlainObject } from './constants-BZuNzqbV.cjs';
2
- export { D as DEFAULT_BASE_URL, a as DocumentInput, G as GeneratePreset, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_PRESETS, d as LIVE_GENERATE_STANDARDS, e as LIVE_PARSE_FORMATS, f as LIVE_PROFILES, g as LIVE_PROFILES_BY_STANDARD, h as LIVE_VALIDATE_FORMATS, i as compactQuery, j as decodeUtf8, k as isPlainObject, l as isProfileAllowedForStandard, m as mergeDeep, p as profilesForStandard, s as sniffContentType, t as toBytes } from './constants-BZuNzqbV.cjs';
1
+ import { P as PlainObject } from './constants-DFGl_MXW.cjs';
2
+ export { D as DEFAULT_BASE_URL, a as DocumentInput, G as GeneratePreset, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_PRESETS, d as LIVE_GENERATE_STANDARDS, e as LIVE_PARSE_FORMATS, f as LIVE_PROFILES, g as LIVE_PROFILES_BY_STANDARD, h as LIVE_VALIDATE_FORMATS, i as compactQuery, j as decodeUtf8, k as isPlainObject, l as isProfileAllowedForStandard, m as mergeDeep, p as profilesForStandard, s as sniffContentType, t as toBytes } from './constants-DFGl_MXW.cjs';
3
3
 
4
4
  type Operation = 'me' | 'generate' | 'validate' | 'parse' | 'convert';
5
5
  /** 'json' => parse the `{ success, data }` envelope; 'binary' => return raw bytes. */
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PlainObject } from './constants-BZuNzqbV.js';
2
- export { D as DEFAULT_BASE_URL, a as DocumentInput, G as GeneratePreset, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_PRESETS, d as LIVE_GENERATE_STANDARDS, e as LIVE_PARSE_FORMATS, f as LIVE_PROFILES, g as LIVE_PROFILES_BY_STANDARD, h as LIVE_VALIDATE_FORMATS, i as compactQuery, j as decodeUtf8, k as isPlainObject, l as isProfileAllowedForStandard, m as mergeDeep, p as profilesForStandard, s as sniffContentType, t as toBytes } from './constants-BZuNzqbV.js';
1
+ import { P as PlainObject } from './constants-DFGl_MXW.js';
2
+ export { D as DEFAULT_BASE_URL, a as DocumentInput, G as GeneratePreset, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_PRESETS, d as LIVE_GENERATE_STANDARDS, e as LIVE_PARSE_FORMATS, f as LIVE_PROFILES, g as LIVE_PROFILES_BY_STANDARD, h as LIVE_VALIDATE_FORMATS, i as compactQuery, j as decodeUtf8, k as isPlainObject, l as isProfileAllowedForStandard, m as mergeDeep, p as profilesForStandard, s as sniffContentType, t as toBytes } from './constants-DFGl_MXW.js';
3
3
 
4
4
  type Operation = 'me' | 'generate' | 'validate' | 'parse' | 'convert';
5
5
  /** 'json' => parse the `{ success, data }` envelope; 'binary' => return raw bytes. */
package/dist/helpers.js CHANGED
@@ -122,7 +122,16 @@ function buildRequest(params) {
122
122
 
123
123
  // src/constants.ts
124
124
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
125
- var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
125
+ var LIVE_GENERATE_STANDARDS = [
126
+ "xrechnung",
127
+ "zugferd",
128
+ "facturx",
129
+ "peppol-bis",
130
+ "fatturapa",
131
+ "facturae",
132
+ "eslog",
133
+ "ksef"
134
+ ];
126
135
  var LIVE_GENERATE_PRESETS = [
127
136
  { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
128
137
  { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
@@ -135,7 +144,11 @@ var LIVE_PROFILES_BY_STANDARD = {
135
144
  xrechnung: ["xrechnung"],
136
145
  "peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
137
146
  zugferd: ["basicwl", "en16931", "extended"],
138
- facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
147
+ facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"],
148
+ fatturapa: ["ordinaria"],
149
+ facturae: ["ordinaria"],
150
+ eslog: ["eracun"],
151
+ ksef: ["fa3"]
139
152
  };
140
153
  function profilesForStandard(standard) {
141
154
  return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
package/dist/index.cjs CHANGED
@@ -211,7 +211,16 @@ function errorFromResponse(status, bytes) {
211
211
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
212
212
  var DEFAULT_TIMEOUT_MS = 9e4;
213
213
  var DEFAULT_MAX_RETRIES = 3;
214
- var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
214
+ var LIVE_GENERATE_STANDARDS = [
215
+ "xrechnung",
216
+ "zugferd",
217
+ "facturx",
218
+ "peppol-bis",
219
+ "fatturapa",
220
+ "facturae",
221
+ "eslog",
222
+ "ksef"
223
+ ];
215
224
  var LIVE_GENERATE_PRESETS = [
216
225
  { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
217
226
  { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
@@ -224,7 +233,11 @@ var LIVE_PROFILES_BY_STANDARD = {
224
233
  xrechnung: ["xrechnung"],
225
234
  "peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
226
235
  zugferd: ["basicwl", "en16931", "extended"],
227
- facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
236
+ facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"],
237
+ fatturapa: ["ordinaria"],
238
+ facturae: ["ordinaria"],
239
+ eslog: ["eracun"],
240
+ ksef: ["fa3"]
228
241
  };
229
242
  function profilesForStandard(standard) {
230
243
  return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
@@ -332,6 +345,11 @@ async function send(config, req) {
332
345
 
333
346
  // src/client.ts
334
347
  var TEST_KEY_PREFIX = "blq_test_";
348
+ function trimTrailingSlashes(url) {
349
+ let end = url.length;
350
+ while (end > 0 && url[end - 1] === "/") end--;
351
+ return url.slice(0, end);
352
+ }
335
353
  function livemodeHeader(headers) {
336
354
  const raw = headers.get("x-beliq-livemode");
337
355
  if (raw === "true") return true;
@@ -396,7 +414,7 @@ var Beliq = class {
396
414
  this.livemode = !options.apiKey.startsWith(TEST_KEY_PREFIX);
397
415
  this.#config = {
398
416
  apiKey: options.apiKey,
399
- baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
417
+ baseUrl: trimTrailingSlashes(options.baseUrl ?? DEFAULT_BASE_URL),
400
418
  auth: options.auth ?? "header",
401
419
  fetchImpl,
402
420
  timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,