@beliq/sdk 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,9 +52,16 @@ if (!result.valid) {
52
52
  Create an API key in the beliq dashboard under API Keys, then pass it to the client:
53
53
 
54
54
  ```ts
55
- new Beliq({ apiKey: 'blq_...' }); // sends X-API-Key (default)
56
- new Beliq({ apiKey: 'blq_...', auth: 'bearer' }); // sends Authorization: Bearer
57
- new Beliq({ apiKey: 'blq_...', baseUrl: 'https://staging.beliq.eu' });
55
+ new Beliq({ apiKey: 'blq_live_...' }); // sends X-API-Key (default)
56
+ new Beliq({ apiKey: 'blq_live_...', auth: 'bearer' }); // sends Authorization: Bearer
57
+ new Beliq({ apiKey: 'blq_live_...', baseUrl: 'https://staging.beliq.eu' });
58
+ ```
59
+
60
+ Keys are prefixed `blq_live_` (production, draws your plan quota) or `blq_test_` (sandbox, separate free allowance, watermarked output). `client.livemode` reports the mode from the key prefix before any request; generate and convert results also carry the authoritative `meta.livemode` from the response.
61
+
62
+ ```ts
63
+ const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
64
+ if (!beliq.livemode) console.warn('running against the sandbox');
58
65
  ```
59
66
 
60
67
  ## API
@@ -62,12 +69,35 @@ new Beliq({ apiKey: 'blq_...', baseUrl: 'https://staging.beliq.eu' });
62
69
  | Method | Endpoint | Input | Returns |
63
70
  |---|---|---|---|
64
71
  | `me()` | GET /v1/me | none | `AccountInfo` (no quota cost) |
65
- | `generate(input)` | POST /v1/generate | EN 16931 invoice object | `{ contentType, bytes, xml?, meta }` |
72
+ | `generate(input)` | POST /v1/generate | EN 16931 invoice object | `{ contentType, bytes, xml?, sha256?, validationResult?, meta }` |
66
73
  | `validate(document, options?)` | POST /v1/validate | XML or PDF | `ValidationResult` |
67
74
  | `parse(document, options?)` | POST /v1/parse | XML or PDF | `ParseResult` |
68
75
  | `convert(document, options)` | POST /v1/convert | XML or PDF | `{ contentType, bytes, meta }` |
69
76
 
70
- `document` accepts a `string`, `Uint8Array`, `Buffer`, `ArrayBuffer`, or typed array. The content type is sniffed from the bytes (PDF vs XML) unless you pass `options.contentType`. `generate` and `convert` return raw document bytes plus the response-header metadata (`schematronVersion`, `pdfKind`, `sourceFormat`/`targetFormat`, `lostElements`, `conversionTools`); for an XML output, `generate` also decodes `xml`.
77
+ `document` accepts a `string`, `Uint8Array`, `Buffer`, `ArrayBuffer`, or typed array. The content type is sniffed from the bytes (PDF vs XML) unless you pass `options.contentType`. `generate` and `convert` return raw document bytes plus the response-header metadata (`schematronVersion`, `pdfKind`, `sourceFormat`/`targetFormat`, `lostElements`, `conversionTools`, `livemode`); for an XML output, `generate` also decodes `xml`.
78
+
79
+ ### Verify-it-yourself seal
80
+
81
+ Pass `seal: true` to `generate` to also get the document `sha256` and the full `validationResult`. Hashing the returned bytes reproduces the hash, so a recipient can check the document independently:
82
+
83
+ ```ts
84
+ import { createHash } from 'node:crypto';
85
+
86
+ const doc = await beliq.generate({ standard: 'xrechnung', invoice, seal: true });
87
+ const ok = createHash('sha256').update(doc.bytes).digest('hex') === doc.sha256;
88
+ console.log(doc.validationResult?.valid, doc.meta.rulesetSha256, ok);
89
+ ```
90
+
91
+ ### Curated option lists
92
+
93
+ `LIVE_GENERATE_PRESETS` is the set of public generate targets beliq.eu itself offers, each mapping to the API `standard` (plus `profile`/`facturxProfile`) it needs. NLCIUS is a Peppol BIS profile and lives here rather than in `LIVE_GENERATE_STANDARDS`. Connectors build their dropdowns from these lists.
94
+
95
+ ```ts
96
+ import { LIVE_GENERATE_PRESETS } from '@beliq/sdk';
97
+
98
+ const nlcius = LIVE_GENERATE_PRESETS.find((p) => p.id === 'nlcius');
99
+ await beliq.generate({ standard: nlcius!.standard, profile: nlcius!.profile, invoice });
100
+ ```
71
101
 
72
102
  Every option enum is typed from the OpenAPI spec, so wrong values fail at compile time. Errors throw `BeliqApiError` with a typed `.code`, HTTP `.status`, and any `.details`:
73
103
 
@@ -13,10 +13,28 @@ declare function sniffContentType(bytes: Uint8Array): string;
13
13
 
14
14
  declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
15
15
  declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
16
+ /** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
17
+ interface GeneratePreset {
18
+ id: string;
19
+ label: string;
20
+ standard: (typeof LIVE_GENERATE_STANDARDS)[number];
21
+ output: 'xml' | 'pdf';
22
+ /** API `profile`; omitted lets the engine pick the standard's default. */
23
+ profile?: string;
24
+ /** API `facturxProfile`; Factur-X / ZUGFeRD only. */
25
+ facturxProfile?: string;
26
+ }
27
+ /**
28
+ * Named generate targets surfaced to end users (connector dropdowns), mirroring
29
+ * the public set on beliq.eu's own generator. NLCIUS is a Peppol BIS profile,
30
+ * not a standalone standard, so it is reachable here rather than through
31
+ * LIVE_GENERATE_STANDARDS or the Factur-X-only LIVE_PROFILES.
32
+ */
33
+ declare const LIVE_GENERATE_PRESETS: readonly GeneratePreset[];
16
34
  declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
17
35
  declare const LIVE_VALIDATE_FORMATS: readonly ["auto", "cii", "ubl"];
18
36
  declare const LIVE_PARSE_FORMATS: readonly ["auto", "cii", "ubl"];
19
37
  declare const LIVE_CONVERT_SOURCE_FORMATS: readonly ["auto", "cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
20
38
  declare const LIVE_CONVERT_TARGET_FORMATS: readonly ["cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
21
39
 
22
- export { DEFAULT_BASE_URL as D, LIVE_CONVERT_SOURCE_FORMATS as L, type PlainObject as P, type DocumentInput as a, LIVE_CONVERT_TARGET_FORMATS as b, LIVE_GENERATE_STANDARDS as c, LIVE_PARSE_FORMATS as d, LIVE_PROFILES as e, LIVE_VALIDATE_FORMATS as f, compactQuery as g, decodeUtf8 as h, isPlainObject as i, mergeDeep as m, sniffContentType as s, toBytes as t };
40
+ export { DEFAULT_BASE_URL as D, type GeneratePreset as G, LIVE_CONVERT_SOURCE_FORMATS as L, type PlainObject as P, type DocumentInput as a, LIVE_CONVERT_TARGET_FORMATS as b, LIVE_GENERATE_PRESETS as c, LIVE_GENERATE_STANDARDS as d, LIVE_PARSE_FORMATS as e, LIVE_PROFILES as f, LIVE_VALIDATE_FORMATS as g, compactQuery as h, decodeUtf8 as i, isPlainObject as j, mergeDeep as m, sniffContentType as s, toBytes as t };
@@ -13,10 +13,28 @@ declare function sniffContentType(bytes: Uint8Array): string;
13
13
 
14
14
  declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
15
15
  declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
16
+ /** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
17
+ interface GeneratePreset {
18
+ id: string;
19
+ label: string;
20
+ standard: (typeof LIVE_GENERATE_STANDARDS)[number];
21
+ output: 'xml' | 'pdf';
22
+ /** API `profile`; omitted lets the engine pick the standard's default. */
23
+ profile?: string;
24
+ /** API `facturxProfile`; Factur-X / ZUGFeRD only. */
25
+ facturxProfile?: string;
26
+ }
27
+ /**
28
+ * Named generate targets surfaced to end users (connector dropdowns), mirroring
29
+ * the public set on beliq.eu's own generator. NLCIUS is a Peppol BIS profile,
30
+ * not a standalone standard, so it is reachable here rather than through
31
+ * LIVE_GENERATE_STANDARDS or the Factur-X-only LIVE_PROFILES.
32
+ */
33
+ declare const LIVE_GENERATE_PRESETS: readonly GeneratePreset[];
16
34
  declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
17
35
  declare const LIVE_VALIDATE_FORMATS: readonly ["auto", "cii", "ubl"];
18
36
  declare const LIVE_PARSE_FORMATS: readonly ["auto", "cii", "ubl"];
19
37
  declare const LIVE_CONVERT_SOURCE_FORMATS: readonly ["auto", "cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
20
38
  declare const LIVE_CONVERT_TARGET_FORMATS: readonly ["cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
21
39
 
22
- export { DEFAULT_BASE_URL as D, LIVE_CONVERT_SOURCE_FORMATS as L, type PlainObject as P, type DocumentInput as a, LIVE_CONVERT_TARGET_FORMATS as b, LIVE_GENERATE_STANDARDS as c, LIVE_PARSE_FORMATS as d, LIVE_PROFILES as e, LIVE_VALIDATE_FORMATS as f, compactQuery as g, decodeUtf8 as h, isPlainObject as i, mergeDeep as m, sniffContentType as s, toBytes as t };
40
+ export { DEFAULT_BASE_URL as D, type GeneratePreset as G, LIVE_CONVERT_SOURCE_FORMATS as L, type PlainObject as P, type DocumentInput as a, LIVE_CONVERT_TARGET_FORMATS as b, LIVE_GENERATE_PRESETS as c, LIVE_GENERATE_STANDARDS as d, LIVE_PARSE_FORMATS as e, LIVE_PROFILES as f, LIVE_VALIDATE_FORMATS as g, compactQuery as h, decodeUtf8 as i, isPlainObject as j, mergeDeep as m, sniffContentType as s, toBytes as t };
package/dist/helpers.cjs CHANGED
@@ -23,6 +23,7 @@ __export(helpers_exports, {
23
23
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
24
24
  LIVE_CONVERT_SOURCE_FORMATS: () => LIVE_CONVERT_SOURCE_FORMATS,
25
25
  LIVE_CONVERT_TARGET_FORMATS: () => LIVE_CONVERT_TARGET_FORMATS,
26
+ LIVE_GENERATE_PRESETS: () => LIVE_GENERATE_PRESETS,
26
27
  LIVE_GENERATE_STANDARDS: () => LIVE_GENERATE_STANDARDS,
27
28
  LIVE_PARSE_FORMATS: () => LIVE_PARSE_FORMATS,
28
29
  LIVE_PROFILES: () => LIVE_PROFILES,
@@ -111,7 +112,8 @@ function buildRequest(params) {
111
112
  path: "/v1/generate",
112
113
  jsonBody: merged,
113
114
  contentType: "application/json",
114
- outputKind: "binary"
115
+ // JSON mode returns the seal envelope; binary mode returns the raw document body.
116
+ ...params.sealed ? { accept: "application/json", outputKind: "json" } : { outputKind: "binary" }
115
117
  };
116
118
  }
117
119
  case "validate": {
@@ -161,6 +163,13 @@ function buildRequest(params) {
161
163
  // src/constants.ts
162
164
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
163
165
  var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
166
+ var LIVE_GENERATE_PRESETS = [
167
+ { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
168
+ { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
169
+ { id: "zugferd", label: "ZUGFeRD", standard: "zugferd", output: "pdf" },
170
+ { id: "peppol-bis", label: "Peppol BIS 3.0", standard: "peppol-bis", output: "xml" },
171
+ { id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
172
+ ];
164
173
  var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
165
174
  var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
166
175
  var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
@@ -186,6 +195,7 @@ var LIVE_CONVERT_TARGET_FORMATS = [
186
195
  DEFAULT_BASE_URL,
187
196
  LIVE_CONVERT_SOURCE_FORMATS,
188
197
  LIVE_CONVERT_TARGET_FORMATS,
198
+ LIVE_GENERATE_PRESETS,
189
199
  LIVE_GENERATE_STANDARDS,
190
200
  LIVE_PARSE_FORMATS,
191
201
  LIVE_PROFILES,
@@ -1,5 +1,5 @@
1
- import { P as PlainObject } from './constants-bWOXCmJD.cjs';
2
- export { D as DEFAULT_BASE_URL, a as DocumentInput, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_STANDARDS, d as LIVE_PARSE_FORMATS, e as LIVE_PROFILES, f as LIVE_VALIDATE_FORMATS, g as compactQuery, h as decodeUtf8, i as isPlainObject, m as mergeDeep, s as sniffContentType, t as toBytes } from './constants-bWOXCmJD.cjs';
1
+ import { P as PlainObject } from './constants-D3j_o7th.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_VALIDATE_FORMATS, h as compactQuery, i as decodeUtf8, j as isPlainObject, m as mergeDeep, s as sniffContentType, t as toBytes } from './constants-D3j_o7th.cjs';
3
3
 
4
4
  type Operation = 'me' | 'generate' | 'validate' | 'parse' | 'convert';
5
5
  /** 'json' => parse the `{ success, data }` envelope; 'binary' => return raw bytes. */
@@ -15,6 +15,8 @@ interface BuildParams {
15
15
  verify?: boolean;
16
16
  template?: string;
17
17
  pdfTemplateId?: string;
18
+ /** Request the JSON-mode seal (Accept: application/json) instead of the binary body. */
19
+ sealed?: boolean;
18
20
  rawBody?: Uint8Array;
19
21
  rawContentType?: string;
20
22
  validateFormat?: string;
@@ -37,6 +39,8 @@ interface BuiltRequest {
37
39
  rawBody?: Uint8Array;
38
40
  /** Request content type; absent for GET. */
39
41
  contentType?: string;
42
+ /** Accept header; set when the caller wants a JSON envelope from an otherwise-binary op. */
43
+ accept?: string;
40
44
  outputKind: OutputKind;
41
45
  }
42
46
  declare function buildRequest(params: BuildParams): BuiltRequest;
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PlainObject } from './constants-bWOXCmJD.js';
2
- export { D as DEFAULT_BASE_URL, a as DocumentInput, L as LIVE_CONVERT_SOURCE_FORMATS, b as LIVE_CONVERT_TARGET_FORMATS, c as LIVE_GENERATE_STANDARDS, d as LIVE_PARSE_FORMATS, e as LIVE_PROFILES, f as LIVE_VALIDATE_FORMATS, g as compactQuery, h as decodeUtf8, i as isPlainObject, m as mergeDeep, s as sniffContentType, t as toBytes } from './constants-bWOXCmJD.js';
1
+ import { P as PlainObject } from './constants-D3j_o7th.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_VALIDATE_FORMATS, h as compactQuery, i as decodeUtf8, j as isPlainObject, m as mergeDeep, s as sniffContentType, t as toBytes } from './constants-D3j_o7th.js';
3
3
 
4
4
  type Operation = 'me' | 'generate' | 'validate' | 'parse' | 'convert';
5
5
  /** 'json' => parse the `{ success, data }` envelope; 'binary' => return raw bytes. */
@@ -15,6 +15,8 @@ interface BuildParams {
15
15
  verify?: boolean;
16
16
  template?: string;
17
17
  pdfTemplateId?: string;
18
+ /** Request the JSON-mode seal (Accept: application/json) instead of the binary body. */
19
+ sealed?: boolean;
18
20
  rawBody?: Uint8Array;
19
21
  rawContentType?: string;
20
22
  validateFormat?: string;
@@ -37,6 +39,8 @@ interface BuiltRequest {
37
39
  rawBody?: Uint8Array;
38
40
  /** Request content type; absent for GET. */
39
41
  contentType?: string;
42
+ /** Accept header; set when the caller wants a JSON envelope from an otherwise-binary op. */
43
+ accept?: string;
40
44
  outputKind: OutputKind;
41
45
  }
42
46
  declare function buildRequest(params: BuildParams): BuiltRequest;
package/dist/helpers.js CHANGED
@@ -72,7 +72,8 @@ function buildRequest(params) {
72
72
  path: "/v1/generate",
73
73
  jsonBody: merged,
74
74
  contentType: "application/json",
75
- outputKind: "binary"
75
+ // JSON mode returns the seal envelope; binary mode returns the raw document body.
76
+ ...params.sealed ? { accept: "application/json", outputKind: "json" } : { outputKind: "binary" }
76
77
  };
77
78
  }
78
79
  case "validate": {
@@ -122,6 +123,13 @@ function buildRequest(params) {
122
123
  // src/constants.ts
123
124
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
124
125
  var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
126
+ var LIVE_GENERATE_PRESETS = [
127
+ { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
128
+ { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
129
+ { id: "zugferd", label: "ZUGFeRD", standard: "zugferd", output: "pdf" },
130
+ { id: "peppol-bis", label: "Peppol BIS 3.0", standard: "peppol-bis", output: "xml" },
131
+ { id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
132
+ ];
125
133
  var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
126
134
  var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
127
135
  var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
@@ -146,6 +154,7 @@ export {
146
154
  DEFAULT_BASE_URL,
147
155
  LIVE_CONVERT_SOURCE_FORMATS,
148
156
  LIVE_CONVERT_TARGET_FORMATS,
157
+ LIVE_GENERATE_PRESETS,
149
158
  LIVE_GENERATE_STANDARDS,
150
159
  LIVE_PARSE_FORMATS,
151
160
  LIVE_PROFILES,
package/dist/index.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
26
26
  LIVE_CONVERT_SOURCE_FORMATS: () => LIVE_CONVERT_SOURCE_FORMATS,
27
27
  LIVE_CONVERT_TARGET_FORMATS: () => LIVE_CONVERT_TARGET_FORMATS,
28
+ LIVE_GENERATE_PRESETS: () => LIVE_GENERATE_PRESETS,
28
29
  LIVE_GENERATE_STANDARDS: () => LIVE_GENERATE_STANDARDS,
29
30
  LIVE_PARSE_FORMATS: () => LIVE_PARSE_FORMATS,
30
31
  LIVE_PROFILES: () => LIVE_PROFILES,
@@ -68,6 +69,18 @@ function toBytes(input) {
68
69
  function decodeUtf8(bytes) {
69
70
  return new TextDecoder("utf-8").decode(bytes);
70
71
  }
72
+ function decodeBase64(input) {
73
+ const b64 = input.replace(/-/g, "+").replace(/_/g, "/");
74
+ if (typeof atob === "function") {
75
+ const bin = atob(b64);
76
+ const out = new Uint8Array(bin.length);
77
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
78
+ return out;
79
+ }
80
+ const maybeBuffer = globalThis.Buffer;
81
+ if (maybeBuffer) return new Uint8Array(maybeBuffer.from(b64, "base64"));
82
+ throw new Error("beliq: no base64 decoder available in this runtime");
83
+ }
71
84
  var PDF_MAGIC = [37, 80, 68, 70, 45];
72
85
  function sniffContentType(bytes) {
73
86
  const isPdf = bytes.length >= PDF_MAGIC.length && PDF_MAGIC.every((b, i) => bytes[i] === b);
@@ -106,7 +119,8 @@ function buildRequest(params) {
106
119
  path: "/v1/generate",
107
120
  jsonBody: merged,
108
121
  contentType: "application/json",
109
- outputKind: "binary"
122
+ // JSON mode returns the seal envelope; binary mode returns the raw document body.
123
+ ...params.sealed ? { accept: "application/json", outputKind: "json" } : { outputKind: "binary" }
110
124
  };
111
125
  }
112
126
  case "validate": {
@@ -191,6 +205,13 @@ function errorFromResponse(status, bytes) {
191
205
  // src/constants.ts
192
206
  var DEFAULT_BASE_URL = "https://api.beliq.eu";
193
207
  var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
208
+ var LIVE_GENERATE_PRESETS = [
209
+ { id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
210
+ { id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
211
+ { id: "zugferd", label: "ZUGFeRD", standard: "zugferd", output: "pdf" },
212
+ { id: "peppol-bis", label: "Peppol BIS 3.0", standard: "peppol-bis", output: "xml" },
213
+ { id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
214
+ ];
194
215
  var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
195
216
  var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
196
217
  var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
@@ -229,6 +250,7 @@ function buildUrl(baseUrl, path, query) {
229
250
  async function send(config, req) {
230
251
  const headers = { ...authHeaders(config) };
231
252
  if (req.contentType) headers["Content-Type"] = req.contentType;
253
+ if (req.accept) headers["Accept"] = req.accept;
232
254
  const body = req.jsonBody !== void 0 ? JSON.stringify(req.jsonBody) : req.rawBody;
233
255
  const res = await config.fetchImpl(buildUrl(config.baseUrl, req.path, req.query), {
234
256
  method: req.method,
@@ -241,11 +263,31 @@ async function send(config, req) {
241
263
  }
242
264
 
243
265
  // src/client.ts
266
+ var TEST_KEY_PREFIX = "blq_test_";
267
+ function livemodeHeader(headers) {
268
+ const raw = headers.get("x-beliq-livemode");
269
+ if (raw === "true") return true;
270
+ if (raw === "false") return false;
271
+ return void 0;
272
+ }
273
+ function parseRulesetArtifacts(headers) {
274
+ const raw = headers.get("x-ruleset-artifacts");
275
+ if (!raw) return void 0;
276
+ try {
277
+ const parsed = JSON.parse(raw);
278
+ return Array.isArray(parsed) ? parsed : void 0;
279
+ } catch {
280
+ return void 0;
281
+ }
282
+ }
244
283
  function generateMeta(headers) {
245
284
  return {
246
285
  schematronVersion: headers.get("x-schematron-version") ?? void 0,
247
286
  pdfKind: headers.get("x-pdf-kind") ?? void 0,
248
- outputEnvelope: headers.get("x-output-envelope") ?? void 0
287
+ outputEnvelope: headers.get("x-output-envelope") ?? void 0,
288
+ rulesetSha256: headers.get("x-ruleset-sha256") ?? void 0,
289
+ rulesetArtifacts: parseRulesetArtifacts(headers),
290
+ livemode: livemodeHeader(headers)
249
291
  };
250
292
  }
251
293
  function convertMeta(headers) {
@@ -265,17 +307,25 @@ function convertMeta(headers) {
265
307
  profileDetected: headers.get("x-profile-detected") ?? void 0,
266
308
  lostElementsCount: countRaw != null ? Number(countRaw) : void 0,
267
309
  lostElements,
268
- conversionTools: headers.get("x-conversion-tools") ?? void 0
310
+ conversionTools: headers.get("x-conversion-tools") ?? void 0,
311
+ livemode: livemodeHeader(headers)
269
312
  };
270
313
  }
271
314
  var Beliq = class {
272
315
  #config;
316
+ /**
317
+ * True for a live key, false for a blq_test_ sandbox key, derived from the key
318
+ * prefix (the same rule the server applies). Available before any request; the
319
+ * per-response x-beliq-livemode header is surfaced on generate/convert meta.
320
+ */
321
+ livemode;
273
322
  constructor(options) {
274
323
  if (!options?.apiKey) throw new Error("beliq: apiKey is required");
275
324
  const fetchImpl = options.fetch ?? globalThis.fetch;
276
325
  if (typeof fetchImpl !== "function") {
277
326
  throw new Error("beliq: no global fetch available; pass options.fetch");
278
327
  }
328
+ this.livemode = !options.apiKey.startsWith(TEST_KEY_PREFIX);
279
329
  this.#config = {
280
330
  apiKey: options.apiKey,
281
331
  baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
@@ -289,14 +339,37 @@ var Beliq = class {
289
339
  }
290
340
  /** Generate a compliant e-invoice from an EN 16931 object. */
291
341
  async generate(input) {
292
- const res = await send(this.#config, buildRequest({ operation: "generate", ...input }));
342
+ const res = await send(
343
+ this.#config,
344
+ buildRequest({ operation: "generate", ...input, sealed: input.seal })
345
+ );
346
+ const meta = generateMeta(res.headers);
347
+ if (input.seal) {
348
+ const envelope = parseEnvelope(res.bytes);
349
+ if (envelope?.success === false) throw errorFromResponse(res.status, res.bytes);
350
+ const data = envelope?.data;
351
+ if (!data || data.output === void 0) {
352
+ throw new BeliqApiError("beliq: seal response was not a JSON envelope", {
353
+ status: res.status
354
+ });
355
+ }
356
+ const bytes = decodeBase64(data.output);
357
+ const contentType2 = data.contentType ?? "application/octet-stream";
358
+ return {
359
+ contentType: contentType2,
360
+ bytes,
361
+ xml: contentType2.includes("xml") ? decodeUtf8(bytes) : void 0,
362
+ sha256: data.sha256,
363
+ validationResult: data.validationResult,
364
+ meta
365
+ };
366
+ }
293
367
  const contentType = res.headers.get("content-type") ?? "application/octet-stream";
294
- const isXml = contentType.includes("xml");
295
368
  return {
296
369
  contentType,
297
370
  bytes: res.bytes,
298
- xml: isXml ? decodeUtf8(res.bytes) : void 0,
299
- meta: generateMeta(res.headers)
371
+ xml: contentType.includes("xml") ? decodeUtf8(res.bytes) : void 0,
372
+ meta
300
373
  };
301
374
  }
302
375
  /** Validate a document against authority-pinned rules. */
@@ -360,6 +433,7 @@ var Beliq = class {
360
433
  DEFAULT_BASE_URL,
361
434
  LIVE_CONVERT_SOURCE_FORMATS,
362
435
  LIVE_CONVERT_TARGET_FORMATS,
436
+ LIVE_GENERATE_PRESETS,
363
437
  LIVE_GENERATE_STANDARDS,
364
438
  LIVE_PARSE_FORMATS,
365
439
  LIVE_PROFILES,