extractia-sdk 1.2.0 → 1.4.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 +14 -14
- package/dist/extractia-sdk.browser.js +516 -82
- package/dist/extractia-sdk.cjs.js +499 -87
- package/dist/extractia-sdk.esm.js +499 -87
- package/dist/index.d.ts +197 -15
- package/package.json +22 -4
- package/src/apiClient.js +189 -23
- package/src/browser-entry.js +35 -0
- package/src/errors.js +278 -40
- package/src/index.d.ts +197 -15
- package/src/index.js +21 -0
- package/src/subusers.js +40 -16
- package/src/utils.js +219 -0
- package/dist/extractia-sdk.browser.js.map +0 -7
- package/dist/extractia-sdk.cjs.js.map +0 -7
- package/dist/extractia-sdk.esm.js.map +0 -7
- package/dist/extractia-sdk.js.map +0 -7
package/dist/index.d.ts
CHANGED
|
@@ -206,45 +206,94 @@ export interface OcrRunResult {
|
|
|
206
206
|
|
|
207
207
|
/** Base error class for all Extractia SDK errors. */
|
|
208
208
|
export class ExtractiaError extends Error {
|
|
209
|
-
/** HTTP status code
|
|
209
|
+
/** HTTP status code (0 = no response). */
|
|
210
210
|
status: number;
|
|
211
|
-
|
|
211
|
+
/** Polished, user-facing English sentence always suitable for display. */
|
|
212
|
+
userMessage: string;
|
|
213
|
+
/** Machine-readable error code (e.g. "AUTH_ERROR", "QUOTA_EXCEEDED"). */
|
|
214
|
+
code: string;
|
|
215
|
+
/** X-Request-Id / X-Correlation-Id from the server response header, when present. */
|
|
216
|
+
requestId: string | null;
|
|
217
|
+
constructor(message: string, status?: number, userMessage?: string, code?: string);
|
|
218
|
+
/** Returns true if automatically retrying the same request may succeed. */
|
|
219
|
+
isRetryable(): boolean;
|
|
220
|
+
toJSON(): { name: string; code: string; status: number; message: string; userMessage: string; requestId: string | null };
|
|
212
221
|
}
|
|
213
222
|
|
|
214
|
-
/**
|
|
223
|
+
/** HTTP 401 — token missing, expired, or malformed. */
|
|
215
224
|
export class AuthError extends ExtractiaError {
|
|
216
225
|
constructor(message?: string);
|
|
217
226
|
}
|
|
218
227
|
|
|
219
|
-
/**
|
|
228
|
+
/** HTTP 403 — authenticated but lacking required permission. */
|
|
220
229
|
export class ForbiddenError extends ExtractiaError {
|
|
221
230
|
constructor(message?: string);
|
|
222
231
|
}
|
|
223
232
|
|
|
224
|
-
/**
|
|
233
|
+
/** HTTP 402 — plan tier does not include this feature. */
|
|
225
234
|
export class TierError extends ExtractiaError {
|
|
226
235
|
constructor(message?: string, status?: number);
|
|
227
236
|
}
|
|
228
237
|
|
|
229
|
-
/**
|
|
230
|
-
export class
|
|
231
|
-
/** Seconds to wait before the next request. */
|
|
232
|
-
retryAfter?: number;
|
|
238
|
+
/** HTTP 402 — document processing quota exhausted for this billing period. */
|
|
239
|
+
export class QuotaError extends ExtractiaError {
|
|
233
240
|
constructor(message?: string);
|
|
234
241
|
}
|
|
235
242
|
|
|
236
|
-
/**
|
|
243
|
+
/** HTTP 429 — requests sent too fast. Check `retryAfter` for the suggested wait time. */
|
|
244
|
+
export class RateLimitError extends ExtractiaError {
|
|
245
|
+
/** Seconds to wait before retrying (from the Retry-After header), or null. */
|
|
246
|
+
retryAfter: number | null;
|
|
247
|
+
constructor(message?: string, retryAfter?: number | null);
|
|
248
|
+
isRetryable(): true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** HTTP 404 — the requested resource does not exist. */
|
|
237
252
|
export class NotFoundError extends ExtractiaError {
|
|
238
253
|
constructor(message?: string);
|
|
239
254
|
}
|
|
240
255
|
|
|
256
|
+
/** HTTP 400 — request body / parameters failed server-side validation. */
|
|
257
|
+
export class ValidationError extends ExtractiaError {
|
|
258
|
+
/** Field-level errors, if the server provided them. */
|
|
259
|
+
fields: Record<string, string> | null;
|
|
260
|
+
constructor(message?: string, fields?: Record<string, string> | null);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** HTTP 409 — a resource with the same unique identifier already exists. */
|
|
264
|
+
export class ConflictError extends ExtractiaError {
|
|
265
|
+
constructor(message?: string);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** HTTP 5xx — unexpected server-side failure. Always retryable. */
|
|
269
|
+
export class ServerError extends ExtractiaError {
|
|
270
|
+
constructor(message?: string, status?: number);
|
|
271
|
+
isRetryable(): true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** No HTTP response — connection refused, DNS failure, etc. */
|
|
275
|
+
export class NetworkError extends ExtractiaError {
|
|
276
|
+
constructor(message?: string);
|
|
277
|
+
isRetryable(): true;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Request timed out before the server responded. */
|
|
281
|
+
export class TimeoutError extends ExtractiaError {
|
|
282
|
+
constructor(message?: string);
|
|
283
|
+
isRetryable(): true;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** Maps an Axios error to the appropriate typed SDK error. */
|
|
287
|
+
export function mapAxiosError(err: unknown): ExtractiaError;
|
|
288
|
+
|
|
241
289
|
// ─── Setup ────────────────────────────────────────────────────────────────────
|
|
242
290
|
|
|
243
291
|
/**
|
|
244
292
|
* Sets the Bearer API token used for all subsequent requests.
|
|
245
293
|
* **Must be called before any SDK method.**
|
|
246
294
|
*
|
|
247
|
-
* @param token Your Extractia API
|
|
295
|
+
* @param token Your Extractia API key (from Account → API Tokens).
|
|
296
|
+
* @throws {Error} If the token is empty or not a string.
|
|
248
297
|
*
|
|
249
298
|
* @example
|
|
250
299
|
* import { setToken } from 'extractia-sdk';
|
|
@@ -252,12 +301,59 @@ export class NotFoundError extends ExtractiaError {
|
|
|
252
301
|
*/
|
|
253
302
|
export function setToken(token: string): void;
|
|
254
303
|
|
|
304
|
+
/** Returns the currently configured API token, or `null` if not set. */
|
|
305
|
+
export function getToken(): string | null;
|
|
306
|
+
|
|
307
|
+
/** Returns `true` if an API token has been set. */
|
|
308
|
+
export function hasToken(): boolean;
|
|
309
|
+
|
|
310
|
+
/** Clears the stored API token. Useful for logout flows or test teardown. */
|
|
311
|
+
export function clearToken(): void;
|
|
312
|
+
|
|
313
|
+
/** Returns a snapshot of the current SDK configuration (token excluded). */
|
|
314
|
+
export function getConfig(): {
|
|
315
|
+
baseURL: string;
|
|
316
|
+
timeout: number;
|
|
317
|
+
retries: number;
|
|
318
|
+
retryDelay: number;
|
|
319
|
+
debug: boolean;
|
|
320
|
+
defaultHeaders: Record<string, string>;
|
|
321
|
+
onBeforeRequest: Function | null;
|
|
322
|
+
onAfterResponse: Function | null;
|
|
323
|
+
onError: Function | null;
|
|
324
|
+
};
|
|
325
|
+
|
|
255
326
|
/**
|
|
256
|
-
* Configures SDK
|
|
257
|
-
*
|
|
258
|
-
* @
|
|
327
|
+
* Configures SDK behaviour. All properties are optional.
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* configure({
|
|
331
|
+
* timeout: 30_000,
|
|
332
|
+
* retries: 2,
|
|
333
|
+
* debug: true,
|
|
334
|
+
* onError: (err) => sentryCapture(err),
|
|
335
|
+
* });
|
|
259
336
|
*/
|
|
260
|
-
export function configure(opts: {
|
|
337
|
+
export function configure(opts: {
|
|
338
|
+
/** Override the API base URL (useful for staging or proxies). */
|
|
339
|
+
baseURL?: string;
|
|
340
|
+
/** Request timeout in milliseconds. Default: 60 000. */
|
|
341
|
+
timeout?: number;
|
|
342
|
+
/** Automatic retries on retryable errors (429 / 5xx / network). Default: 1. */
|
|
343
|
+
retries?: number;
|
|
344
|
+
/** Base delay (ms) between retries; multiplied by attempt number. Default: 1 000. */
|
|
345
|
+
retryDelay?: number;
|
|
346
|
+
/** Log requests / responses / retries to console.debug. Default: false. */
|
|
347
|
+
debug?: boolean;
|
|
348
|
+
/** Extra headers merged into every request. */
|
|
349
|
+
defaultHeaders?: Record<string, string>;
|
|
350
|
+
/** Hook called before each request. Return a modified config or void. */
|
|
351
|
+
onBeforeRequest?: (config: unknown) => unknown | void;
|
|
352
|
+
/** Hook called after each successful response. */
|
|
353
|
+
onAfterResponse?: (response: unknown) => void;
|
|
354
|
+
/** Hook called with the mapped SDK error whenever a request fails (after retries). */
|
|
355
|
+
onError?: (error: ExtractiaError) => void;
|
|
356
|
+
}): void;
|
|
261
357
|
|
|
262
358
|
// ─── Auth / Profile ───────────────────────────────────────────────────────────
|
|
263
359
|
|
|
@@ -694,11 +790,87 @@ export function toggleSuspendSubUser(username: string): Promise<{ username: stri
|
|
|
694
790
|
|
|
695
791
|
// ─── Default export ───────────────────────────────────────────────────────────
|
|
696
792
|
|
|
793
|
+
// ─── Utilities ───────────────────────────────────────────────────────────────
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Converts a browser `File` or `Blob` to a base64 data-URL string.
|
|
797
|
+
* @throws {Error} In Node.js environments where `FileReader` is unavailable.
|
|
798
|
+
*/
|
|
799
|
+
export function fileToBase64(file: File | Blob): Promise<string>;
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Strips the `data:…;base64,` prefix from a base64 string.
|
|
803
|
+
* Safe to call on a plain base64 string — returns it unchanged.
|
|
804
|
+
*/
|
|
805
|
+
export function stripDataUrlPrefix(base64OrDataUrl: string): string;
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Returns the MIME type embedded in a data-URL prefix, or `null`.
|
|
809
|
+
* @example getMimeType('data:image/png;base64,...') // → 'image/png'
|
|
810
|
+
*/
|
|
811
|
+
export function getMimeType(dataUrl: string): string | null;
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Returns `true` if the string is a valid base64-encoded value
|
|
815
|
+
* (with or without a data-URL prefix).
|
|
816
|
+
*/
|
|
817
|
+
export function isBase64(str: string): boolean;
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Accepts a `File`, `Blob`, or base64 string and always resolves to a
|
|
821
|
+
* base64 string — the data-URL for files and the string as-is otherwise.
|
|
822
|
+
*/
|
|
823
|
+
export function ensureBase64(fileOrBase64: File | Blob | string): Promise<string>;
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Async generator that yields individual items across all pages of a
|
|
827
|
+
* paginated SDK function.
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* for await (const entry of paginate(getCreditsHistory, { size: 100 })) {
|
|
831
|
+
* console.log(entry);
|
|
832
|
+
* }
|
|
833
|
+
*/
|
|
834
|
+
export function paginate<T>(
|
|
835
|
+
fn: (opts: { page: number; size: number }) => Promise<{ content: T[]; totalPages: number }>,
|
|
836
|
+
opts?: { size?: number; startPage?: number; maxPages?: number }
|
|
837
|
+
): AsyncGenerator<T>;
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Collects all pages of a paginated SDK function into a flat array.
|
|
841
|
+
*/
|
|
842
|
+
export function paginateAll<T>(
|
|
843
|
+
fn: (opts: { page: number; size: number }) => Promise<{ content: T[]; totalPages: number }>,
|
|
844
|
+
opts?: { size?: number; startPage?: number; maxPages?: number }
|
|
845
|
+
): Promise<T[]>;
|
|
846
|
+
|
|
847
|
+
/** Returns a Promise that resolves after `ms` milliseconds. */
|
|
848
|
+
export function delay(ms: number): Promise<void>;
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Calls an async function and retries it with exponential back-off on
|
|
852
|
+
* retryable `ExtractiaError`s.
|
|
853
|
+
*/
|
|
854
|
+
export function withRetry<T>(
|
|
855
|
+
fn: () => Promise<T>,
|
|
856
|
+
opts?: {
|
|
857
|
+
retries?: number;
|
|
858
|
+
initialDelay?: number;
|
|
859
|
+
shouldRetry?: (err: Error) => boolean;
|
|
860
|
+
}
|
|
861
|
+
): Promise<T>;
|
|
862
|
+
|
|
863
|
+
// ─── Default export ───────────────────────────────────────────────────────────
|
|
864
|
+
|
|
697
865
|
/** Namespace object bundling all SDK methods for UMD / CommonJS consumers. */
|
|
698
866
|
declare const extractia: {
|
|
699
867
|
// Setup
|
|
700
868
|
setToken: typeof setToken;
|
|
869
|
+
getToken: typeof getToken;
|
|
870
|
+
hasToken: typeof hasToken;
|
|
871
|
+
clearToken: typeof clearToken;
|
|
701
872
|
configure: typeof configure;
|
|
873
|
+
getConfig: typeof getConfig;
|
|
702
874
|
// Auth
|
|
703
875
|
getMyProfile: typeof getMyProfile;
|
|
704
876
|
updateWebhook: typeof updateWebhook;
|
|
@@ -741,6 +913,16 @@ declare const extractia: {
|
|
|
741
913
|
deleteSubUser: typeof deleteSubUser;
|
|
742
914
|
updateSubUser: typeof updateSubUser;
|
|
743
915
|
toggleSuspendSubUser: typeof toggleSuspendSubUser;
|
|
916
|
+
// Utilities
|
|
917
|
+
fileToBase64: typeof fileToBase64;
|
|
918
|
+
stripDataUrlPrefix: typeof stripDataUrlPrefix;
|
|
919
|
+
getMimeType: typeof getMimeType;
|
|
920
|
+
isBase64: typeof isBase64;
|
|
921
|
+
ensureBase64: typeof ensureBase64;
|
|
922
|
+
paginate: typeof paginate;
|
|
923
|
+
paginateAll: typeof paginateAll;
|
|
924
|
+
delay: typeof delay;
|
|
925
|
+
withRetry: typeof withRetry;
|
|
744
926
|
};
|
|
745
927
|
|
|
746
928
|
export default extractia;
|
package/package.json
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extractia-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "JavaScript SDK for the ExtractIA API — document extraction, OCR tools, AI summaries, templates & more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "ExtractIA Team",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"homepage": "https://www.extractia.info/docs/sdk",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/extractia/extractia-sdk"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/extractia/extractia-sdk/issues",
|
|
15
|
+
"email": "support@extractia.info"
|
|
16
|
+
},
|
|
8
17
|
"keywords": [
|
|
9
18
|
"sdk",
|
|
10
19
|
"extractia",
|
|
@@ -14,7 +23,10 @@
|
|
|
14
23
|
"client",
|
|
15
24
|
"document-extraction",
|
|
16
25
|
"ai",
|
|
17
|
-
"gemini"
|
|
26
|
+
"gemini",
|
|
27
|
+
"document-ai",
|
|
28
|
+
"typescript",
|
|
29
|
+
"data-extraction"
|
|
18
30
|
],
|
|
19
31
|
"main": "dist/extractia-sdk.cjs.js",
|
|
20
32
|
"module": "dist/extractia-sdk.esm.js",
|
|
@@ -34,12 +46,18 @@
|
|
|
34
46
|
},
|
|
35
47
|
"scripts": {
|
|
36
48
|
"build": "node build.js",
|
|
37
|
-
"test": "
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest",
|
|
51
|
+
"test:coverage": "vitest run --coverage",
|
|
52
|
+
"test:ui": "vitest --ui"
|
|
38
53
|
},
|
|
39
54
|
"dependencies": {
|
|
40
55
|
"axios": "^1.10.0"
|
|
41
56
|
},
|
|
42
57
|
"devDependencies": {
|
|
43
|
-
"
|
|
58
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
59
|
+
"axios-mock-adapter": "^2.1.0",
|
|
60
|
+
"esbuild": "^0.25.6",
|
|
61
|
+
"vitest": "^2.1.9"
|
|
44
62
|
}
|
|
45
63
|
}
|
package/src/apiClient.js
CHANGED
|
@@ -1,46 +1,212 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
mapAxiosError,
|
|
4
|
+
ExtractiaError,
|
|
5
|
+
NetworkError,
|
|
6
|
+
TimeoutError,
|
|
7
|
+
} from "./errors.js";
|
|
3
8
|
|
|
4
|
-
|
|
9
|
+
// ─── Internal state ───────────────────────────────────────────────────────────
|
|
5
10
|
|
|
6
|
-
|
|
11
|
+
let _token = null;
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
/** @type {SDKConfig} */
|
|
14
|
+
const _config = {
|
|
15
|
+
baseURL: "https://api.extractia.info/api/public",
|
|
16
|
+
timeout: 60_000,
|
|
17
|
+
retries: 1,
|
|
18
|
+
retryDelay: 1_000,
|
|
19
|
+
debug: false,
|
|
20
|
+
defaultHeaders: {},
|
|
21
|
+
onBeforeRequest: null,
|
|
22
|
+
onAfterResponse: null,
|
|
23
|
+
onError: null,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// ─── Axios instance ───────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
export const _api = axios.create({
|
|
29
|
+
baseURL: _config.baseURL,
|
|
30
|
+
timeout: _config.timeout,
|
|
11
31
|
});
|
|
12
32
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
33
|
+
// ── Request interceptor ──────────────────────────────────────────────────────
|
|
34
|
+
_api.interceptors.request.use((config) => {
|
|
35
|
+
if (!_token) {
|
|
36
|
+
const err = new ExtractiaError(
|
|
37
|
+
"API token not set. Call setToken(token) before making requests.",
|
|
38
|
+
0,
|
|
39
|
+
"API token not set. Call setToken(token) before making requests.",
|
|
40
|
+
"TOKEN_MISSING",
|
|
41
|
+
);
|
|
42
|
+
return Promise.reject(err);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
config.headers = config.headers ?? {};
|
|
46
|
+
config.headers["Authorization"] = `Bearer ${_token}`;
|
|
47
|
+
|
|
48
|
+
// Apply default headers
|
|
49
|
+
Object.assign(config.headers, _config.defaultHeaders);
|
|
50
|
+
|
|
51
|
+
if (_config.debug) {
|
|
52
|
+
console.debug(
|
|
53
|
+
`[ExtractIA SDK] → ${(config.method ?? "GET").toUpperCase()} ${config.baseURL ?? ""}${config.url ?? ""}`,
|
|
54
|
+
config.params ?? "",
|
|
17
55
|
);
|
|
18
56
|
}
|
|
19
|
-
|
|
57
|
+
|
|
58
|
+
if (typeof _config.onBeforeRequest === "function") {
|
|
59
|
+
const modified = _config.onBeforeRequest(config);
|
|
60
|
+
return modified ?? config;
|
|
61
|
+
}
|
|
62
|
+
|
|
20
63
|
return config;
|
|
21
64
|
});
|
|
22
65
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(
|
|
66
|
+
// ── Response interceptor ─────────────────────────────────────────────────────
|
|
67
|
+
_api.interceptors.response.use(
|
|
68
|
+
(response) => {
|
|
69
|
+
if (_config.debug) {
|
|
70
|
+
console.debug(
|
|
71
|
+
`[ExtractIA SDK] ← ${response.status} ${response.config?.url ?? ""}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (typeof _config.onAfterResponse === "function") {
|
|
75
|
+
_config.onAfterResponse(response);
|
|
76
|
+
}
|
|
77
|
+
return response;
|
|
78
|
+
},
|
|
79
|
+
async (err) => {
|
|
80
|
+
// If already a typed ExtractiaError (e.g. from request interceptor), pass through
|
|
81
|
+
if (err instanceof ExtractiaError) {
|
|
82
|
+
if (typeof _config.onError === "function") _config.onError(err);
|
|
83
|
+
return Promise.reject(err);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const mapped = mapAxiosError(err);
|
|
87
|
+
const cfg = err.config;
|
|
88
|
+
|
|
89
|
+
// Automatic retry for retryable errors (429 / 5xx / network / timeout)
|
|
90
|
+
if (
|
|
91
|
+
cfg &&
|
|
92
|
+
mapped.isRetryable() &&
|
|
93
|
+
(cfg._retryCount ?? 0) < _config.retries
|
|
94
|
+
) {
|
|
95
|
+
cfg._retryCount = (cfg._retryCount ?? 0) + 1;
|
|
96
|
+
|
|
97
|
+
// Honour Retry-After header for rate limits, otherwise exponential back-off
|
|
98
|
+
const delayMs =
|
|
99
|
+
mapped.retryAfter != null
|
|
100
|
+
? mapped.retryAfter * 1_000
|
|
101
|
+
: _config.retryDelay * cfg._retryCount;
|
|
102
|
+
|
|
103
|
+
if (_config.debug) {
|
|
104
|
+
console.debug(
|
|
105
|
+
`[ExtractIA SDK] retrying (${cfg._retryCount}/${_config.retries}) in ${delayMs}ms…`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
110
|
+
return _api(cfg);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (typeof _config.onError === "function") _config.onError(mapped);
|
|
114
|
+
return Promise.reject(mapped);
|
|
115
|
+
},
|
|
26
116
|
);
|
|
27
117
|
|
|
118
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
28
120
|
/**
|
|
29
121
|
* Sets the API token used for all subsequent requests.
|
|
30
122
|
* Must be called before any SDK method.
|
|
31
|
-
*
|
|
123
|
+
*
|
|
124
|
+
* @param {string} token - Your Extractia API key.
|
|
125
|
+
* @throws {Error} If the token is empty or not a string.
|
|
32
126
|
*/
|
|
33
|
-
export function setToken(
|
|
34
|
-
token
|
|
127
|
+
export function setToken(token) {
|
|
128
|
+
if (!token || typeof token !== "string" || !token.trim()) {
|
|
129
|
+
throw new Error("setToken: token must be a non-empty string.");
|
|
130
|
+
}
|
|
131
|
+
_token = token.trim();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Returns the currently configured API token, or `null` if not set.
|
|
136
|
+
* @returns {string|null}
|
|
137
|
+
*/
|
|
138
|
+
export function getToken() {
|
|
139
|
+
return _token;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Returns `true` if an API token has been set.
|
|
144
|
+
* @returns {boolean}
|
|
145
|
+
*/
|
|
146
|
+
export function hasToken() {
|
|
147
|
+
return Boolean(_token);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Clears the stored API token.
|
|
152
|
+
* Useful for logout flows or test teardown.
|
|
153
|
+
*/
|
|
154
|
+
export function clearToken() {
|
|
155
|
+
_token = null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Configures SDK behaviour. All properties are optional; unspecified properties
|
|
160
|
+
* retain their current value.
|
|
161
|
+
*
|
|
162
|
+
* @param {object} opts
|
|
163
|
+
* @param {string} [opts.baseURL]
|
|
164
|
+
* Override the API base URL (useful for staging environments or proxies).
|
|
165
|
+
* @param {number} [opts.timeout]
|
|
166
|
+
* Request timeout in milliseconds. Default: 60 000 (60 s).
|
|
167
|
+
* @param {number} [opts.retries]
|
|
168
|
+
* Number of automatic retries on retryable errors (429 / 5xx / network). Default: 1.
|
|
169
|
+
* @param {number} [opts.retryDelay]
|
|
170
|
+
* Base delay (ms) between retries; multiplied by the attempt number. Default: 1 000.
|
|
171
|
+
* @param {boolean} [opts.debug]
|
|
172
|
+
* Log request/response/retry info to `console.debug`. Default: false.
|
|
173
|
+
* @param {Record<string,string>} [opts.defaultHeaders]
|
|
174
|
+
* Extra HTTP headers merged into every request (e.g. `{ "X-App-Version": "2.0" }`).
|
|
175
|
+
* @param {(config: import('axios').InternalAxiosRequestConfig) => import('axios').InternalAxiosRequestConfig|void} [opts.onBeforeRequest]
|
|
176
|
+
* Hook called with the Axios request config before each request.
|
|
177
|
+
* Return a modified config or `void` to keep the original.
|
|
178
|
+
* @param {(response: import('axios').AxiosResponse) => void} [opts.onAfterResponse]
|
|
179
|
+
* Hook called after each successful response. Useful for logging or metrics.
|
|
180
|
+
* @param {(error: import('./errors.js').ExtractiaError) => void} [opts.onError]
|
|
181
|
+
* Hook called with the mapped SDK error whenever a request fails.
|
|
182
|
+
* Called after retries are exhausted.
|
|
183
|
+
*/
|
|
184
|
+
export function configure(opts = {}) {
|
|
185
|
+
if (opts.baseURL) {
|
|
186
|
+
_config.baseURL = opts.baseURL;
|
|
187
|
+
_api.defaults.baseURL = opts.baseURL;
|
|
188
|
+
}
|
|
189
|
+
if (opts.timeout != null) {
|
|
190
|
+
_config.timeout = opts.timeout;
|
|
191
|
+
_api.defaults.timeout = opts.timeout;
|
|
192
|
+
}
|
|
193
|
+
if (opts.retries != null) _config.retries = opts.retries;
|
|
194
|
+
if (opts.retryDelay != null) _config.retryDelay = opts.retryDelay;
|
|
195
|
+
if (opts.debug != null) _config.debug = Boolean(opts.debug);
|
|
196
|
+
if (opts.defaultHeaders) {
|
|
197
|
+
_config.defaultHeaders = { ..._config.defaultHeaders, ...opts.defaultHeaders };
|
|
198
|
+
}
|
|
199
|
+
if (opts.onBeforeRequest) _config.onBeforeRequest = opts.onBeforeRequest;
|
|
200
|
+
if (opts.onAfterResponse) _config.onAfterResponse = opts.onAfterResponse;
|
|
201
|
+
if (opts.onError) _config.onError = opts.onError;
|
|
35
202
|
}
|
|
36
203
|
|
|
37
204
|
/**
|
|
38
|
-
*
|
|
39
|
-
* @
|
|
40
|
-
* @param {string} [opts.baseURL] - Override the default API base URL.
|
|
205
|
+
* Returns a snapshot of the current SDK configuration (token excluded).
|
|
206
|
+
* @returns {Readonly<typeof _config>}
|
|
41
207
|
*/
|
|
42
|
-
export function
|
|
43
|
-
|
|
208
|
+
export function getConfig() {
|
|
209
|
+
return { ..._config };
|
|
44
210
|
}
|
|
45
211
|
|
|
46
|
-
export default
|
|
212
|
+
export default _api;
|
package/src/browser-entry.js
CHANGED
|
@@ -3,6 +3,23 @@ import * as templates from "./templates.js";
|
|
|
3
3
|
import * as documents from "./documents.js";
|
|
4
4
|
import * as analytics from "./analytics.js";
|
|
5
5
|
import * as ocrTools from "./ocrTools.js";
|
|
6
|
+
import * as subusers from "./subusers.js";
|
|
7
|
+
import * as utils from "./utils.js";
|
|
8
|
+
import { getToken, hasToken, clearToken, getConfig } from "./apiClient.js";
|
|
9
|
+
import {
|
|
10
|
+
ExtractiaError,
|
|
11
|
+
AuthError,
|
|
12
|
+
ForbiddenError,
|
|
13
|
+
TierError,
|
|
14
|
+
QuotaError,
|
|
15
|
+
RateLimitError,
|
|
16
|
+
NotFoundError,
|
|
17
|
+
ValidationError,
|
|
18
|
+
ConflictError,
|
|
19
|
+
ServerError,
|
|
20
|
+
NetworkError,
|
|
21
|
+
TimeoutError,
|
|
22
|
+
} from "./errors.js";
|
|
6
23
|
|
|
7
24
|
const extractia = {
|
|
8
25
|
...auth,
|
|
@@ -10,6 +27,24 @@ const extractia = {
|
|
|
10
27
|
...documents,
|
|
11
28
|
...analytics,
|
|
12
29
|
...ocrTools,
|
|
30
|
+
...subusers,
|
|
31
|
+
...utils,
|
|
32
|
+
getToken,
|
|
33
|
+
hasToken,
|
|
34
|
+
clearToken,
|
|
35
|
+
getConfig,
|
|
36
|
+
ExtractiaError,
|
|
37
|
+
AuthError,
|
|
38
|
+
ForbiddenError,
|
|
39
|
+
TierError,
|
|
40
|
+
QuotaError,
|
|
41
|
+
RateLimitError,
|
|
42
|
+
NotFoundError,
|
|
43
|
+
ValidationError,
|
|
44
|
+
ConflictError,
|
|
45
|
+
ServerError,
|
|
46
|
+
NetworkError,
|
|
47
|
+
TimeoutError,
|
|
13
48
|
};
|
|
14
49
|
|
|
15
50
|
export default extractia;
|