@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 +35 -5
- package/dist/{constants-bWOXCmJD.d.cts → constants-D3j_o7th.d.cts} +19 -1
- package/dist/{constants-bWOXCmJD.d.ts → constants-D3j_o7th.d.ts} +19 -1
- package/dist/helpers.cjs +11 -1
- package/dist/helpers.d.cts +6 -2
- package/dist/helpers.d.ts +6 -2
- package/dist/helpers.js +10 -1
- package/dist/index.cjs +81 -7
- package/dist/index.d.cts +188 -27
- package/dist/index.d.ts +188 -27
- package/dist/index.js +80 -7
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -34,6 +34,18 @@ function toBytes(input) {
|
|
|
34
34
|
function decodeUtf8(bytes) {
|
|
35
35
|
return new TextDecoder("utf-8").decode(bytes);
|
|
36
36
|
}
|
|
37
|
+
function decodeBase64(input) {
|
|
38
|
+
const b64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
39
|
+
if (typeof atob === "function") {
|
|
40
|
+
const bin = atob(b64);
|
|
41
|
+
const out = new Uint8Array(bin.length);
|
|
42
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
const maybeBuffer = globalThis.Buffer;
|
|
46
|
+
if (maybeBuffer) return new Uint8Array(maybeBuffer.from(b64, "base64"));
|
|
47
|
+
throw new Error("beliq: no base64 decoder available in this runtime");
|
|
48
|
+
}
|
|
37
49
|
var PDF_MAGIC = [37, 80, 68, 70, 45];
|
|
38
50
|
function sniffContentType(bytes) {
|
|
39
51
|
const isPdf = bytes.length >= PDF_MAGIC.length && PDF_MAGIC.every((b, i) => bytes[i] === b);
|
|
@@ -72,7 +84,8 @@ function buildRequest(params) {
|
|
|
72
84
|
path: "/v1/generate",
|
|
73
85
|
jsonBody: merged,
|
|
74
86
|
contentType: "application/json",
|
|
75
|
-
|
|
87
|
+
// JSON mode returns the seal envelope; binary mode returns the raw document body.
|
|
88
|
+
...params.sealed ? { accept: "application/json", outputKind: "json" } : { outputKind: "binary" }
|
|
76
89
|
};
|
|
77
90
|
}
|
|
78
91
|
case "validate": {
|
|
@@ -157,6 +170,13 @@ function errorFromResponse(status, bytes) {
|
|
|
157
170
|
// src/constants.ts
|
|
158
171
|
var DEFAULT_BASE_URL = "https://api.beliq.eu";
|
|
159
172
|
var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
|
|
173
|
+
var LIVE_GENERATE_PRESETS = [
|
|
174
|
+
{ id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
|
|
175
|
+
{ id: "factur-x", label: "Factur-X", standard: "facturx", output: "pdf", facturxProfile: "en16931" },
|
|
176
|
+
{ id: "zugferd", label: "ZUGFeRD", standard: "zugferd", output: "pdf" },
|
|
177
|
+
{ id: "peppol-bis", label: "Peppol BIS 3.0", standard: "peppol-bis", output: "xml" },
|
|
178
|
+
{ id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
|
|
179
|
+
];
|
|
160
180
|
var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
161
181
|
var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
|
|
162
182
|
var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
|
|
@@ -195,6 +215,7 @@ function buildUrl(baseUrl, path, query) {
|
|
|
195
215
|
async function send(config, req) {
|
|
196
216
|
const headers = { ...authHeaders(config) };
|
|
197
217
|
if (req.contentType) headers["Content-Type"] = req.contentType;
|
|
218
|
+
if (req.accept) headers["Accept"] = req.accept;
|
|
198
219
|
const body = req.jsonBody !== void 0 ? JSON.stringify(req.jsonBody) : req.rawBody;
|
|
199
220
|
const res = await config.fetchImpl(buildUrl(config.baseUrl, req.path, req.query), {
|
|
200
221
|
method: req.method,
|
|
@@ -207,11 +228,31 @@ async function send(config, req) {
|
|
|
207
228
|
}
|
|
208
229
|
|
|
209
230
|
// src/client.ts
|
|
231
|
+
var TEST_KEY_PREFIX = "blq_test_";
|
|
232
|
+
function livemodeHeader(headers) {
|
|
233
|
+
const raw = headers.get("x-beliq-livemode");
|
|
234
|
+
if (raw === "true") return true;
|
|
235
|
+
if (raw === "false") return false;
|
|
236
|
+
return void 0;
|
|
237
|
+
}
|
|
238
|
+
function parseRulesetArtifacts(headers) {
|
|
239
|
+
const raw = headers.get("x-ruleset-artifacts");
|
|
240
|
+
if (!raw) return void 0;
|
|
241
|
+
try {
|
|
242
|
+
const parsed = JSON.parse(raw);
|
|
243
|
+
return Array.isArray(parsed) ? parsed : void 0;
|
|
244
|
+
} catch {
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
210
248
|
function generateMeta(headers) {
|
|
211
249
|
return {
|
|
212
250
|
schematronVersion: headers.get("x-schematron-version") ?? void 0,
|
|
213
251
|
pdfKind: headers.get("x-pdf-kind") ?? void 0,
|
|
214
|
-
outputEnvelope: headers.get("x-output-envelope") ?? void 0
|
|
252
|
+
outputEnvelope: headers.get("x-output-envelope") ?? void 0,
|
|
253
|
+
rulesetSha256: headers.get("x-ruleset-sha256") ?? void 0,
|
|
254
|
+
rulesetArtifacts: parseRulesetArtifacts(headers),
|
|
255
|
+
livemode: livemodeHeader(headers)
|
|
215
256
|
};
|
|
216
257
|
}
|
|
217
258
|
function convertMeta(headers) {
|
|
@@ -231,17 +272,25 @@ function convertMeta(headers) {
|
|
|
231
272
|
profileDetected: headers.get("x-profile-detected") ?? void 0,
|
|
232
273
|
lostElementsCount: countRaw != null ? Number(countRaw) : void 0,
|
|
233
274
|
lostElements,
|
|
234
|
-
conversionTools: headers.get("x-conversion-tools") ?? void 0
|
|
275
|
+
conversionTools: headers.get("x-conversion-tools") ?? void 0,
|
|
276
|
+
livemode: livemodeHeader(headers)
|
|
235
277
|
};
|
|
236
278
|
}
|
|
237
279
|
var Beliq = class {
|
|
238
280
|
#config;
|
|
281
|
+
/**
|
|
282
|
+
* True for a live key, false for a blq_test_ sandbox key, derived from the key
|
|
283
|
+
* prefix (the same rule the server applies). Available before any request; the
|
|
284
|
+
* per-response x-beliq-livemode header is surfaced on generate/convert meta.
|
|
285
|
+
*/
|
|
286
|
+
livemode;
|
|
239
287
|
constructor(options) {
|
|
240
288
|
if (!options?.apiKey) throw new Error("beliq: apiKey is required");
|
|
241
289
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
242
290
|
if (typeof fetchImpl !== "function") {
|
|
243
291
|
throw new Error("beliq: no global fetch available; pass options.fetch");
|
|
244
292
|
}
|
|
293
|
+
this.livemode = !options.apiKey.startsWith(TEST_KEY_PREFIX);
|
|
245
294
|
this.#config = {
|
|
246
295
|
apiKey: options.apiKey,
|
|
247
296
|
baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
|
|
@@ -255,14 +304,37 @@ var Beliq = class {
|
|
|
255
304
|
}
|
|
256
305
|
/** Generate a compliant e-invoice from an EN 16931 object. */
|
|
257
306
|
async generate(input) {
|
|
258
|
-
const res = await send(
|
|
307
|
+
const res = await send(
|
|
308
|
+
this.#config,
|
|
309
|
+
buildRequest({ operation: "generate", ...input, sealed: input.seal })
|
|
310
|
+
);
|
|
311
|
+
const meta = generateMeta(res.headers);
|
|
312
|
+
if (input.seal) {
|
|
313
|
+
const envelope = parseEnvelope(res.bytes);
|
|
314
|
+
if (envelope?.success === false) throw errorFromResponse(res.status, res.bytes);
|
|
315
|
+
const data = envelope?.data;
|
|
316
|
+
if (!data || data.output === void 0) {
|
|
317
|
+
throw new BeliqApiError("beliq: seal response was not a JSON envelope", {
|
|
318
|
+
status: res.status
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
const bytes = decodeBase64(data.output);
|
|
322
|
+
const contentType2 = data.contentType ?? "application/octet-stream";
|
|
323
|
+
return {
|
|
324
|
+
contentType: contentType2,
|
|
325
|
+
bytes,
|
|
326
|
+
xml: contentType2.includes("xml") ? decodeUtf8(bytes) : void 0,
|
|
327
|
+
sha256: data.sha256,
|
|
328
|
+
validationResult: data.validationResult,
|
|
329
|
+
meta
|
|
330
|
+
};
|
|
331
|
+
}
|
|
259
332
|
const contentType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
260
|
-
const isXml = contentType.includes("xml");
|
|
261
333
|
return {
|
|
262
334
|
contentType,
|
|
263
335
|
bytes: res.bytes,
|
|
264
|
-
xml:
|
|
265
|
-
meta
|
|
336
|
+
xml: contentType.includes("xml") ? decodeUtf8(res.bytes) : void 0,
|
|
337
|
+
meta
|
|
266
338
|
};
|
|
267
339
|
}
|
|
268
340
|
/** Validate a document against authority-pinned rules. */
|
|
@@ -325,6 +397,7 @@ export {
|
|
|
325
397
|
DEFAULT_BASE_URL,
|
|
326
398
|
LIVE_CONVERT_SOURCE_FORMATS,
|
|
327
399
|
LIVE_CONVERT_TARGET_FORMATS,
|
|
400
|
+
LIVE_GENERATE_PRESETS,
|
|
328
401
|
LIVE_GENERATE_STANDARDS,
|
|
329
402
|
LIVE_PARSE_FORMATS,
|
|
330
403
|
LIVE_PROFILES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beliq/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Official beliq SDK: generate, validate, parse, and convert EU-compliant e-invoices (XRechnung, ZUGFeRD, Factur-X, Peppol BIS) against authority-pinned, drift-checked rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"beliq",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"sync:spec": "node scripts/sync-spec.mjs",
|
|
73
73
|
"gen:types": "node scripts/gen-types.mjs",
|
|
74
74
|
"openapi:check": "node scripts/gen-types.mjs --check",
|
|
75
|
+
"spec:drift": "node scripts/check-live-drift.mjs",
|
|
75
76
|
"test": "vitest run --exclude test/integration.test.ts",
|
|
76
77
|
"test:integration": "vitest run test/integration.test.ts",
|
|
77
78
|
"prepublishOnly": "npm run build"
|