@beliq/sdk 0.2.0 → 0.3.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 +30 -0
- package/dist/constants-BZuNzqbV.d.cts +85 -0
- package/dist/constants-BZuNzqbV.d.ts +85 -0
- package/dist/helpers.cjs +19 -0
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +16 -0
- package/dist/index.cjs +80 -11
- package/dist/index.d.cts +642 -27
- package/dist/index.d.ts +642 -27
- package/dist/index.js +74 -10
- package/package.json +11 -6
- package/dist/constants-D3j_o7th.d.cts +0 -40
- package/dist/constants-D3j_o7th.d.ts +0 -40
package/README.md
CHANGED
|
@@ -64,6 +64,36 @@ const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
|
|
|
64
64
|
if (!beliq.livemode) console.warn('running against the sandbox');
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
## Timeouts and retries
|
|
68
|
+
|
|
69
|
+
The client retries transient failures for you, so you do not have to reimplement
|
|
70
|
+
backoff around it.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
new Beliq({
|
|
74
|
+
apiKey: 'blq_live_...',
|
|
75
|
+
timeoutMs: 90_000, // per-attempt deadline (default)
|
|
76
|
+
maxRetries: 3, // extra attempts after the first (default)
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Both defaults are exported as `DEFAULT_TIMEOUT_MS` and `DEFAULT_MAX_RETRIES`, so
|
|
81
|
+
you can derive from them instead of repeating the numbers.
|
|
82
|
+
|
|
83
|
+
Only `429`, `502` and `503` are retried, honouring the server's `Retry-After`
|
|
84
|
+
with jitter. beliq refunds the document's quota unit on a `503`, so a retry never
|
|
85
|
+
costs you a second document.
|
|
86
|
+
|
|
87
|
+
`504` and this client's own timeout are deliberately **not** retried: both mean
|
|
88
|
+
the work may still be running on beliq's side, so retrying risks producing a
|
|
89
|
+
second document rather than recovering the first.
|
|
90
|
+
|
|
91
|
+
The default deadline is generous because beliq runs the full Schematron rule set
|
|
92
|
+
over each document, and a generate or validate can legitimately take tens of
|
|
93
|
+
seconds. If you lower it, keep it above the latency you actually see: a deadline
|
|
94
|
+
shorter than the server's own turns completed work into an unknown outcome. Set
|
|
95
|
+
`timeoutMs: 0` to disable it, and `maxRetries: 0` to handle retrying yourself.
|
|
96
|
+
|
|
67
97
|
## API
|
|
68
98
|
|
|
69
99
|
| Method | Endpoint | Input | Returns |
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
type PlainObject = Record<string, unknown>;
|
|
2
|
+
declare function isPlainObject(value: unknown): value is PlainObject;
|
|
3
|
+
/** Deep-merge `source` into `target` (source wins). Arrays and scalars overwrite. */
|
|
4
|
+
declare function mergeDeep(target: PlainObject, source: PlainObject): PlainObject;
|
|
5
|
+
/** Drop undefined/empty entries so optional query params are omitted, not sent blank. */
|
|
6
|
+
declare function compactQuery(query: PlainObject): PlainObject;
|
|
7
|
+
/** Document bytes a caller may pass to validate/parse/convert. */
|
|
8
|
+
type DocumentInput = string | Uint8Array | ArrayBuffer | ArrayBufferView;
|
|
9
|
+
declare function toBytes(input: DocumentInput): Uint8Array;
|
|
10
|
+
declare function decodeUtf8(bytes: Uint8Array): string;
|
|
11
|
+
/** Sniff `application/pdf` vs `application/xml` from the leading bytes. */
|
|
12
|
+
declare function sniffContentType(bytes: Uint8Array): string;
|
|
13
|
+
|
|
14
|
+
declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
|
|
15
|
+
/**
|
|
16
|
+
* Per-attempt deadline. Sits above the API's own worst case so the server is
|
|
17
|
+
* always the one to answer: a client that gives up first abandons work that is
|
|
18
|
+
* still running, and cannot tell whether the document was produced.
|
|
19
|
+
*/
|
|
20
|
+
declare const DEFAULT_TIMEOUT_MS = 90000;
|
|
21
|
+
/** Extra attempts after the first, for 429 / 502 / 503 only. */
|
|
22
|
+
declare const DEFAULT_MAX_RETRIES = 3;
|
|
23
|
+
declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
|
|
24
|
+
/** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
|
|
25
|
+
interface GeneratePreset {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
standard: (typeof LIVE_GENERATE_STANDARDS)[number];
|
|
29
|
+
output: 'xml' | 'pdf';
|
|
30
|
+
/** API `profile`; omitted lets the engine pick the standard's default. */
|
|
31
|
+
profile?: string;
|
|
32
|
+
/** API `facturxProfile`; Factur-X / ZUGFeRD only. */
|
|
33
|
+
facturxProfile?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Named generate targets surfaced to end users (connector dropdowns), mirroring
|
|
37
|
+
* the public set on beliq.eu's own generator. NLCIUS is a Peppol BIS profile,
|
|
38
|
+
* not a standalone standard, so it is reachable here rather than through
|
|
39
|
+
* LIVE_GENERATE_STANDARDS or the Factur-X-only LIVE_PROFILES.
|
|
40
|
+
*/
|
|
41
|
+
declare const LIVE_GENERATE_PRESETS: readonly GeneratePreset[];
|
|
42
|
+
/**
|
|
43
|
+
* The Factur-X granularity values offered publicly. Kept as the flat list the
|
|
44
|
+
* hybrid-PDF family shares; anything choosing a profile for a specific standard
|
|
45
|
+
* wants LIVE_PROFILES_BY_STANDARD instead, which is what the API enforces.
|
|
46
|
+
*/
|
|
47
|
+
declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
48
|
+
/**
|
|
49
|
+
* Which profiles each standard accepts, publicly-offered values only.
|
|
50
|
+
*
|
|
51
|
+
* `profile` is not a free enum: the engine pins it per standard and answers a
|
|
52
|
+
* pair outside the table with `422 PROFILE_STANDARD_MISMATCH`
|
|
53
|
+
* (beliq-engine `app/routes/generate.py`, ALLOWED_PROFILES_FOR_STANDARD). A
|
|
54
|
+
* surface that offers one flat profile list therefore offers values that cannot
|
|
55
|
+
* succeed: none of the Factur-X granularity values is legal for `xrechnung` or
|
|
56
|
+
* `peppol-bis`, and `extended-ctc-fr` is the AFNOR XP Z12-012 France CTC overlay
|
|
57
|
+
* with no ZUGFeRD-branded counterpart.
|
|
58
|
+
*
|
|
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.
|
|
63
|
+
*
|
|
64
|
+
* `scripts/check-profile-drift.mjs` compares this against the engine's table.
|
|
65
|
+
*/
|
|
66
|
+
declare const LIVE_PROFILES_BY_STANDARD: {
|
|
67
|
+
readonly xrechnung: readonly ["xrechnung"];
|
|
68
|
+
readonly 'peppol-bis': readonly ["peppol", "romania-ro-cius", "netherlands-nlcius"];
|
|
69
|
+
readonly zugferd: readonly ["basicwl", "en16931", "extended"];
|
|
70
|
+
readonly facturx: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
71
|
+
};
|
|
72
|
+
/** The profiles a caller may choose for `standard`; empty for an unknown standard. */
|
|
73
|
+
declare function profilesForStandard(standard: string): readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* Whether `profile` is legal for `standard`. An unknown standard passes: the API
|
|
76
|
+
* is the authority on values this list does not carry, and a client-side guess
|
|
77
|
+
* would refuse a request the server would have accepted.
|
|
78
|
+
*/
|
|
79
|
+
declare function isProfileAllowedForStandard(standard: string, profile: string): boolean;
|
|
80
|
+
declare const LIVE_VALIDATE_FORMATS: readonly ["auto", "cii", "ubl"];
|
|
81
|
+
declare const LIVE_PARSE_FORMATS: readonly ["auto", "cii", "ubl"];
|
|
82
|
+
declare const LIVE_CONVERT_SOURCE_FORMATS: readonly ["auto", "cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
|
|
83
|
+
declare const LIVE_CONVERT_TARGET_FORMATS: readonly ["cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
|
|
84
|
+
|
|
85
|
+
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_PROFILES_BY_STANDARD as g, LIVE_VALIDATE_FORMATS as h, compactQuery as i, decodeUtf8 as j, isPlainObject as k, isProfileAllowedForStandard as l, mergeDeep as m, DEFAULT_MAX_RETRIES as n, DEFAULT_TIMEOUT_MS as o, profilesForStandard as p, sniffContentType as s, toBytes as t };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
type PlainObject = Record<string, unknown>;
|
|
2
|
+
declare function isPlainObject(value: unknown): value is PlainObject;
|
|
3
|
+
/** Deep-merge `source` into `target` (source wins). Arrays and scalars overwrite. */
|
|
4
|
+
declare function mergeDeep(target: PlainObject, source: PlainObject): PlainObject;
|
|
5
|
+
/** Drop undefined/empty entries so optional query params are omitted, not sent blank. */
|
|
6
|
+
declare function compactQuery(query: PlainObject): PlainObject;
|
|
7
|
+
/** Document bytes a caller may pass to validate/parse/convert. */
|
|
8
|
+
type DocumentInput = string | Uint8Array | ArrayBuffer | ArrayBufferView;
|
|
9
|
+
declare function toBytes(input: DocumentInput): Uint8Array;
|
|
10
|
+
declare function decodeUtf8(bytes: Uint8Array): string;
|
|
11
|
+
/** Sniff `application/pdf` vs `application/xml` from the leading bytes. */
|
|
12
|
+
declare function sniffContentType(bytes: Uint8Array): string;
|
|
13
|
+
|
|
14
|
+
declare const DEFAULT_BASE_URL = "https://api.beliq.eu";
|
|
15
|
+
/**
|
|
16
|
+
* Per-attempt deadline. Sits above the API's own worst case so the server is
|
|
17
|
+
* always the one to answer: a client that gives up first abandons work that is
|
|
18
|
+
* still running, and cannot tell whether the document was produced.
|
|
19
|
+
*/
|
|
20
|
+
declare const DEFAULT_TIMEOUT_MS = 90000;
|
|
21
|
+
/** Extra attempts after the first, for 429 / 502 / 503 only. */
|
|
22
|
+
declare const DEFAULT_MAX_RETRIES = 3;
|
|
23
|
+
declare const LIVE_GENERATE_STANDARDS: readonly ["xrechnung", "zugferd", "facturx", "peppol-bis"];
|
|
24
|
+
/** A named generate target: the API `standard` plus the `profile`/`facturxProfile`/`output` it needs. */
|
|
25
|
+
interface GeneratePreset {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
standard: (typeof LIVE_GENERATE_STANDARDS)[number];
|
|
29
|
+
output: 'xml' | 'pdf';
|
|
30
|
+
/** API `profile`; omitted lets the engine pick the standard's default. */
|
|
31
|
+
profile?: string;
|
|
32
|
+
/** API `facturxProfile`; Factur-X / ZUGFeRD only. */
|
|
33
|
+
facturxProfile?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Named generate targets surfaced to end users (connector dropdowns), mirroring
|
|
37
|
+
* the public set on beliq.eu's own generator. NLCIUS is a Peppol BIS profile,
|
|
38
|
+
* not a standalone standard, so it is reachable here rather than through
|
|
39
|
+
* LIVE_GENERATE_STANDARDS or the Factur-X-only LIVE_PROFILES.
|
|
40
|
+
*/
|
|
41
|
+
declare const LIVE_GENERATE_PRESETS: readonly GeneratePreset[];
|
|
42
|
+
/**
|
|
43
|
+
* The Factur-X granularity values offered publicly. Kept as the flat list the
|
|
44
|
+
* hybrid-PDF family shares; anything choosing a profile for a specific standard
|
|
45
|
+
* wants LIVE_PROFILES_BY_STANDARD instead, which is what the API enforces.
|
|
46
|
+
*/
|
|
47
|
+
declare const LIVE_PROFILES: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
48
|
+
/**
|
|
49
|
+
* Which profiles each standard accepts, publicly-offered values only.
|
|
50
|
+
*
|
|
51
|
+
* `profile` is not a free enum: the engine pins it per standard and answers a
|
|
52
|
+
* pair outside the table with `422 PROFILE_STANDARD_MISMATCH`
|
|
53
|
+
* (beliq-engine `app/routes/generate.py`, ALLOWED_PROFILES_FOR_STANDARD). A
|
|
54
|
+
* surface that offers one flat profile list therefore offers values that cannot
|
|
55
|
+
* succeed: none of the Factur-X granularity values is legal for `xrechnung` or
|
|
56
|
+
* `peppol-bis`, and `extended-ctc-fr` is the AFNOR XP Z12-012 France CTC overlay
|
|
57
|
+
* with no ZUGFeRD-branded counterpart.
|
|
58
|
+
*
|
|
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.
|
|
63
|
+
*
|
|
64
|
+
* `scripts/check-profile-drift.mjs` compares this against the engine's table.
|
|
65
|
+
*/
|
|
66
|
+
declare const LIVE_PROFILES_BY_STANDARD: {
|
|
67
|
+
readonly xrechnung: readonly ["xrechnung"];
|
|
68
|
+
readonly 'peppol-bis': readonly ["peppol", "romania-ro-cius", "netherlands-nlcius"];
|
|
69
|
+
readonly zugferd: readonly ["basicwl", "en16931", "extended"];
|
|
70
|
+
readonly facturx: readonly ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
71
|
+
};
|
|
72
|
+
/** The profiles a caller may choose for `standard`; empty for an unknown standard. */
|
|
73
|
+
declare function profilesForStandard(standard: string): readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* Whether `profile` is legal for `standard`. An unknown standard passes: the API
|
|
76
|
+
* is the authority on values this list does not carry, and a client-side guess
|
|
77
|
+
* would refuse a request the server would have accepted.
|
|
78
|
+
*/
|
|
79
|
+
declare function isProfileAllowedForStandard(standard: string, profile: string): boolean;
|
|
80
|
+
declare const LIVE_VALIDATE_FORMATS: readonly ["auto", "cii", "ubl"];
|
|
81
|
+
declare const LIVE_PARSE_FORMATS: readonly ["auto", "cii", "ubl"];
|
|
82
|
+
declare const LIVE_CONVERT_SOURCE_FORMATS: readonly ["auto", "cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
|
|
83
|
+
declare const LIVE_CONVERT_TARGET_FORMATS: readonly ["cii", "ubl", "zugferd", "facturx", "xrechnung", "peppol-bis"];
|
|
84
|
+
|
|
85
|
+
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_PROFILES_BY_STANDARD as g, LIVE_VALIDATE_FORMATS as h, compactQuery as i, decodeUtf8 as j, isPlainObject as k, isProfileAllowedForStandard as l, mergeDeep as m, DEFAULT_MAX_RETRIES as n, DEFAULT_TIMEOUT_MS as o, profilesForStandard as p, sniffContentType as s, toBytes as t };
|
package/dist/helpers.cjs
CHANGED
|
@@ -27,12 +27,15 @@ __export(helpers_exports, {
|
|
|
27
27
|
LIVE_GENERATE_STANDARDS: () => LIVE_GENERATE_STANDARDS,
|
|
28
28
|
LIVE_PARSE_FORMATS: () => LIVE_PARSE_FORMATS,
|
|
29
29
|
LIVE_PROFILES: () => LIVE_PROFILES,
|
|
30
|
+
LIVE_PROFILES_BY_STANDARD: () => LIVE_PROFILES_BY_STANDARD,
|
|
30
31
|
LIVE_VALIDATE_FORMATS: () => LIVE_VALIDATE_FORMATS,
|
|
31
32
|
buildRequest: () => buildRequest,
|
|
32
33
|
compactQuery: () => compactQuery,
|
|
33
34
|
decodeUtf8: () => decodeUtf8,
|
|
34
35
|
isPlainObject: () => isPlainObject,
|
|
36
|
+
isProfileAllowedForStandard: () => isProfileAllowedForStandard,
|
|
35
37
|
mergeDeep: () => mergeDeep,
|
|
38
|
+
profilesForStandard: () => profilesForStandard,
|
|
36
39
|
sniffContentType: () => sniffContentType,
|
|
37
40
|
toBytes: () => toBytes
|
|
38
41
|
});
|
|
@@ -171,6 +174,19 @@ var LIVE_GENERATE_PRESETS = [
|
|
|
171
174
|
{ id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
|
|
172
175
|
];
|
|
173
176
|
var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
177
|
+
var LIVE_PROFILES_BY_STANDARD = {
|
|
178
|
+
xrechnung: ["xrechnung"],
|
|
179
|
+
"peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
|
|
180
|
+
zugferd: ["basicwl", "en16931", "extended"],
|
|
181
|
+
facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
|
|
182
|
+
};
|
|
183
|
+
function profilesForStandard(standard) {
|
|
184
|
+
return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
|
|
185
|
+
}
|
|
186
|
+
function isProfileAllowedForStandard(standard, profile) {
|
|
187
|
+
const allowed = profilesForStandard(standard);
|
|
188
|
+
return allowed.length === 0 || allowed.includes(profile);
|
|
189
|
+
}
|
|
174
190
|
var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
|
|
175
191
|
var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
|
|
176
192
|
var LIVE_CONVERT_SOURCE_FORMATS = [
|
|
@@ -199,12 +215,15 @@ var LIVE_CONVERT_TARGET_FORMATS = [
|
|
|
199
215
|
LIVE_GENERATE_STANDARDS,
|
|
200
216
|
LIVE_PARSE_FORMATS,
|
|
201
217
|
LIVE_PROFILES,
|
|
218
|
+
LIVE_PROFILES_BY_STANDARD,
|
|
202
219
|
LIVE_VALIDATE_FORMATS,
|
|
203
220
|
buildRequest,
|
|
204
221
|
compactQuery,
|
|
205
222
|
decodeUtf8,
|
|
206
223
|
isPlainObject,
|
|
224
|
+
isProfileAllowedForStandard,
|
|
207
225
|
mergeDeep,
|
|
226
|
+
profilesForStandard,
|
|
208
227
|
sniffContentType,
|
|
209
228
|
toBytes
|
|
210
229
|
});
|
package/dist/helpers.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PlainObject } from './constants-
|
|
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
|
|
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';
|
|
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-
|
|
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
|
|
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';
|
|
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
|
@@ -131,6 +131,19 @@ var LIVE_GENERATE_PRESETS = [
|
|
|
131
131
|
{ id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
|
|
132
132
|
];
|
|
133
133
|
var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
134
|
+
var LIVE_PROFILES_BY_STANDARD = {
|
|
135
|
+
xrechnung: ["xrechnung"],
|
|
136
|
+
"peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
|
|
137
|
+
zugferd: ["basicwl", "en16931", "extended"],
|
|
138
|
+
facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
|
|
139
|
+
};
|
|
140
|
+
function profilesForStandard(standard) {
|
|
141
|
+
return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
|
|
142
|
+
}
|
|
143
|
+
function isProfileAllowedForStandard(standard, profile) {
|
|
144
|
+
const allowed = profilesForStandard(standard);
|
|
145
|
+
return allowed.length === 0 || allowed.includes(profile);
|
|
146
|
+
}
|
|
134
147
|
var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
|
|
135
148
|
var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
|
|
136
149
|
var LIVE_CONVERT_SOURCE_FORMATS = [
|
|
@@ -158,12 +171,15 @@ export {
|
|
|
158
171
|
LIVE_GENERATE_STANDARDS,
|
|
159
172
|
LIVE_PARSE_FORMATS,
|
|
160
173
|
LIVE_PROFILES,
|
|
174
|
+
LIVE_PROFILES_BY_STANDARD,
|
|
161
175
|
LIVE_VALIDATE_FORMATS,
|
|
162
176
|
buildRequest,
|
|
163
177
|
compactQuery,
|
|
164
178
|
decodeUtf8,
|
|
165
179
|
isPlainObject,
|
|
180
|
+
isProfileAllowedForStandard,
|
|
166
181
|
mergeDeep,
|
|
182
|
+
profilesForStandard,
|
|
167
183
|
sniffContentType,
|
|
168
184
|
toBytes
|
|
169
185
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -23,13 +23,18 @@ __export(index_exports, {
|
|
|
23
23
|
Beliq: () => Beliq,
|
|
24
24
|
BeliqApiError: () => BeliqApiError,
|
|
25
25
|
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
26
|
+
DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES,
|
|
27
|
+
DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
|
|
26
28
|
LIVE_CONVERT_SOURCE_FORMATS: () => LIVE_CONVERT_SOURCE_FORMATS,
|
|
27
29
|
LIVE_CONVERT_TARGET_FORMATS: () => LIVE_CONVERT_TARGET_FORMATS,
|
|
28
30
|
LIVE_GENERATE_PRESETS: () => LIVE_GENERATE_PRESETS,
|
|
29
31
|
LIVE_GENERATE_STANDARDS: () => LIVE_GENERATE_STANDARDS,
|
|
30
32
|
LIVE_PARSE_FORMATS: () => LIVE_PARSE_FORMATS,
|
|
31
33
|
LIVE_PROFILES: () => LIVE_PROFILES,
|
|
32
|
-
|
|
34
|
+
LIVE_PROFILES_BY_STANDARD: () => LIVE_PROFILES_BY_STANDARD,
|
|
35
|
+
LIVE_VALIDATE_FORMATS: () => LIVE_VALIDATE_FORMATS,
|
|
36
|
+
isProfileAllowedForStandard: () => isProfileAllowedForStandard,
|
|
37
|
+
profilesForStandard: () => profilesForStandard
|
|
33
38
|
});
|
|
34
39
|
module.exports = __toCommonJS(index_exports);
|
|
35
40
|
|
|
@@ -204,6 +209,8 @@ function errorFromResponse(status, bytes) {
|
|
|
204
209
|
|
|
205
210
|
// src/constants.ts
|
|
206
211
|
var DEFAULT_BASE_URL = "https://api.beliq.eu";
|
|
212
|
+
var DEFAULT_TIMEOUT_MS = 9e4;
|
|
213
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
207
214
|
var LIVE_GENERATE_STANDARDS = ["xrechnung", "zugferd", "facturx", "peppol-bis"];
|
|
208
215
|
var LIVE_GENERATE_PRESETS = [
|
|
209
216
|
{ id: "xrechnung", label: "XRechnung", standard: "xrechnung", output: "xml" },
|
|
@@ -213,6 +220,19 @@ var LIVE_GENERATE_PRESETS = [
|
|
|
213
220
|
{ id: "nlcius", label: "NLCIUS", standard: "peppol-bis", output: "xml", profile: "netherlands-nlcius" }
|
|
214
221
|
];
|
|
215
222
|
var LIVE_PROFILES = ["basicwl", "en16931", "extended", "extended-ctc-fr"];
|
|
223
|
+
var LIVE_PROFILES_BY_STANDARD = {
|
|
224
|
+
xrechnung: ["xrechnung"],
|
|
225
|
+
"peppol-bis": ["peppol", "romania-ro-cius", "netherlands-nlcius"],
|
|
226
|
+
zugferd: ["basicwl", "en16931", "extended"],
|
|
227
|
+
facturx: ["basicwl", "en16931", "extended", "extended-ctc-fr"]
|
|
228
|
+
};
|
|
229
|
+
function profilesForStandard(standard) {
|
|
230
|
+
return LIVE_PROFILES_BY_STANDARD[standard] ?? [];
|
|
231
|
+
}
|
|
232
|
+
function isProfileAllowedForStandard(standard, profile) {
|
|
233
|
+
const allowed = profilesForStandard(standard);
|
|
234
|
+
return allowed.length === 0 || allowed.includes(profile);
|
|
235
|
+
}
|
|
216
236
|
var LIVE_VALIDATE_FORMATS = ["auto", "cii", "ubl"];
|
|
217
237
|
var LIVE_PARSE_FORMATS = ["auto", "cii", "ubl"];
|
|
218
238
|
var LIVE_CONVERT_SOURCE_FORMATS = [
|
|
@@ -234,6 +254,9 @@ var LIVE_CONVERT_TARGET_FORMATS = [
|
|
|
234
254
|
];
|
|
235
255
|
|
|
236
256
|
// src/transport.ts
|
|
257
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503]);
|
|
258
|
+
var MAX_RETRY_AFTER_MS = 3e4;
|
|
259
|
+
var BACKOFF_BASE_MS = 500;
|
|
237
260
|
function authHeaders(config) {
|
|
238
261
|
return config.auth === "bearer" ? { Authorization: `Bearer ${config.apiKey}` } : { "X-API-Key": config.apiKey };
|
|
239
262
|
}
|
|
@@ -247,19 +270,58 @@ function buildUrl(baseUrl, path, query) {
|
|
|
247
270
|
const qs = params.toString();
|
|
248
271
|
return qs ? `${baseUrl}${path}?${qs}` : `${baseUrl}${path}`;
|
|
249
272
|
}
|
|
273
|
+
function retryDelayMs(res, attempt) {
|
|
274
|
+
const header = res?.headers.get("retry-after");
|
|
275
|
+
if (header) {
|
|
276
|
+
const seconds = Number(header);
|
|
277
|
+
if (Number.isFinite(seconds) && seconds >= 0) {
|
|
278
|
+
return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS) + Math.random() * 250;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const backoff = BACKOFF_BASE_MS * 2 ** attempt;
|
|
282
|
+
return backoff + Math.random() * backoff;
|
|
283
|
+
}
|
|
284
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
250
285
|
async function send(config, req) {
|
|
251
286
|
const headers = { ...authHeaders(config) };
|
|
252
287
|
if (req.contentType) headers["Content-Type"] = req.contentType;
|
|
253
288
|
if (req.accept) headers["Accept"] = req.accept;
|
|
254
289
|
const body = req.jsonBody !== void 0 ? JSON.stringify(req.jsonBody) : req.rawBody;
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
const url = buildUrl(config.baseUrl, req.path, req.query);
|
|
291
|
+
let lastError;
|
|
292
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
293
|
+
const controller = new AbortController();
|
|
294
|
+
const timer = config.timeoutMs > 0 ? setTimeout(() => controller.abort(), config.timeoutMs) : void 0;
|
|
295
|
+
let res;
|
|
296
|
+
try {
|
|
297
|
+
res = await config.fetchImpl(url, {
|
|
298
|
+
method: req.method,
|
|
299
|
+
headers,
|
|
300
|
+
body,
|
|
301
|
+
signal: controller.signal
|
|
302
|
+
});
|
|
303
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
304
|
+
if (res.ok) return { status: res.status, headers: res.headers, bytes };
|
|
305
|
+
lastError = errorFromResponse(res.status, bytes);
|
|
306
|
+
if (!RETRYABLE_STATUSES.has(res.status) || attempt === config.maxRetries) {
|
|
307
|
+
throw lastError;
|
|
308
|
+
}
|
|
309
|
+
} catch (err) {
|
|
310
|
+
if (err instanceof BeliqApiError && !RETRYABLE_STATUSES.has(err.status)) throw err;
|
|
311
|
+
if (controller.signal.aborted) {
|
|
312
|
+
throw new BeliqApiError(
|
|
313
|
+
`beliq: request to ${req.path} exceeded ${config.timeoutMs}ms`,
|
|
314
|
+
{ status: 0, code: "TIMEOUT" }
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
lastError = err;
|
|
318
|
+
if (attempt === config.maxRetries) throw err;
|
|
319
|
+
} finally {
|
|
320
|
+
if (timer) clearTimeout(timer);
|
|
321
|
+
}
|
|
322
|
+
await sleep(retryDelayMs(res, attempt));
|
|
323
|
+
}
|
|
324
|
+
throw lastError;
|
|
263
325
|
}
|
|
264
326
|
|
|
265
327
|
// src/client.ts
|
|
@@ -330,7 +392,9 @@ var Beliq = class {
|
|
|
330
392
|
apiKey: options.apiKey,
|
|
331
393
|
baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
|
|
332
394
|
auth: options.auth ?? "header",
|
|
333
|
-
fetchImpl
|
|
395
|
+
fetchImpl,
|
|
396
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
397
|
+
maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
334
398
|
};
|
|
335
399
|
}
|
|
336
400
|
/** Account, plan, and quota context for the key. Does not consume quota. */
|
|
@@ -431,11 +495,16 @@ var Beliq = class {
|
|
|
431
495
|
Beliq,
|
|
432
496
|
BeliqApiError,
|
|
433
497
|
DEFAULT_BASE_URL,
|
|
498
|
+
DEFAULT_MAX_RETRIES,
|
|
499
|
+
DEFAULT_TIMEOUT_MS,
|
|
434
500
|
LIVE_CONVERT_SOURCE_FORMATS,
|
|
435
501
|
LIVE_CONVERT_TARGET_FORMATS,
|
|
436
502
|
LIVE_GENERATE_PRESETS,
|
|
437
503
|
LIVE_GENERATE_STANDARDS,
|
|
438
504
|
LIVE_PARSE_FORMATS,
|
|
439
505
|
LIVE_PROFILES,
|
|
440
|
-
|
|
506
|
+
LIVE_PROFILES_BY_STANDARD,
|
|
507
|
+
LIVE_VALIDATE_FORMATS,
|
|
508
|
+
isProfileAllowedForStandard,
|
|
509
|
+
profilesForStandard
|
|
441
510
|
});
|