oxpdf 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 0xPdf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # oxpdf
2
+
3
+ TypeScript/JavaScript SDK for the [0xPdf](https://0xpdf.com) PDF-to-JSON API.
4
+
5
+ Works in **Node.js 18+**, **Bun**, **Deno**, and the **browser** — zero dependencies, uses native `fetch`.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install oxpdf
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { OxPDFClient } from "oxpdf";
17
+
18
+ const client = new OxPDFClient({ apiKey: "your_api_key" });
19
+
20
+ // Parse with a built-in template
21
+ const result = await client.parse(pdfBuffer, "invoice.pdf", {
22
+ schemaTemplate: "invoice",
23
+ });
24
+ console.log(result.data);
25
+
26
+ // Parse from a file path (Node.js only)
27
+ const result2 = await client.parseFile("./invoice.pdf", {
28
+ schemaTemplate: "invoice",
29
+ });
30
+
31
+ // Streaming parse with real-time progress
32
+ for await (const event of client.parseFileStream("./large.pdf", {
33
+ schemaTemplate: "invoice",
34
+ })) {
35
+ if (event.event === "page") console.log(event.data.message);
36
+ if (event.event === "complete") console.log("Done!", event.data);
37
+ }
38
+ ```
39
+
40
+ ## Browser Usage
41
+
42
+ ```typescript
43
+ const input = document.querySelector<HTMLInputElement>("#pdf-upload")!;
44
+ input.addEventListener("change", async () => {
45
+ const file = input.files![0];
46
+ const result = await client.parse(file, file.name, {
47
+ schemaTemplate: "invoice",
48
+ });
49
+ console.log(result.data);
50
+ });
51
+ ```
52
+
53
+ ## Error Handling
54
+
55
+ ```typescript
56
+ import { OxPDFClient, OxPDFError } from "oxpdf";
57
+
58
+ try {
59
+ const result = await client.parseFile("doc.pdf", {
60
+ schemaTemplate: "invoice",
61
+ });
62
+ } catch (e) {
63
+ if (e instanceof OxPDFError) {
64
+ console.error(`API error: ${e.message} (status: ${e.statusCode})`);
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## Full API Reference
70
+
71
+ ### Constructor
72
+
73
+ ```typescript
74
+ new OxPDFClient({ apiKey, baseUrl?, timeout? })
75
+ ```
76
+
77
+ | Option | Type | Default | Description |
78
+ | --------- | -------- | ------------------------------------ | -------------------- |
79
+ | `apiKey` | `string` | — | Your 0xPdf API key |
80
+ | `baseUrl` | `string` | `https://api.0xpdf.com/api/v1` | API base URL |
81
+ | `timeout` | `number` | `120000` | Request timeout (ms) |
82
+
83
+ ### PDF Parsing
84
+
85
+ | Method | Description |
86
+ |---|---|
87
+ | `parse(file, filename, options?)` | Sync parse from Buffer/Blob/File |
88
+ | `parseFile(filePath, options?)` | Sync parse from file path (Node.js) |
89
+ | `parseStream(file, filename, options?)` | Streaming SSE parse (async generator) |
90
+ | `parseFileStream(filePath, options?)` | Streaming parse from file (Node.js) |
91
+ | `validate(file, filename, options?)` | Dry-run validation |
92
+
93
+ ### Async Jobs
94
+
95
+ | Method | Description |
96
+ |---|---|
97
+ | `upload(file, filename, options?)` | Queue PDF for background processing |
98
+ | `jobStatus(jobId)` | Poll async job status |
99
+
100
+ ### Image Extraction
101
+
102
+ | Method | Description |
103
+ |---|---|
104
+ | `extractImages(file, filename, options?)` | Extract images from a PDF |
105
+ | `listImages(limit?, offset?)` | List extracted images |
106
+ | `getImageUrl(imageId, expirationSeconds?)` | Get/refresh presigned URL |
107
+ | `deleteImage(imageId)` | Delete a specific image |
108
+ | `deleteAllImages()` | Delete all images |
109
+
110
+ ### File Management
111
+
112
+ | Method | Description |
113
+ |---|---|
114
+ | `listFiles()` | List uploaded PDFs |
115
+ | `getFile(pdfId)` | Get PDF metadata + download URL |
116
+ | `deleteFile(pdfId)` | Delete an uploaded PDF |
117
+
118
+ ### Schema CRUD
119
+
120
+ | Method | Description |
121
+ |---|---|
122
+ | `listSchemas()` | List saved schemas |
123
+ | `getSchema(schemaId)` | Get schema with full definition |
124
+ | `createSchema(options)` | Create a new schema |
125
+ | `updateSchema(schemaId, options)` | Update existing schema |
126
+ | `deleteSchema(schemaId)` | Delete a schema |
127
+ | `setDefaultSchema(schemaId)` | Set as default |
128
+ | `generateSchema(options)` | AI-generate a schema |
129
+
130
+ ### Templates
131
+
132
+ | Method | Description |
133
+ |---|---|
134
+ | `listTemplates()` | Parse templates (invoice, receipt, etc.) |
135
+ | `listSchemaTemplates()` | Schema editor templates |
136
+ | `getSchemaTemplate(templateId)` | Get template with full schema |
137
+
138
+ ### Analytics & Pricing
139
+
140
+ | Method | Description |
141
+ |---|---|
142
+ | `getAnalytics()` | Usage analytics |
143
+ | `submitFeedback(feedback)` | Submit feedback |
144
+ | `getPricing(billingCycle?)` | Get pricing tiers |
145
+ | `getCurrentTier()` | Current subscription & quota |
146
+
147
+ ### Parse Options
148
+
149
+ | Option | Type | Description |
150
+ | ---------------- | ---------------------- | -------------------------------------- |
151
+ | `schema` | `Record<string, any>` | Custom JSON schema |
152
+ | `schemaTemplate` | `string` | Pre-built template name |
153
+ | `schemaId` | `string` | Saved schema ID |
154
+ | `useOcr` | `boolean` | Enable OCR (default: `false`) |
155
+ | `ocrEngine` | `string` | `"surya"` or `"groq_vision"` |
156
+ | `pages` | `number[]` | Specific pages to parse |
package/dist/index.cjs ADDED
@@ -0,0 +1,412 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ OxPDFClient: () => OxPDFClient,
34
+ OxPDFError: () => OxPDFError
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/errors.ts
39
+ var OxPDFError = class extends Error {
40
+ statusCode;
41
+ responseBody;
42
+ constructor(message, statusCode, responseBody) {
43
+ super(message);
44
+ this.name = "OxPDFError";
45
+ this.statusCode = statusCode;
46
+ this.responseBody = responseBody;
47
+ }
48
+ };
49
+
50
+ // src/client.ts
51
+ var DEFAULT_BASE_URL = "https://api.0xpdf.com/api/v1";
52
+ var DEFAULT_TIMEOUT = 12e4;
53
+ var OxPDFClient = class {
54
+ #apiKey;
55
+ #baseUrl;
56
+ #timeout;
57
+ constructor(options) {
58
+ if (!options.apiKey) {
59
+ throw new OxPDFError("apiKey is required");
60
+ }
61
+ this.#apiKey = options.apiKey;
62
+ this.#baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
63
+ this.#timeout = options.timeout ?? DEFAULT_TIMEOUT;
64
+ }
65
+ // ── internal helpers ─────────────────────────────────────────────
66
+ #url(path) {
67
+ return `${this.#baseUrl}/${path.replace(/^\/+/, "")}`;
68
+ }
69
+ async #request(method, path, init) {
70
+ const url = new URL(this.#url(path));
71
+ if (init?.params) {
72
+ for (const [k, v] of Object.entries(init.params)) {
73
+ url.searchParams.set(k, v);
74
+ }
75
+ }
76
+ const controller = new AbortController();
77
+ const timer = setTimeout(() => controller.abort(), this.#timeout);
78
+ let resp;
79
+ try {
80
+ resp = await fetch(url.toString(), {
81
+ method,
82
+ headers: {
83
+ "X-API-Key": this.#apiKey,
84
+ ...init?.headers
85
+ },
86
+ body: init?.body,
87
+ signal: controller.signal
88
+ });
89
+ } catch (err) {
90
+ const msg = err instanceof Error ? err.message : String(err);
91
+ throw new OxPDFError(`Request failed: ${msg}`);
92
+ } finally {
93
+ clearTimeout(timer);
94
+ }
95
+ if (resp.status === 204) return {};
96
+ if (!resp.ok) {
97
+ const text2 = await resp.text();
98
+ let detail;
99
+ try {
100
+ const body = JSON.parse(text2);
101
+ const raw = body.detail ?? body.error ?? text2;
102
+ if (Array.isArray(raw)) {
103
+ detail = raw.map((d) => d.msg ?? JSON.stringify(d)).join("; ");
104
+ } else {
105
+ detail = typeof raw === "string" ? raw : JSON.stringify(raw);
106
+ }
107
+ } catch {
108
+ detail = text2 || resp.statusText || `HTTP ${resp.status}`;
109
+ }
110
+ throw new OxPDFError(detail, resp.status, text2);
111
+ }
112
+ const text = await resp.text();
113
+ if (!text) return {};
114
+ return JSON.parse(text);
115
+ }
116
+ #buildPdfForm(file, filename, fields) {
117
+ if (!filename.toLowerCase().endsWith(".pdf")) {
118
+ throw new OxPDFError("File must be a PDF");
119
+ }
120
+ const form = new FormData();
121
+ let blob;
122
+ if (file instanceof Blob) {
123
+ blob = file;
124
+ } else {
125
+ const arr = new Uint8Array(file.buffer, file.byteOffset, file.byteLength);
126
+ blob = new Blob([arr], {
127
+ type: "application/pdf"
128
+ });
129
+ }
130
+ form.append("file", blob, filename);
131
+ if (fields) {
132
+ for (const [k, v] of Object.entries(fields)) form.append(k, v);
133
+ }
134
+ return form;
135
+ }
136
+ // ── PDF parsing ──────────────────────────────────────────────────
137
+ /** Parse a PDF and return structured JSON. */
138
+ async parse(file, filename, options = {}) {
139
+ const formFields = {
140
+ use_ocr: String(options.useOcr ?? false)
141
+ };
142
+ if (options.ocrEngine) formFields.ocr_engine = options.ocrEngine;
143
+ if (options.schema) formFields.schema_json = JSON.stringify(options.schema);
144
+ const params = {};
145
+ if (options.schemaTemplate) params.schema_template = options.schemaTemplate;
146
+ if (options.schemaId) params.schema_id = options.schemaId;
147
+ if (options.pages) params.pages = options.pages.join(",");
148
+ const form = this.#buildPdfForm(file, filename, formFields);
149
+ return this.#request("POST", "pdf/parse", {
150
+ params: Object.keys(params).length ? params : void 0,
151
+ body: form
152
+ });
153
+ }
154
+ /** Parse a PDF from a file path (Node.js only). */
155
+ async parseFile(filePath, options = {}) {
156
+ const { readFile } = await import("fs/promises");
157
+ const { basename } = await import("path");
158
+ const buf = await readFile(filePath);
159
+ return this.parse(buf, basename(filePath), options);
160
+ }
161
+ /**
162
+ * Streaming parse via Server-Sent Events.
163
+ * Returns an async generator that yields ``StreamEvent`` objects.
164
+ */
165
+ async *parseStream(file, filename, options = {}) {
166
+ const formFields = {
167
+ use_ocr: String(options.useOcr ?? false)
168
+ };
169
+ if (options.ocrEngine) formFields.ocr_engine = options.ocrEngine;
170
+ if (options.schema) formFields.schema_json = JSON.stringify(options.schema);
171
+ const params = {
172
+ batch_size: String(options.batchSize ?? 5)
173
+ };
174
+ if (options.schemaTemplate) params.schema_template = options.schemaTemplate;
175
+ if (options.schemaId) params.schema_id = options.schemaId;
176
+ if (options.pages) params.pages = options.pages.join(",");
177
+ const form = this.#buildPdfForm(file, filename, formFields);
178
+ const url = new URL(this.#url("pdf/parse-stream"));
179
+ for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
180
+ const controller = new AbortController();
181
+ const timer = setTimeout(() => controller.abort(), 3e5);
182
+ let resp;
183
+ try {
184
+ resp = await fetch(url.toString(), {
185
+ method: "POST",
186
+ headers: { "X-API-Key": this.#apiKey },
187
+ body: form,
188
+ signal: controller.signal
189
+ });
190
+ } catch (err) {
191
+ clearTimeout(timer);
192
+ const msg = err instanceof Error ? err.message : String(err);
193
+ throw new OxPDFError(`Stream request failed: ${msg}`);
194
+ }
195
+ if (!resp.ok) {
196
+ clearTimeout(timer);
197
+ const text = await resp.text();
198
+ throw new OxPDFError(text, resp.status, text);
199
+ }
200
+ try {
201
+ const reader = resp.body?.getReader();
202
+ if (!reader) throw new OxPDFError("No response body");
203
+ const decoder = new TextDecoder();
204
+ let buffer = "";
205
+ let eventType = "message";
206
+ while (true) {
207
+ const { done, value } = await reader.read();
208
+ if (done) break;
209
+ buffer += decoder.decode(value, { stream: true });
210
+ const lines = buffer.split("\n");
211
+ buffer = lines.pop() ?? "";
212
+ for (const line of lines) {
213
+ if (line.startsWith("event:")) {
214
+ eventType = line.slice(6).trim();
215
+ } else if (line.startsWith("data:")) {
216
+ const raw = line.slice(5).trim();
217
+ let data;
218
+ try {
219
+ data = JSON.parse(raw);
220
+ } catch {
221
+ data = { raw };
222
+ }
223
+ yield { event: eventType, data };
224
+ eventType = "message";
225
+ }
226
+ }
227
+ }
228
+ } finally {
229
+ clearTimeout(timer);
230
+ }
231
+ }
232
+ /** Streaming parse from a file path (Node.js only). */
233
+ async *parseFileStream(filePath, options = {}) {
234
+ const { readFile } = await import("fs/promises");
235
+ const { basename } = await import("path");
236
+ const buf = await readFile(filePath);
237
+ yield* this.parseStream(buf, basename(filePath), options);
238
+ }
239
+ // ── Async upload (job queue) ─────────────────────────────────────
240
+ /** Upload a PDF for async background processing. Returns a job_id. */
241
+ async upload(file, filename, options = {}) {
242
+ const params = {
243
+ use_ocr: String(options.useOcr ?? false),
244
+ ocr_engine: options.ocrEngine ?? "surya"
245
+ };
246
+ if (options.schemaId) params.schema_id = options.schemaId;
247
+ if (options.schemaName) params.schema_name = options.schemaName;
248
+ const form = this.#buildPdfForm(file, filename);
249
+ return this.#request("POST", "pdf/upload", {
250
+ params,
251
+ body: form
252
+ });
253
+ }
254
+ /** Poll the status of an async PDF processing job. */
255
+ async jobStatus(jobId) {
256
+ return this.#request("GET", `pdf/status/${jobId}`);
257
+ }
258
+ // ── PDF validation ───────────────────────────────────────────────
259
+ /** Validate a PDF without full processing (dry-run). */
260
+ async validate(file, filename, options = {}) {
261
+ const params = { dry_run: "true" };
262
+ if (options.schemaId) params.schema_id = options.schemaId;
263
+ if (options.schemaName) params.schema_name = options.schemaName;
264
+ const form = this.#buildPdfForm(file, filename);
265
+ return this.#request("POST", "pdf/validate", { params, body: form });
266
+ }
267
+ // ── Image extraction ─────────────────────────────────────────────
268
+ /** Extract images from a PDF. */
269
+ async extractImages(file, filename, options = {}) {
270
+ const params = {
271
+ min_width: String(options.minWidth ?? 50),
272
+ min_height: String(options.minHeight ?? 50),
273
+ use_ocr: String(options.useOcr ?? false),
274
+ ocr_engine: options.ocrEngine ?? "surya"
275
+ };
276
+ if (options.pages) params.pages = options.pages.join(",");
277
+ const form = this.#buildPdfForm(file, filename);
278
+ return this.#request("POST", "pdf/parse-images", { params, body: form });
279
+ }
280
+ // ── Image management ─────────────────────────────────────────────
281
+ /** List extracted images. */
282
+ async listImages(limit = 100, offset = 0) {
283
+ return this.#request("GET", "pdf/images", {
284
+ params: { limit: String(limit), offset: String(offset) }
285
+ });
286
+ }
287
+ /** Get or refresh a presigned URL for an image. */
288
+ async getImageUrl(imageId, expirationSeconds = 3600) {
289
+ return this.#request("GET", `pdf/images/${imageId}/url`, {
290
+ params: { expiration_seconds: String(expirationSeconds) }
291
+ });
292
+ }
293
+ /** Delete a specific image. */
294
+ async deleteImage(imageId) {
295
+ await this.#request("DELETE", `pdf/images/${imageId}`);
296
+ }
297
+ /** Delete all extracted images. */
298
+ async deleteAllImages() {
299
+ return this.#request("DELETE", "pdf/images");
300
+ }
301
+ // ── File management ──────────────────────────────────────────────
302
+ /** List previously uploaded PDFs. */
303
+ async listFiles() {
304
+ return this.#request("GET", "pdf/files");
305
+ }
306
+ /** Get metadata and download URL for an uploaded PDF. */
307
+ async getFile(pdfId) {
308
+ return this.#request("GET", `pdf/files/${pdfId}`);
309
+ }
310
+ /** Delete an uploaded PDF. */
311
+ async deleteFile(pdfId) {
312
+ await this.#request("DELETE", `pdf/files/${pdfId}`);
313
+ }
314
+ // ── Schema templates ─────────────────────────────────────────────
315
+ /** List pre-built schema templates (pdf route). */
316
+ async listTemplates() {
317
+ const res = await this.#request("GET", "pdf/templates");
318
+ return res.templates ?? [];
319
+ }
320
+ /** List schema templates from /schemas/templates/list. */
321
+ async listSchemaTemplates() {
322
+ const res = await this.#request(
323
+ "GET",
324
+ "schemas/templates/list"
325
+ );
326
+ return res.templates ?? [];
327
+ }
328
+ /** Get a specific schema template with full definition. */
329
+ async getSchemaTemplate(templateId) {
330
+ return this.#request("GET", `schemas/templates/${templateId}`);
331
+ }
332
+ // ── Schema CRUD ──────────────────────────────────────────────────
333
+ /** List user's saved schemas. */
334
+ async listSchemas() {
335
+ const res = await this.#request("GET", "schemas");
336
+ return res.schemas ?? [];
337
+ }
338
+ /** Get a specific schema by ID. */
339
+ async getSchema(schemaId) {
340
+ return this.#request("GET", `schemas/${schemaId}`);
341
+ }
342
+ /** Create a new JSON schema. */
343
+ async createSchema(options) {
344
+ return this.#request("POST", "schemas", {
345
+ body: JSON.stringify({
346
+ name: options.name,
347
+ schema: options.schema,
348
+ is_default: options.isDefault ?? false
349
+ }),
350
+ headers: { "Content-Type": "application/json" }
351
+ });
352
+ }
353
+ /** Update an existing schema. */
354
+ async updateSchema(schemaId, options) {
355
+ return this.#request("PUT", `schemas/${schemaId}`, {
356
+ body: JSON.stringify({
357
+ name: options.name,
358
+ schema: options.schema,
359
+ is_default: options.isDefault ?? false
360
+ }),
361
+ headers: { "Content-Type": "application/json" }
362
+ });
363
+ }
364
+ /** Delete a schema. */
365
+ async deleteSchema(schemaId) {
366
+ await this.#request("DELETE", `schemas/${schemaId}`);
367
+ }
368
+ /** Set a schema as the default. */
369
+ async setDefaultSchema(schemaId) {
370
+ return this.#request("PATCH", `schemas/${schemaId}/set-default`);
371
+ }
372
+ /** Generate a schema using AI from a natural-language description. */
373
+ async generateSchema(options) {
374
+ const body = { description: options.description };
375
+ if (options.refinement) body.refinement = options.refinement;
376
+ if (options.currentSchema) body.current_schema = options.currentSchema;
377
+ if (options.selectedText) body.selected_text = options.selectedText;
378
+ return this.#request("POST", "schemas/generate", {
379
+ body: JSON.stringify(body),
380
+ headers: { "Content-Type": "application/json" }
381
+ });
382
+ }
383
+ // ── Analytics ────────────────────────────────────────────────────
384
+ /** Get usage analytics for the current user/org. */
385
+ async getAnalytics() {
386
+ return this.#request("GET", "analytics/user");
387
+ }
388
+ /** Submit in-app feedback. */
389
+ async submitFeedback(feedback) {
390
+ return this.#request("POST", "analytics/feedback", {
391
+ body: JSON.stringify({ feedback }),
392
+ headers: { "Content-Type": "application/json" }
393
+ });
394
+ }
395
+ // ── Pricing ──────────────────────────────────────────────────────
396
+ /** Get available pricing tiers. */
397
+ async getPricing(billingCycle = "monthly") {
398
+ return this.#request("GET", "pricing", {
399
+ params: { billing_cycle: billingCycle }
400
+ });
401
+ }
402
+ /** Get the current user's tier and quota. */
403
+ async getCurrentTier() {
404
+ return this.#request("GET", "pricing/current");
405
+ }
406
+ };
407
+ // Annotate the CommonJS export names for ESM import in node:
408
+ 0 && (module.exports = {
409
+ OxPDFClient,
410
+ OxPDFError
411
+ });
412
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { OxPDFClient } from \"./client.js\";\nexport { OxPDFError } from \"./errors.js\";\nexport type {\n AnalyticsResult,\n ClientOptions,\n CreateSchemaOptions,\n ExtractImagesOptions,\n FileInfo,\n FileListResult,\n GenerateSchemaOptions,\n GenerateSchemaResult,\n ImageInfo,\n ImageListResult,\n ImageUrlResult,\n JobStatus,\n ParseOptions,\n ParseResult,\n ParseStreamOptions,\n SchemaInfo,\n SchemaTemplate,\n StreamEvent,\n UpdateSchemaOptions,\n UploadOptions,\n UploadResult,\n ValidateOptions,\n} from \"./types.js\";\n","export class OxPDFError extends Error {\n readonly statusCode: number | undefined;\n readonly responseBody: string | undefined;\n\n constructor(\n message: string,\n statusCode?: number,\n responseBody?: string,\n ) {\n super(message);\n this.name = \"OxPDFError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n }\n}\n","import { OxPDFError } from \"./errors.js\";\nimport type {\n AnalyticsResult,\n ClientOptions,\n CreateSchemaOptions,\n ExtractImagesOptions,\n FileInfo,\n FileListResult,\n GenerateSchemaOptions,\n GenerateSchemaResult,\n ImageListResult,\n ImageUrlResult,\n JobStatus,\n ParseOptions,\n ParseResult,\n ParseStreamOptions,\n SchemaInfo,\n SchemaTemplate,\n StreamEvent,\n UpdateSchemaOptions,\n UploadOptions,\n UploadResult,\n ValidateOptions,\n} from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.0xpdf.com/api/v1\";\nconst DEFAULT_TIMEOUT = 120_000;\n\nexport class OxPDFClient {\n readonly #apiKey: string;\n readonly #baseUrl: string;\n readonly #timeout: number;\n\n constructor(options: ClientOptions) {\n if (!options.apiKey) {\n throw new OxPDFError(\"apiKey is required\");\n }\n this.#apiKey = options.apiKey;\n this.#baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.#timeout = options.timeout ?? DEFAULT_TIMEOUT;\n }\n\n // ── internal helpers ─────────────────────────────────────────────\n\n #url(path: string): string {\n return `${this.#baseUrl}/${path.replace(/^\\/+/, \"\")}`;\n }\n\n async #request<T = Record<string, unknown>>(\n method: string,\n path: string,\n init?: {\n params?: Record<string, string>;\n body?: FormData | string;\n headers?: Record<string, string>;\n },\n ): Promise<T> {\n const url = new URL(this.#url(path));\n if (init?.params) {\n for (const [k, v] of Object.entries(init.params)) {\n url.searchParams.set(k, v);\n }\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.#timeout);\n\n let resp: Response;\n try {\n resp = await fetch(url.toString(), {\n method,\n headers: {\n \"X-API-Key\": this.#apiKey,\n ...init?.headers,\n },\n body: init?.body,\n signal: controller.signal,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new OxPDFError(`Request failed: ${msg}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (resp.status === 204) return {} as T;\n\n if (!resp.ok) {\n const text = await resp.text();\n let detail: string;\n try {\n const body = JSON.parse(text);\n const raw = body.detail ?? body.error ?? text;\n if (Array.isArray(raw)) {\n detail = raw.map((d: Record<string, unknown>) => d.msg ?? JSON.stringify(d)).join(\"; \");\n } else {\n detail = typeof raw === \"string\" ? raw : JSON.stringify(raw);\n }\n } catch {\n detail = text || resp.statusText || `HTTP ${resp.status}`;\n }\n throw new OxPDFError(detail, resp.status, text);\n }\n\n const text = await resp.text();\n if (!text) return {} as T;\n return JSON.parse(text) as T;\n }\n\n #buildPdfForm(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n fields?: Record<string, string>,\n ): FormData {\n if (!filename.toLowerCase().endsWith(\".pdf\")) {\n throw new OxPDFError(\"File must be a PDF\");\n }\n\n const form = new FormData();\n let blob: Blob;\n if (file instanceof Blob) {\n blob = file;\n } else {\n const arr = new Uint8Array(file.buffer, file.byteOffset, file.byteLength);\n blob = new Blob([arr as unknown as Uint8Array<ArrayBuffer>], {\n type: \"application/pdf\",\n });\n }\n form.append(\"file\", blob, filename);\n if (fields) {\n for (const [k, v] of Object.entries(fields)) form.append(k, v);\n }\n return form;\n }\n\n // ── PDF parsing ──────────────────────────────────────────────────\n\n /** Parse a PDF and return structured JSON. */\n async parse(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n options: ParseOptions = {},\n ): Promise<ParseResult> {\n const formFields: Record<string, string> = {\n use_ocr: String(options.useOcr ?? false),\n };\n if (options.ocrEngine) formFields.ocr_engine = options.ocrEngine;\n if (options.schema) formFields.schema_json = JSON.stringify(options.schema);\n\n const params: Record<string, string> = {};\n if (options.schemaTemplate) params.schema_template = options.schemaTemplate;\n if (options.schemaId) params.schema_id = options.schemaId;\n if (options.pages) params.pages = options.pages.join(\",\");\n\n const form = this.#buildPdfForm(file, filename, formFields);\n\n return this.#request<ParseResult>(\"POST\", \"pdf/parse\", {\n params: Object.keys(params).length ? params : undefined,\n body: form,\n });\n }\n\n /** Parse a PDF from a file path (Node.js only). */\n async parseFile(filePath: string, options: ParseOptions = {}): Promise<ParseResult> {\n const { readFile } = await import(\"node:fs/promises\");\n const { basename } = await import(\"node:path\");\n const buf = await readFile(filePath);\n return this.parse(buf, basename(filePath), options);\n }\n\n /**\n * Streaming parse via Server-Sent Events.\n * Returns an async generator that yields ``StreamEvent`` objects.\n */\n async *parseStream(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n options: ParseStreamOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const formFields: Record<string, string> = {\n use_ocr: String(options.useOcr ?? false),\n };\n if (options.ocrEngine) formFields.ocr_engine = options.ocrEngine;\n if (options.schema) formFields.schema_json = JSON.stringify(options.schema);\n\n const params: Record<string, string> = {\n batch_size: String(options.batchSize ?? 5),\n };\n if (options.schemaTemplate) params.schema_template = options.schemaTemplate;\n if (options.schemaId) params.schema_id = options.schemaId;\n if (options.pages) params.pages = options.pages.join(\",\");\n\n const form = this.#buildPdfForm(file, filename, formFields);\n\n const url = new URL(this.#url(\"pdf/parse-stream\"));\n for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 300_000);\n\n let resp: Response;\n try {\n resp = await fetch(url.toString(), {\n method: \"POST\",\n headers: { \"X-API-Key\": this.#apiKey },\n body: form,\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n const msg = err instanceof Error ? err.message : String(err);\n throw new OxPDFError(`Stream request failed: ${msg}`);\n }\n\n if (!resp.ok) {\n clearTimeout(timer);\n const text = await resp.text();\n throw new OxPDFError(text, resp.status, text);\n }\n\n try {\n const reader = resp.body?.getReader();\n if (!reader) throw new OxPDFError(\"No response body\");\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n let eventType = \"message\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event:\")) {\n eventType = line.slice(6).trim();\n } else if (line.startsWith(\"data:\")) {\n const raw = line.slice(5).trim();\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(raw);\n } catch {\n data = { raw };\n }\n yield { event: eventType, data };\n eventType = \"message\";\n }\n }\n }\n } finally {\n clearTimeout(timer);\n }\n }\n\n /** Streaming parse from a file path (Node.js only). */\n async *parseFileStream(\n filePath: string,\n options: ParseStreamOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const { readFile } = await import(\"node:fs/promises\");\n const { basename } = await import(\"node:path\");\n const buf = await readFile(filePath);\n yield* this.parseStream(buf, basename(filePath), options);\n }\n\n // ── Async upload (job queue) ─────────────────────────────────────\n\n /** Upload a PDF for async background processing. Returns a job_id. */\n async upload(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n options: UploadOptions = {},\n ): Promise<UploadResult> {\n const params: Record<string, string> = {\n use_ocr: String(options.useOcr ?? false),\n ocr_engine: options.ocrEngine ?? \"surya\",\n };\n if (options.schemaId) params.schema_id = options.schemaId;\n if (options.schemaName) params.schema_name = options.schemaName;\n\n const form = this.#buildPdfForm(file, filename);\n\n return this.#request<UploadResult>(\"POST\", \"pdf/upload\", {\n params,\n body: form,\n });\n }\n\n /** Poll the status of an async PDF processing job. */\n async jobStatus(jobId: string): Promise<JobStatus> {\n return this.#request<JobStatus>(\"GET\", `pdf/status/${jobId}`);\n }\n\n // ── PDF validation ───────────────────────────────────────────────\n\n /** Validate a PDF without full processing (dry-run). */\n async validate(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n options: ValidateOptions = {},\n ): Promise<Record<string, unknown>> {\n const params: Record<string, string> = { dry_run: \"true\" };\n if (options.schemaId) params.schema_id = options.schemaId;\n if (options.schemaName) params.schema_name = options.schemaName;\n\n const form = this.#buildPdfForm(file, filename);\n return this.#request(\"POST\", \"pdf/validate\", { params, body: form });\n }\n\n // ── Image extraction ─────────────────────────────────────────────\n\n /** Extract images from a PDF. */\n async extractImages(\n file: Blob | Buffer | Uint8Array,\n filename: string,\n options: ExtractImagesOptions = {},\n ): Promise<Record<string, unknown>> {\n const params: Record<string, string> = {\n min_width: String(options.minWidth ?? 50),\n min_height: String(options.minHeight ?? 50),\n use_ocr: String(options.useOcr ?? false),\n ocr_engine: options.ocrEngine ?? \"surya\",\n };\n if (options.pages) params.pages = options.pages.join(\",\");\n\n const form = this.#buildPdfForm(file, filename);\n return this.#request(\"POST\", \"pdf/parse-images\", { params, body: form });\n }\n\n // ── Image management ─────────────────────────────────────────────\n\n /** List extracted images. */\n async listImages(limit = 100, offset = 0): Promise<ImageListResult> {\n return this.#request<ImageListResult>(\"GET\", \"pdf/images\", {\n params: { limit: String(limit), offset: String(offset) },\n });\n }\n\n /** Get or refresh a presigned URL for an image. */\n async getImageUrl(imageId: string, expirationSeconds = 3600): Promise<ImageUrlResult> {\n return this.#request<ImageUrlResult>(\"GET\", `pdf/images/${imageId}/url`, {\n params: { expiration_seconds: String(expirationSeconds) },\n });\n }\n\n /** Delete a specific image. */\n async deleteImage(imageId: string): Promise<void> {\n await this.#request(\"DELETE\", `pdf/images/${imageId}`);\n }\n\n /** Delete all extracted images. */\n async deleteAllImages(): Promise<Record<string, unknown>> {\n return this.#request(\"DELETE\", \"pdf/images\");\n }\n\n // ── File management ──────────────────────────────────────────────\n\n /** List previously uploaded PDFs. */\n async listFiles(): Promise<FileListResult> {\n return this.#request<FileListResult>(\"GET\", \"pdf/files\");\n }\n\n /** Get metadata and download URL for an uploaded PDF. */\n async getFile(pdfId: string): Promise<FileInfo> {\n return this.#request<FileInfo>(\"GET\", `pdf/files/${pdfId}`);\n }\n\n /** Delete an uploaded PDF. */\n async deleteFile(pdfId: string): Promise<void> {\n await this.#request(\"DELETE\", `pdf/files/${pdfId}`);\n }\n\n // ── Schema templates ─────────────────────────────────────────────\n\n /** List pre-built schema templates (pdf route). */\n async listTemplates(): Promise<SchemaTemplate[]> {\n const res = await this.#request<{ templates: SchemaTemplate[] }>(\"GET\", \"pdf/templates\");\n return res.templates ?? [];\n }\n\n /** List schema templates from /schemas/templates/list. */\n async listSchemaTemplates(): Promise<SchemaTemplate[]> {\n const res = await this.#request<{ templates: SchemaTemplate[] }>(\n \"GET\",\n \"schemas/templates/list\",\n );\n return res.templates ?? [];\n }\n\n /** Get a specific schema template with full definition. */\n async getSchemaTemplate(templateId: string): Promise<SchemaTemplate> {\n return this.#request<SchemaTemplate>(\"GET\", `schemas/templates/${templateId}`);\n }\n\n // ── Schema CRUD ──────────────────────────────────────────────────\n\n /** List user's saved schemas. */\n async listSchemas(): Promise<SchemaInfo[]> {\n const res = await this.#request<{ schemas: SchemaInfo[] }>(\"GET\", \"schemas\");\n return res.schemas ?? [];\n }\n\n /** Get a specific schema by ID. */\n async getSchema(schemaId: string): Promise<SchemaInfo> {\n return this.#request<SchemaInfo>(\"GET\", `schemas/${schemaId}`);\n }\n\n /** Create a new JSON schema. */\n async createSchema(options: CreateSchemaOptions): Promise<SchemaInfo> {\n return this.#request<SchemaInfo>(\"POST\", \"schemas\", {\n body: JSON.stringify({\n name: options.name,\n schema: options.schema,\n is_default: options.isDefault ?? false,\n }),\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n /** Update an existing schema. */\n async updateSchema(schemaId: string, options: UpdateSchemaOptions): Promise<SchemaInfo> {\n return this.#request<SchemaInfo>(\"PUT\", `schemas/${schemaId}`, {\n body: JSON.stringify({\n name: options.name,\n schema: options.schema,\n is_default: options.isDefault ?? false,\n }),\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n /** Delete a schema. */\n async deleteSchema(schemaId: string): Promise<void> {\n await this.#request(\"DELETE\", `schemas/${schemaId}`);\n }\n\n /** Set a schema as the default. */\n async setDefaultSchema(schemaId: string): Promise<SchemaInfo> {\n return this.#request<SchemaInfo>(\"PATCH\", `schemas/${schemaId}/set-default`);\n }\n\n /** Generate a schema using AI from a natural-language description. */\n async generateSchema(options: GenerateSchemaOptions): Promise<GenerateSchemaResult> {\n const body: Record<string, unknown> = { description: options.description };\n if (options.refinement) body.refinement = options.refinement;\n if (options.currentSchema) body.current_schema = options.currentSchema;\n if (options.selectedText) body.selected_text = options.selectedText;\n\n return this.#request<GenerateSchemaResult>(\"POST\", \"schemas/generate\", {\n body: JSON.stringify(body),\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // ── Analytics ────────────────────────────────────────────────────\n\n /** Get usage analytics for the current user/org. */\n async getAnalytics(): Promise<AnalyticsResult> {\n return this.#request<AnalyticsResult>(\"GET\", \"analytics/user\");\n }\n\n /** Submit in-app feedback. */\n async submitFeedback(feedback: string): Promise<{ success: boolean }> {\n return this.#request<{ success: boolean }>(\"POST\", \"analytics/feedback\", {\n body: JSON.stringify({ feedback }),\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n // ── Pricing ──────────────────────────────────────────────────────\n\n /** Get available pricing tiers. */\n async getPricing(billingCycle = \"monthly\"): Promise<Record<string, unknown>> {\n return this.#request(\"GET\", \"pricing\", {\n params: { billing_cycle: billingCycle },\n });\n }\n\n /** Get the current user's tier and quota. */\n async getCurrentTier(): Promise<Record<string, unknown>> {\n return this.#request(\"GET\", \"pricing/current\");\n }\n}\n"],"mappings":"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","names":["text"]}