flexorch-sdk 0.2.2 → 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/dist/index.cjs CHANGED
@@ -83,11 +83,12 @@ var init_dataset = __esm({
83
83
  _transport: transport
84
84
  });
85
85
  }
86
- async export(format) {
86
+ async export(format, opts = {}) {
87
87
  if (!SUPPORTED_FORMATS.has(format)) {
88
88
  throw new Error(`Unsupported format "${format}". Choose from: ${[...SUPPORTED_FORMATS].sort().join(", ")}`);
89
89
  }
90
- return this._transport.getBytes(`/datasets/${this.id}/export`, { format });
90
+ const params = opts.minQuality !== void 0 ? { min_quality: opts.minQuality } : void 0;
91
+ return this._transport.getBytes(`/datasets/${this.id}/export/${format}`, params);
91
92
  }
92
93
  async exportToS3(connectorId, format, prefix = "") {
93
94
  if (!SUPPORTED_FORMATS.has(format)) {
@@ -139,6 +140,25 @@ var init_dataset = __esm({
139
140
  totalChunks: Number(data["total_chunks"] ?? 0)
140
141
  };
141
142
  }
143
+ /** Preview dataset rows. */
144
+ async rows(opts = {}) {
145
+ const params = {};
146
+ if (opts.page !== void 0) params["page"] = String(opts.page);
147
+ if (opts.pageSize !== void 0) params["page_size"] = String(opts.pageSize);
148
+ if (opts.q !== void 0) params["q"] = opts.q;
149
+ return await this._transport.get(`/datasets/${this.id}/rows`, params) ?? {};
150
+ }
151
+ /** Quality/privacy profile — only available once status is "ready". */
152
+ async profile() {
153
+ return await this._transport.get(`/datasets/${this.id}/profile`) ?? {};
154
+ }
155
+ /** KVKK/GDPR processing transparency report (Pro+ required). */
156
+ async complianceReport(format = "json") {
157
+ if (format === "pdf") {
158
+ return this._transport.getBytes(`/datasets/${this.id}/compliance-report`, { format: "pdf" });
159
+ }
160
+ return await this._transport.get(`/datasets/${this.id}/compliance-report`, { format }) ?? {};
161
+ }
142
162
  toString() {
143
163
  return `Dataset(id=${this.id}, name=${this.name}, rows=${this.rowCount}, status=${this.status})`;
144
164
  }
@@ -152,6 +172,7 @@ __export(index_exports, {
152
172
  AuthError: () => AuthError,
153
173
  Connector: () => Connector,
154
174
  Dataset: () => Dataset,
175
+ Document: () => Document,
155
176
  FlexOrchClient: () => FlexOrchClient,
156
177
  FlexOrchError: () => FlexOrchError,
157
178
  FlexOrchReader: () => FlexOrchReader,
@@ -272,6 +293,12 @@ async function parseError(res) {
272
293
  function sleep(ms) {
273
294
  return new Promise((r) => setTimeout(r, ms));
274
295
  }
296
+ function unwrap(body) {
297
+ if (body !== null && typeof body === "object" && "data" in body && "error" in body && typeof body["status"] === "string") {
298
+ return body["data"];
299
+ }
300
+ return body;
301
+ }
275
302
  var Transport = class {
276
303
  baseUrl;
277
304
  defaultHeaders;
@@ -285,7 +312,7 @@ var Transport = class {
285
312
  this.fetchFn = fetchFn ?? globalThis.fetch.bind(globalThis);
286
313
  this.defaultHeaders = {
287
314
  "X-API-KEY": apiKey,
288
- "User-Agent": "flexorch-sdk-js/0.1.0"
315
+ "User-Agent": "flexorch-sdk-js/0.3.0"
289
316
  };
290
317
  }
291
318
  url(path, params) {
@@ -326,7 +353,7 @@ var Transport = class {
326
353
  if (!ct.includes("application/json")) return null;
327
354
  const text = await res.text();
328
355
  if (!text.trim()) return null;
329
- return JSON.parse(text);
356
+ return unwrap(JSON.parse(text));
330
357
  } catch (err) {
331
358
  clearTimeout(timer);
332
359
  if (err instanceof FlexOrchError) throw err;
@@ -359,13 +386,35 @@ var Transport = class {
359
386
  };
360
387
 
361
388
  // src/models/job.ts
389
+ function jobFeedbackFromDict(data) {
390
+ return {
391
+ id: String(data["id"] ?? ""),
392
+ jobId: String(data["job_id"] ?? ""),
393
+ rating: String(data["rating"] ?? ""),
394
+ issue: data["issue"] ?? null,
395
+ notes: data["notes"] ?? null,
396
+ createdAt: String(data["created_at"] ?? "")
397
+ };
398
+ }
362
399
  var Job = class _Job {
363
400
  id;
364
401
  status;
365
402
  qualityGrade;
366
403
  qualityScore;
367
404
  documentId;
405
+ /** Needed by buildDataset() — POST /datasets/build-from-execution/{executionId}. */
406
+ executionId;
368
407
  hasDataset;
408
+ /**
409
+ * True when the underlying pipeline execution completed but one or more
410
+ * non-critical steps failed (e.g. structured extraction couldn't find a
411
+ * table in the document). The job still succeeds — PII detection and
412
+ * quality scoring results are still meaningful — but `records`/columns
413
+ * may be empty. Read from `execution_summary.degraded`; false for jobs
414
+ * with no execution (e.g. dataset_build). wait() does not throw for a
415
+ * degraded completion.
416
+ */
417
+ degraded;
369
418
  failureReason;
370
419
  _transport;
371
420
  constructor(data) {
@@ -374,19 +423,30 @@ var Job = class _Job {
374
423
  this.qualityGrade = data.qualityGrade;
375
424
  this.qualityScore = data.qualityScore;
376
425
  this.documentId = data.documentId;
426
+ this.executionId = data.executionId;
377
427
  this.hasDataset = data.hasDataset;
428
+ this.degraded = data.degraded;
378
429
  this.failureReason = data.failureReason;
379
430
  this._transport = data._transport;
380
431
  }
381
432
  static fromDict(data, transport) {
382
- const quality = data["quality"] ?? {};
433
+ const executionSummary = data["execution_summary"];
434
+ const processingSummary = data["processing_summary"];
435
+ let quality = data["quality"];
436
+ if (!quality && processingSummary) {
437
+ quality = processingSummary["quality"];
438
+ }
439
+ quality = quality ?? {};
440
+ const executionId = executionSummary?.["execution_id"] ?? processingSummary?.["execution_id"] ?? data["execution_id"] ?? null;
383
441
  return new _Job({
384
442
  id: String(data["job_id"] ?? data["id"] ?? ""),
385
443
  status: String(data["status"] ?? ""),
386
444
  qualityGrade: quality["grade"] ?? null,
387
445
  qualityScore: quality["score"] ?? null,
388
446
  documentId: data["document_id"] ?? null,
389
- hasDataset: Boolean(data["has_dataset"] ?? false),
447
+ executionId,
448
+ hasDataset: Boolean(data["has_dataset"] ?? processingSummary?.["has_dataset"] ?? false),
449
+ degraded: Boolean(executionSummary?.["degraded"] ?? false),
390
450
  failureReason: data["failure_reason"] ?? null,
391
451
  _transport: transport
392
452
  });
@@ -422,6 +482,43 @@ var Job = class _Job {
422
482
  const { Dataset: Dataset2 } = await Promise.resolve().then(() => (init_dataset(), dataset_exports));
423
483
  return Dataset2.fromDict(items[0], this._transport);
424
484
  }
485
+ /**
486
+ * Build a dataset from this job's execution.
487
+ *
488
+ * A completed data_process job does not have a dataset yet — building one
489
+ * is a separate, explicit step (`POST
490
+ * /datasets/build-from-execution/{executionId}`). Call this after
491
+ * `.wait()`, then `.wait()` again on the returned dataset_build Job before
492
+ * calling `.dataset()`:
493
+ *
494
+ * ```ts
495
+ * const job = await client.process("invoice.pdf");
496
+ * const done = await job.wait();
497
+ * const dataset = await (await done.buildDataset()).wait().then(j => j.dataset());
498
+ * ```
499
+ *
500
+ * @throws {Error} If this job has no executionId to build a dataset from
501
+ * (e.g. it failed, or is itself a dataset_build job).
502
+ */
503
+ async buildDataset(opts = {}) {
504
+ if (!this.executionId) {
505
+ throw new Error(
506
+ `Job ${this.id} has no executionId to build a dataset from (job must be a completed data_process job).`
507
+ );
508
+ }
509
+ const body = {
510
+ force_rebuild: opts.forceRebuild ?? false,
511
+ replace_existing: opts.replaceExisting ?? false
512
+ };
513
+ if (opts.name !== void 0) body["name"] = opts.name;
514
+ if (opts.description !== void 0) body["description"] = opts.description;
515
+ if (opts.slug !== void 0) body["slug"] = opts.slug;
516
+ const data = await this._transport.post(
517
+ `/datasets/build-from-execution/${this.executionId}`,
518
+ body
519
+ );
520
+ return _Job.fromDict(data, this._transport);
521
+ }
425
522
  toString() {
426
523
  return `Job(id=${this.id}, status=${this.status}, grade=${this.qualityGrade})`;
427
524
  }
@@ -465,6 +562,15 @@ var SearchResult = class _SearchResult {
465
562
  };
466
563
 
467
564
  // src/resources/jobs.ts
565
+ var VALID_RATINGS = /* @__PURE__ */ new Set(["up", "down"]);
566
+ var VALID_ISSUES = /* @__PURE__ */ new Set([
567
+ "wrong_doc_type",
568
+ "missing_fields",
569
+ "wrong_values",
570
+ "pii_missed",
571
+ "pii_over_masked",
572
+ "other"
573
+ ]);
468
574
  var JobsResource = class {
469
575
  constructor(_t) {
470
576
  this._t = _t;
@@ -482,6 +588,34 @@ var JobsResource = class {
482
588
  const items = data["items"] ?? [];
483
589
  return items.map((item) => Job.fromDict(item, this._t));
484
590
  }
591
+ /**
592
+ * Submit user feedback for a completed job. Upsert — a second call for the
593
+ * same job replaces the previous feedback.
594
+ *
595
+ * @param rating "up" or "down".
596
+ * @param opts.issue When rating="down": "wrong_doc_type" | "missing_fields" |
597
+ * "wrong_values" | "pii_missed" | "pii_over_masked" | "other".
598
+ */
599
+ async submitFeedback(jobId, rating, opts = {}) {
600
+ if (!VALID_RATINGS.has(rating)) {
601
+ throw new Error(`Invalid rating "${rating}". Valid: ${[...VALID_RATINGS].join(", ")}`);
602
+ }
603
+ if (opts.issue !== void 0 && !VALID_ISSUES.has(opts.issue)) {
604
+ throw new Error(`Invalid issue "${opts.issue}". Valid: ${[...VALID_ISSUES].join(", ")}`);
605
+ }
606
+ const data = await this._t.post(`/jobs/${jobId}/feedback`, {
607
+ rating,
608
+ issue: opts.issue ?? null,
609
+ notes: opts.notes ?? null
610
+ });
611
+ return jobFeedbackFromDict(data);
612
+ }
613
+ /** Existing feedback for a job, or null if none was submitted. */
614
+ async getFeedback(jobId) {
615
+ const data = await this._t.get(`/jobs/${jobId}/feedback`);
616
+ if (!data) return null;
617
+ return jobFeedbackFromDict(data);
618
+ }
485
619
  };
486
620
 
487
621
  // src/resources/datasets.ts
@@ -499,10 +633,121 @@ var DatasetsResource = class {
499
633
  const params = {};
500
634
  if (opts.page !== void 0) params["page"] = String(opts.page);
501
635
  if (opts.pageSize !== void 0) params["page_size"] = String(opts.pageSize);
636
+ if (opts.status !== void 0) params["status"] = opts.status;
637
+ if (opts.sourceExecutionId !== void 0) params["source_execution_id"] = String(opts.sourceExecutionId);
638
+ if (opts.sourceDocumentId !== void 0) params["source_document_id"] = String(opts.sourceDocumentId);
639
+ if (opts.q !== void 0) params["q"] = opts.q;
502
640
  const data = await this._t.get("/datasets", params);
503
641
  const items = data["items"] ?? [];
504
642
  return items.map((item) => Dataset.fromDict(item, this._t));
505
643
  }
644
+ /**
645
+ * Build a dataset from a completed execution.
646
+ *
647
+ * Prefer `Job.buildDataset()` when you already have a Job object — this is
648
+ * the lower-level call for when you only have an executionId (e.g. from
649
+ * `Document.latestExecution`).
650
+ *
651
+ * @returns A dataset_build Job — call `.wait()` then `.dataset()`.
652
+ */
653
+ async buildFromExecution(executionId, opts = {}) {
654
+ const body = {
655
+ force_rebuild: opts.forceRebuild ?? false,
656
+ replace_existing: opts.replaceExisting ?? false
657
+ };
658
+ if (opts.name !== void 0) body["name"] = opts.name;
659
+ if (opts.description !== void 0) body["description"] = opts.description;
660
+ if (opts.slug !== void 0) body["slug"] = opts.slug;
661
+ const data = await this._t.post(
662
+ `/datasets/build-from-execution/${executionId}`,
663
+ body
664
+ );
665
+ return Job.fromDict(data, this._t);
666
+ }
667
+ };
668
+
669
+ // src/models/document.ts
670
+ var Document = class _Document {
671
+ id;
672
+ filename;
673
+ fileExt;
674
+ status;
675
+ storagePath;
676
+ createdAt;
677
+ processingCount;
678
+ latestExecution;
679
+ dataset;
680
+ processingHistory;
681
+ relatedDatasets;
682
+ _transport;
683
+ constructor(data) {
684
+ this.id = data.id;
685
+ this.filename = data.filename;
686
+ this.fileExt = data.fileExt;
687
+ this.status = data.status;
688
+ this.storagePath = data.storagePath;
689
+ this.createdAt = data.createdAt;
690
+ this.processingCount = data.processingCount;
691
+ this.latestExecution = data.latestExecution;
692
+ this.dataset = data.dataset;
693
+ this.processingHistory = data.processingHistory;
694
+ this.relatedDatasets = data.relatedDatasets;
695
+ this._transport = data._transport;
696
+ }
697
+ static fromDict(data, transport) {
698
+ return new _Document({
699
+ id: String(data["id"] ?? ""),
700
+ filename: String(data["filename"] ?? ""),
701
+ fileExt: String(data["file_ext"] ?? ""),
702
+ status: String(data["status"] ?? ""),
703
+ storagePath: String(data["storage_path"] ?? ""),
704
+ createdAt: String(data["created_at"] ?? ""),
705
+ processingCount: Number(data["processing_count"] ?? 0),
706
+ latestExecution: data["latest_execution"] ?? null,
707
+ dataset: data["dataset"] ?? null,
708
+ processingHistory: data["processing_history"] ?? [],
709
+ relatedDatasets: data["related_datasets"] ?? [],
710
+ _transport: transport
711
+ });
712
+ }
713
+ /**
714
+ * Re-queue this document through the processing pipeline.
715
+ *
716
+ * Raises (via the API): 400 DOCUMENT_FILE_NOT_AVAILABLE if the source file
717
+ * is no longer on disk, or 400 REPROCESS_NOT_SUPPORTED for
718
+ * connector-sourced (e.g. S3) documents.
719
+ */
720
+ async reprocess(pipelineConfig) {
721
+ const body = {};
722
+ if (pipelineConfig) body["pipeline_config"] = pipelineConfig;
723
+ const data = await this._transport.post(`/documents/${this.id}/reprocess`, body);
724
+ return Job.fromDict(data, this._transport);
725
+ }
726
+ toString() {
727
+ return `Document(id=${this.id}, filename=${this.filename}, status=${this.status})`;
728
+ }
729
+ };
730
+
731
+ // src/resources/documents.ts
732
+ var DocumentsResource = class {
733
+ constructor(_t) {
734
+ this._t = _t;
735
+ }
736
+ _t;
737
+ /** Fetch a single document, including processingHistory and relatedDatasets. */
738
+ async get(documentId) {
739
+ const data = await this._t.get(`/documents/${documentId}`);
740
+ return Document.fromDict(data, this._t);
741
+ }
742
+ /** List documents for the current tenant, newest first. */
743
+ async list(opts = {}) {
744
+ const params = {};
745
+ if (opts.page !== void 0) params["page"] = String(opts.page);
746
+ if (opts.pageSize !== void 0) params["page_size"] = String(opts.pageSize);
747
+ const data = await this._t.get("/documents", params);
748
+ const items = data["items"] ?? [];
749
+ return items.map((item) => Document.fromDict(item, this._t));
750
+ }
506
751
  };
507
752
 
508
753
  // src/resources/usage.ts
@@ -512,15 +757,51 @@ var UsageResource = class {
512
757
  }
513
758
  _t;
514
759
  async current() {
515
- const data = await this._t.get("/usage/current");
760
+ const data = await this._t.get("/usage") ?? {};
761
+ const trial = data["trial"] ?? {};
762
+ const usage = data["usage"] ?? {};
763
+ const credits = usage["credits"] ?? {};
764
+ return {
765
+ plan: String(data["plan"] ?? ""),
766
+ creditsUsed: Number(credits["used"] ?? 0),
767
+ creditsLimit: credits["limit"] ?? null,
768
+ creditsRemaining: credits["remaining"] ?? null,
769
+ isTrial: Boolean(trial["is_trial"] ?? false),
770
+ trialEndsAt: trial["trial_ends_at"] ?? null,
771
+ trialDaysRemaining: trial["trial_days_remaining"] ?? null
772
+ };
773
+ }
774
+ /** @param period "7d" | "30d" | "90d". Default: "30d". */
775
+ async history(period = "30d") {
776
+ const data = await this._t.get("/usage/history", { period });
777
+ return (data ?? []).map((item) => ({
778
+ date: String(item["date"] ?? ""),
779
+ creditsUsed: Number(item["credits_used"] ?? 0),
780
+ jobsCount: Number(item["jobs_count"] ?? 0)
781
+ }));
782
+ }
783
+ /** @param period "7d" | "30d" | "90d". Default: "30d". */
784
+ async qualityTrend(period = "30d") {
785
+ const data = await this._t.get("/usage/quality-trend", { period });
786
+ return (data ?? []).map((item) => ({
787
+ date: String(item["date"] ?? ""),
788
+ avgQualityScore: Number(item["avg_quality_score"] ?? 0),
789
+ gradeDistribution: item["grade_distribution"] ?? {},
790
+ avgFieldFillRate: item["avg_field_fill_rate"] ?? null,
791
+ jobCount: Number(item["job_count"] ?? 0)
792
+ }));
793
+ }
794
+ /** Current rate limit configuration and window usage. Does not consume a request slot. */
795
+ async rateLimits() {
796
+ const data = await this._t.get("/usage/rate-limits") ?? {};
516
797
  return {
517
798
  plan: String(data["plan"] ?? ""),
518
- creditsUsed: Number(data["credits_used"] ?? 0),
519
- creditsLimit: Number(data["credits_limit"] ?? 0),
520
- creditsRemaining: Number(data["credits_remaining"] ?? 0),
521
- resetAt: String(data["reset_at"] ?? ""),
522
- periodStart: String(data["period_start"] ?? ""),
523
- periodEnd: String(data["period_end"] ?? "")
799
+ unlimited: Boolean(data["unlimited"] ?? false),
800
+ limit: data["limit"] ?? null,
801
+ used: data["used"] ?? null,
802
+ remaining: data["remaining"] ?? null,
803
+ windowSeconds: Number(data["window_seconds"] ?? 0),
804
+ resetInSeconds: data["reset_in_seconds"] ?? null
524
805
  };
525
806
  }
526
807
  };
@@ -592,6 +873,32 @@ var Connector = class _Connector {
592
873
  return `Connector(id=${this.id}, name=${this.name}, type=${this.type})`;
593
874
  }
594
875
  };
876
+ function syncScheduleFromDict(data) {
877
+ return {
878
+ id: String(data["id"] ?? ""),
879
+ connectorId: String(data["connector_id"] ?? ""),
880
+ cronExpression: String(data["cron_expression"] ?? ""),
881
+ prefixFilter: data["prefix_filter"] ?? null,
882
+ isActive: Boolean(data["is_active"] ?? true),
883
+ lastRunAt: data["last_run_at"] ?? null,
884
+ nextRunAt: data["next_run_at"] ?? null,
885
+ createdAt: String(data["created_at"] ?? "")
886
+ };
887
+ }
888
+ function syncLogFromDict(data) {
889
+ return {
890
+ id: String(data["id"] ?? ""),
891
+ scheduleId: String(data["schedule_id"] ?? ""),
892
+ startedAt: String(data["started_at"] ?? ""),
893
+ completedAt: data["completed_at"] ?? null,
894
+ filesFound: Number(data["files_found"] ?? 0),
895
+ filesNew: Number(data["files_new"] ?? 0),
896
+ filesSkipped: Number(data["files_skipped"] ?? 0),
897
+ filesFailed: Number(data["files_failed"] ?? 0),
898
+ status: String(data["status"] ?? ""),
899
+ errorMessage: data["error_message"] ?? null
900
+ };
901
+ }
595
902
 
596
903
  // src/resources/connectors.ts
597
904
  var VALID_TYPES = /* @__PURE__ */ new Set([
@@ -635,13 +942,54 @@ var ConnectorsResource = class {
635
942
  message: String(data["message"] ?? "")
636
943
  };
637
944
  }
945
+ /** Define a scheduled sync for a connector (Pro+ required). */
946
+ async createSchedule(connectorId, cronExpression, prefixFilter = null) {
947
+ const data = await this._t.post(`/connectors/${connectorId}/schedules`, {
948
+ cron_expression: cronExpression,
949
+ prefix_filter: prefixFilter
950
+ });
951
+ return syncScheduleFromDict(data);
952
+ }
953
+ /** Active schedules for a connector. */
954
+ async listSchedules(connectorId) {
955
+ const data = await this._t.get(`/connectors/${connectorId}/schedules`);
956
+ return (data ?? []).map(syncScheduleFromDict);
957
+ }
958
+ /** Delete a scheduled sync. */
959
+ async deleteSchedule(connectorId, scheduleId) {
960
+ await this._t.delete(`/connectors/${connectorId}/schedules/${scheduleId}`);
961
+ }
962
+ /** Run a schedule immediately instead of waiting for its cron time. */
963
+ async triggerSchedule(connectorId, scheduleId) {
964
+ const data = await this._t.post(
965
+ `/connectors/${connectorId}/schedules/${scheduleId}/trigger`
966
+ );
967
+ return syncLogFromDict(data);
968
+ }
969
+ /** Recent sync run logs for a schedule. */
970
+ async scheduleLogs(connectorId, scheduleId) {
971
+ const data = await this._t.get(
972
+ `/connectors/${connectorId}/schedules/${scheduleId}/logs`
973
+ );
974
+ return (data ?? []).map(syncLogFromDict);
975
+ }
638
976
  };
639
977
 
640
978
  // src/client.ts
641
979
  var DEFAULT_BASE_URL = "https://api.flexorch.com/v1";
980
+ function firstJobOrThrow(uploadResponse, filename, transport) {
981
+ const jobs = uploadResponse["jobs"] ?? [];
982
+ if (jobs.length > 0) {
983
+ return Job.fromDict(jobs[0], transport);
984
+ }
985
+ const rejected = uploadResponse["rejected"] ?? [];
986
+ const reason = rejected.length > 0 ? String(rejected[0]["error"]) : "unknown error";
987
+ throw new ValidationError(`${filename} was rejected: ${reason}`);
988
+ }
642
989
  var FlexOrchClient = class {
643
990
  jobs;
644
991
  datasets;
992
+ documents;
645
993
  usage;
646
994
  webhooks;
647
995
  connectors;
@@ -663,6 +1011,7 @@ var FlexOrchClient = class {
663
1011
  );
664
1012
  this.jobs = new JobsResource(this._transport);
665
1013
  this.datasets = new DatasetsResource(this._transport);
1014
+ this.documents = new DocumentsResource(this._transport);
666
1015
  this.usage = new UsageResource(this._transport);
667
1016
  this.webhooks = new WebhooksResource(this._transport);
668
1017
  this.connectors = new ConnectorsResource(this._transport);
@@ -680,13 +1029,13 @@ var FlexOrchClient = class {
680
1029
  chunks.push(chunk);
681
1030
  }
682
1031
  const blob = new Blob([Buffer.concat(chunks)], { type: "application/octet-stream" });
683
- form.append("file", blob, basename(filePath));
1032
+ form.append("files", blob, basename(filePath));
684
1033
  form.append("locale", opts.locale ?? "und");
685
1034
  if (opts.pipelineConfig) {
686
1035
  form.append("pipeline_config", JSON.stringify(opts.pipelineConfig));
687
1036
  }
688
1037
  const data = await this._transport.postForm("/data-process/async", form);
689
- return Job.fromDict(data, this._transport);
1038
+ return firstJobOrThrow(data, basename(filePath), this._transport);
690
1039
  }
691
1040
  async processMany(filePaths, opts = {}) {
692
1041
  const jobs = [];
@@ -705,7 +1054,7 @@ var FlexOrchClient = class {
705
1054
  form.append("pipeline_config", JSON.stringify(opts.pipelineConfig));
706
1055
  }
707
1056
  const data = await this._transport.postForm("/data-process/async", form);
708
- jobs.push(Job.fromDict(data, this._transport));
1057
+ jobs.push(firstJobOrThrow(data, key, this._transport));
709
1058
  }
710
1059
  return jobs;
711
1060
  }
@@ -912,12 +1261,13 @@ var FlexOrchReader = class {
912
1261
  };
913
1262
 
914
1263
  // src/index.ts
915
- var version = "0.2.0";
1264
+ var version = "0.3.0";
916
1265
  // Annotate the CommonJS export names for ESM import in node:
917
1266
  0 && (module.exports = {
918
1267
  AuthError,
919
1268
  Connector,
920
1269
  Dataset,
1270
+ Document,
921
1271
  FlexOrchClient,
922
1272
  FlexOrchError,
923
1273
  FlexOrchReader,