flexorch-sdk 0.2.3 → 0.3.1
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 +90 -38
- package/dist/{chunk-35RGZSFP.js → chunk-4KCMMRD7.js} +22 -2
- package/dist/{dataset-PP755LIW.js → dataset-E7EXJETI.js} +1 -1
- package/dist/index.cjs +369 -18
- package/dist/index.d.cts +204 -8
- package/dist/index.d.ts +204 -8
- package/dist/index.js +347 -17
- package/package.json +1 -1
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
|
-
|
|
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
|
|
315
|
+
"User-Agent": "flexorch-sdk-js/0.3.1"
|
|
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,27 @@ 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
|
+
/** Set from `dataset_summary.dataset_id` on a completed dataset_build job's response. */
|
|
409
|
+
datasetId;
|
|
369
410
|
/**
|
|
370
411
|
* True when the underlying pipeline execution completed but one or more
|
|
371
412
|
* non-critical steps failed (e.g. structured extraction couldn't find a
|
|
@@ -384,21 +425,37 @@ var Job = class _Job {
|
|
|
384
425
|
this.qualityGrade = data.qualityGrade;
|
|
385
426
|
this.qualityScore = data.qualityScore;
|
|
386
427
|
this.documentId = data.documentId;
|
|
428
|
+
this.executionId = data.executionId;
|
|
387
429
|
this.hasDataset = data.hasDataset;
|
|
430
|
+
this.datasetId = data.datasetId;
|
|
388
431
|
this.degraded = data.degraded;
|
|
389
432
|
this.failureReason = data.failureReason;
|
|
390
433
|
this._transport = data._transport;
|
|
391
434
|
}
|
|
392
435
|
static fromDict(data, transport) {
|
|
393
|
-
const quality = data["quality"] ?? {};
|
|
394
436
|
const executionSummary = data["execution_summary"];
|
|
437
|
+
const processingSummary = data["processing_summary"];
|
|
438
|
+
const datasetSummary = data["dataset_summary"];
|
|
439
|
+
let quality = data["quality"];
|
|
440
|
+
if (!quality && processingSummary) {
|
|
441
|
+
quality = processingSummary["quality"];
|
|
442
|
+
}
|
|
443
|
+
quality = quality ?? {};
|
|
444
|
+
const executionId = executionSummary?.["execution_id"] ?? processingSummary?.["execution_id"] ?? data["execution_id"] ?? null;
|
|
395
445
|
return new _Job({
|
|
396
446
|
id: String(data["job_id"] ?? data["id"] ?? ""),
|
|
397
447
|
status: String(data["status"] ?? ""),
|
|
398
448
|
qualityGrade: quality["grade"] ?? null,
|
|
399
449
|
qualityScore: quality["score"] ?? null,
|
|
400
450
|
documentId: data["document_id"] ?? null,
|
|
401
|
-
|
|
451
|
+
executionId,
|
|
452
|
+
// dataset_summary is only present on a completed dataset_build job's
|
|
453
|
+
// response — neither has_dataset nor processing_summary is ever set
|
|
454
|
+
// for that job type, so without this .dataset() always returned null
|
|
455
|
+
// for the job.buildDataset().wait().dataset() chain even though the
|
|
456
|
+
// dataset had been built successfully.
|
|
457
|
+
hasDataset: Boolean(data["has_dataset"] ?? processingSummary?.["has_dataset"] ?? Boolean(datasetSummary) ?? false),
|
|
458
|
+
datasetId: datasetSummary?.["dataset_id"] ?? null,
|
|
402
459
|
degraded: Boolean(executionSummary?.["degraded"] ?? false),
|
|
403
460
|
failureReason: data["failure_reason"] ?? null,
|
|
404
461
|
_transport: transport
|
|
@@ -426,15 +483,56 @@ var Job = class _Job {
|
|
|
426
483
|
throw new JobTimeoutError(this.id, timeout);
|
|
427
484
|
}
|
|
428
485
|
async dataset() {
|
|
486
|
+
const { Dataset: Dataset2 } = await Promise.resolve().then(() => (init_dataset(), dataset_exports));
|
|
487
|
+
if (this.datasetId !== null) {
|
|
488
|
+
const data2 = await this._transport.get(`/datasets/${this.datasetId}`);
|
|
489
|
+
return Dataset2.fromDict(data2, this._transport);
|
|
490
|
+
}
|
|
429
491
|
if (!this.hasDataset) return null;
|
|
430
492
|
const data = await this._transport.get("/datasets", {
|
|
431
493
|
job_id: this.id
|
|
432
494
|
});
|
|
433
495
|
const items = data["items"] ?? [];
|
|
434
496
|
if (items.length === 0) return null;
|
|
435
|
-
const { Dataset: Dataset2 } = await Promise.resolve().then(() => (init_dataset(), dataset_exports));
|
|
436
497
|
return Dataset2.fromDict(items[0], this._transport);
|
|
437
498
|
}
|
|
499
|
+
/**
|
|
500
|
+
* Build a dataset from this job's execution.
|
|
501
|
+
*
|
|
502
|
+
* A completed data_process job does not have a dataset yet — building one
|
|
503
|
+
* is a separate, explicit step (`POST
|
|
504
|
+
* /datasets/build-from-execution/{executionId}`). Call this after
|
|
505
|
+
* `.wait()`, then `.wait()` again on the returned dataset_build Job before
|
|
506
|
+
* calling `.dataset()`:
|
|
507
|
+
*
|
|
508
|
+
* ```ts
|
|
509
|
+
* const job = await client.process("invoice.pdf");
|
|
510
|
+
* const done = await job.wait();
|
|
511
|
+
* const dataset = await (await done.buildDataset()).wait().then(j => j.dataset());
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @throws {Error} If this job has no executionId to build a dataset from
|
|
515
|
+
* (e.g. it failed, or is itself a dataset_build job).
|
|
516
|
+
*/
|
|
517
|
+
async buildDataset(opts = {}) {
|
|
518
|
+
if (!this.executionId) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
`Job ${this.id} has no executionId to build a dataset from (job must be a completed data_process job).`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const body = {
|
|
524
|
+
force_rebuild: opts.forceRebuild ?? false,
|
|
525
|
+
replace_existing: opts.replaceExisting ?? false
|
|
526
|
+
};
|
|
527
|
+
if (opts.name !== void 0) body["name"] = opts.name;
|
|
528
|
+
if (opts.description !== void 0) body["description"] = opts.description;
|
|
529
|
+
if (opts.slug !== void 0) body["slug"] = opts.slug;
|
|
530
|
+
const data = await this._transport.post(
|
|
531
|
+
`/datasets/build-from-execution/${this.executionId}`,
|
|
532
|
+
body
|
|
533
|
+
);
|
|
534
|
+
return _Job.fromDict(data, this._transport);
|
|
535
|
+
}
|
|
438
536
|
toString() {
|
|
439
537
|
return `Job(id=${this.id}, status=${this.status}, grade=${this.qualityGrade})`;
|
|
440
538
|
}
|
|
@@ -478,6 +576,15 @@ var SearchResult = class _SearchResult {
|
|
|
478
576
|
};
|
|
479
577
|
|
|
480
578
|
// src/resources/jobs.ts
|
|
579
|
+
var VALID_RATINGS = /* @__PURE__ */ new Set(["up", "down"]);
|
|
580
|
+
var VALID_ISSUES = /* @__PURE__ */ new Set([
|
|
581
|
+
"wrong_doc_type",
|
|
582
|
+
"missing_fields",
|
|
583
|
+
"wrong_values",
|
|
584
|
+
"pii_missed",
|
|
585
|
+
"pii_over_masked",
|
|
586
|
+
"other"
|
|
587
|
+
]);
|
|
481
588
|
var JobsResource = class {
|
|
482
589
|
constructor(_t) {
|
|
483
590
|
this._t = _t;
|
|
@@ -495,6 +602,34 @@ var JobsResource = class {
|
|
|
495
602
|
const items = data["items"] ?? [];
|
|
496
603
|
return items.map((item) => Job.fromDict(item, this._t));
|
|
497
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Submit user feedback for a completed job. Upsert — a second call for the
|
|
607
|
+
* same job replaces the previous feedback.
|
|
608
|
+
*
|
|
609
|
+
* @param rating "up" or "down".
|
|
610
|
+
* @param opts.issue When rating="down": "wrong_doc_type" | "missing_fields" |
|
|
611
|
+
* "wrong_values" | "pii_missed" | "pii_over_masked" | "other".
|
|
612
|
+
*/
|
|
613
|
+
async submitFeedback(jobId, rating, opts = {}) {
|
|
614
|
+
if (!VALID_RATINGS.has(rating)) {
|
|
615
|
+
throw new Error(`Invalid rating "${rating}". Valid: ${[...VALID_RATINGS].join(", ")}`);
|
|
616
|
+
}
|
|
617
|
+
if (opts.issue !== void 0 && !VALID_ISSUES.has(opts.issue)) {
|
|
618
|
+
throw new Error(`Invalid issue "${opts.issue}". Valid: ${[...VALID_ISSUES].join(", ")}`);
|
|
619
|
+
}
|
|
620
|
+
const data = await this._t.post(`/jobs/${jobId}/feedback`, {
|
|
621
|
+
rating,
|
|
622
|
+
issue: opts.issue ?? null,
|
|
623
|
+
notes: opts.notes ?? null
|
|
624
|
+
});
|
|
625
|
+
return jobFeedbackFromDict(data);
|
|
626
|
+
}
|
|
627
|
+
/** Existing feedback for a job, or null if none was submitted. */
|
|
628
|
+
async getFeedback(jobId) {
|
|
629
|
+
const data = await this._t.get(`/jobs/${jobId}/feedback`);
|
|
630
|
+
if (!data) return null;
|
|
631
|
+
return jobFeedbackFromDict(data);
|
|
632
|
+
}
|
|
498
633
|
};
|
|
499
634
|
|
|
500
635
|
// src/resources/datasets.ts
|
|
@@ -512,10 +647,121 @@ var DatasetsResource = class {
|
|
|
512
647
|
const params = {};
|
|
513
648
|
if (opts.page !== void 0) params["page"] = String(opts.page);
|
|
514
649
|
if (opts.pageSize !== void 0) params["page_size"] = String(opts.pageSize);
|
|
650
|
+
if (opts.status !== void 0) params["status"] = opts.status;
|
|
651
|
+
if (opts.sourceExecutionId !== void 0) params["source_execution_id"] = String(opts.sourceExecutionId);
|
|
652
|
+
if (opts.sourceDocumentId !== void 0) params["source_document_id"] = String(opts.sourceDocumentId);
|
|
653
|
+
if (opts.q !== void 0) params["q"] = opts.q;
|
|
515
654
|
const data = await this._t.get("/datasets", params);
|
|
516
655
|
const items = data["items"] ?? [];
|
|
517
656
|
return items.map((item) => Dataset.fromDict(item, this._t));
|
|
518
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* Build a dataset from a completed execution.
|
|
660
|
+
*
|
|
661
|
+
* Prefer `Job.buildDataset()` when you already have a Job object — this is
|
|
662
|
+
* the lower-level call for when you only have an executionId (e.g. from
|
|
663
|
+
* `Document.latestExecution`).
|
|
664
|
+
*
|
|
665
|
+
* @returns A dataset_build Job — call `.wait()` then `.dataset()`.
|
|
666
|
+
*/
|
|
667
|
+
async buildFromExecution(executionId, opts = {}) {
|
|
668
|
+
const body = {
|
|
669
|
+
force_rebuild: opts.forceRebuild ?? false,
|
|
670
|
+
replace_existing: opts.replaceExisting ?? false
|
|
671
|
+
};
|
|
672
|
+
if (opts.name !== void 0) body["name"] = opts.name;
|
|
673
|
+
if (opts.description !== void 0) body["description"] = opts.description;
|
|
674
|
+
if (opts.slug !== void 0) body["slug"] = opts.slug;
|
|
675
|
+
const data = await this._t.post(
|
|
676
|
+
`/datasets/build-from-execution/${executionId}`,
|
|
677
|
+
body
|
|
678
|
+
);
|
|
679
|
+
return Job.fromDict(data, this._t);
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/models/document.ts
|
|
684
|
+
var Document = class _Document {
|
|
685
|
+
id;
|
|
686
|
+
filename;
|
|
687
|
+
fileExt;
|
|
688
|
+
status;
|
|
689
|
+
storagePath;
|
|
690
|
+
createdAt;
|
|
691
|
+
processingCount;
|
|
692
|
+
latestExecution;
|
|
693
|
+
dataset;
|
|
694
|
+
processingHistory;
|
|
695
|
+
relatedDatasets;
|
|
696
|
+
_transport;
|
|
697
|
+
constructor(data) {
|
|
698
|
+
this.id = data.id;
|
|
699
|
+
this.filename = data.filename;
|
|
700
|
+
this.fileExt = data.fileExt;
|
|
701
|
+
this.status = data.status;
|
|
702
|
+
this.storagePath = data.storagePath;
|
|
703
|
+
this.createdAt = data.createdAt;
|
|
704
|
+
this.processingCount = data.processingCount;
|
|
705
|
+
this.latestExecution = data.latestExecution;
|
|
706
|
+
this.dataset = data.dataset;
|
|
707
|
+
this.processingHistory = data.processingHistory;
|
|
708
|
+
this.relatedDatasets = data.relatedDatasets;
|
|
709
|
+
this._transport = data._transport;
|
|
710
|
+
}
|
|
711
|
+
static fromDict(data, transport) {
|
|
712
|
+
return new _Document({
|
|
713
|
+
id: String(data["id"] ?? ""),
|
|
714
|
+
filename: String(data["filename"] ?? ""),
|
|
715
|
+
fileExt: String(data["file_ext"] ?? ""),
|
|
716
|
+
status: String(data["status"] ?? ""),
|
|
717
|
+
storagePath: String(data["storage_path"] ?? ""),
|
|
718
|
+
createdAt: String(data["created_at"] ?? ""),
|
|
719
|
+
processingCount: Number(data["processing_count"] ?? 0),
|
|
720
|
+
latestExecution: data["latest_execution"] ?? null,
|
|
721
|
+
dataset: data["dataset"] ?? null,
|
|
722
|
+
processingHistory: data["processing_history"] ?? [],
|
|
723
|
+
relatedDatasets: data["related_datasets"] ?? [],
|
|
724
|
+
_transport: transport
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Re-queue this document through the processing pipeline.
|
|
729
|
+
*
|
|
730
|
+
* Raises (via the API): 400 DOCUMENT_FILE_NOT_AVAILABLE if the source file
|
|
731
|
+
* is no longer on disk, or 400 REPROCESS_NOT_SUPPORTED for
|
|
732
|
+
* connector-sourced (e.g. S3) documents.
|
|
733
|
+
*/
|
|
734
|
+
async reprocess(pipelineConfig) {
|
|
735
|
+
const body = {};
|
|
736
|
+
if (pipelineConfig) body["pipeline_config"] = pipelineConfig;
|
|
737
|
+
const data = await this._transport.post(`/documents/${this.id}/reprocess`, body);
|
|
738
|
+
return Job.fromDict(data, this._transport);
|
|
739
|
+
}
|
|
740
|
+
toString() {
|
|
741
|
+
return `Document(id=${this.id}, filename=${this.filename}, status=${this.status})`;
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// src/resources/documents.ts
|
|
746
|
+
var DocumentsResource = class {
|
|
747
|
+
constructor(_t) {
|
|
748
|
+
this._t = _t;
|
|
749
|
+
}
|
|
750
|
+
_t;
|
|
751
|
+
/** Fetch a single document, including processingHistory and relatedDatasets. */
|
|
752
|
+
async get(documentId) {
|
|
753
|
+
const data = await this._t.get(`/documents/${documentId}`);
|
|
754
|
+
return Document.fromDict(data, this._t);
|
|
755
|
+
}
|
|
756
|
+
/** List documents for the current tenant, newest first. */
|
|
757
|
+
async list(opts = {}) {
|
|
758
|
+
const params = {};
|
|
759
|
+
if (opts.page !== void 0) params["page"] = String(opts.page);
|
|
760
|
+
if (opts.pageSize !== void 0) params["page_size"] = String(opts.pageSize);
|
|
761
|
+
const data = await this._t.get("/documents", params);
|
|
762
|
+
const items = data["items"] ?? [];
|
|
763
|
+
return items.map((item) => Document.fromDict(item, this._t));
|
|
764
|
+
}
|
|
519
765
|
};
|
|
520
766
|
|
|
521
767
|
// src/resources/usage.ts
|
|
@@ -525,15 +771,51 @@ var UsageResource = class {
|
|
|
525
771
|
}
|
|
526
772
|
_t;
|
|
527
773
|
async current() {
|
|
528
|
-
const data = await this._t.get("/usage
|
|
774
|
+
const data = await this._t.get("/usage") ?? {};
|
|
775
|
+
const trial = data["trial"] ?? {};
|
|
776
|
+
const usage = data["usage"] ?? {};
|
|
777
|
+
const credits = usage["credits"] ?? {};
|
|
778
|
+
return {
|
|
779
|
+
plan: String(data["plan"] ?? ""),
|
|
780
|
+
creditsUsed: Number(credits["used"] ?? 0),
|
|
781
|
+
creditsLimit: credits["limit"] ?? null,
|
|
782
|
+
creditsRemaining: credits["remaining"] ?? null,
|
|
783
|
+
isTrial: Boolean(trial["is_trial"] ?? false),
|
|
784
|
+
trialEndsAt: trial["trial_ends_at"] ?? null,
|
|
785
|
+
trialDaysRemaining: trial["trial_days_remaining"] ?? null
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
/** @param period "7d" | "30d" | "90d". Default: "30d". */
|
|
789
|
+
async history(period = "30d") {
|
|
790
|
+
const data = await this._t.get("/usage/history", { period });
|
|
791
|
+
return (data ?? []).map((item) => ({
|
|
792
|
+
date: String(item["date"] ?? ""),
|
|
793
|
+
creditsUsed: Number(item["credits_used"] ?? 0),
|
|
794
|
+
jobsCount: Number(item["jobs_count"] ?? 0)
|
|
795
|
+
}));
|
|
796
|
+
}
|
|
797
|
+
/** @param period "7d" | "30d" | "90d". Default: "30d". */
|
|
798
|
+
async qualityTrend(period = "30d") {
|
|
799
|
+
const data = await this._t.get("/usage/quality-trend", { period });
|
|
800
|
+
return (data ?? []).map((item) => ({
|
|
801
|
+
date: String(item["date"] ?? ""),
|
|
802
|
+
avgQualityScore: Number(item["avg_quality_score"] ?? 0),
|
|
803
|
+
gradeDistribution: item["grade_distribution"] ?? {},
|
|
804
|
+
avgFieldFillRate: item["avg_field_fill_rate"] ?? null,
|
|
805
|
+
jobCount: Number(item["job_count"] ?? 0)
|
|
806
|
+
}));
|
|
807
|
+
}
|
|
808
|
+
/** Current rate limit configuration and window usage. Does not consume a request slot. */
|
|
809
|
+
async rateLimits() {
|
|
810
|
+
const data = await this._t.get("/usage/rate-limits") ?? {};
|
|
529
811
|
return {
|
|
530
812
|
plan: String(data["plan"] ?? ""),
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
813
|
+
unlimited: Boolean(data["unlimited"] ?? false),
|
|
814
|
+
limit: data["limit"] ?? null,
|
|
815
|
+
used: data["used"] ?? null,
|
|
816
|
+
remaining: data["remaining"] ?? null,
|
|
817
|
+
windowSeconds: Number(data["window_seconds"] ?? 0),
|
|
818
|
+
resetInSeconds: data["reset_in_seconds"] ?? null
|
|
537
819
|
};
|
|
538
820
|
}
|
|
539
821
|
};
|
|
@@ -605,6 +887,32 @@ var Connector = class _Connector {
|
|
|
605
887
|
return `Connector(id=${this.id}, name=${this.name}, type=${this.type})`;
|
|
606
888
|
}
|
|
607
889
|
};
|
|
890
|
+
function syncScheduleFromDict(data) {
|
|
891
|
+
return {
|
|
892
|
+
id: String(data["id"] ?? ""),
|
|
893
|
+
connectorId: String(data["connector_id"] ?? ""),
|
|
894
|
+
cronExpression: String(data["cron_expression"] ?? ""),
|
|
895
|
+
prefixFilter: data["prefix_filter"] ?? null,
|
|
896
|
+
isActive: Boolean(data["is_active"] ?? true),
|
|
897
|
+
lastRunAt: data["last_run_at"] ?? null,
|
|
898
|
+
nextRunAt: data["next_run_at"] ?? null,
|
|
899
|
+
createdAt: String(data["created_at"] ?? "")
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
function syncLogFromDict(data) {
|
|
903
|
+
return {
|
|
904
|
+
id: String(data["id"] ?? ""),
|
|
905
|
+
scheduleId: String(data["schedule_id"] ?? ""),
|
|
906
|
+
startedAt: String(data["started_at"] ?? ""),
|
|
907
|
+
completedAt: data["completed_at"] ?? null,
|
|
908
|
+
filesFound: Number(data["files_found"] ?? 0),
|
|
909
|
+
filesNew: Number(data["files_new"] ?? 0),
|
|
910
|
+
filesSkipped: Number(data["files_skipped"] ?? 0),
|
|
911
|
+
filesFailed: Number(data["files_failed"] ?? 0),
|
|
912
|
+
status: String(data["status"] ?? ""),
|
|
913
|
+
errorMessage: data["error_message"] ?? null
|
|
914
|
+
};
|
|
915
|
+
}
|
|
608
916
|
|
|
609
917
|
// src/resources/connectors.ts
|
|
610
918
|
var VALID_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -648,13 +956,54 @@ var ConnectorsResource = class {
|
|
|
648
956
|
message: String(data["message"] ?? "")
|
|
649
957
|
};
|
|
650
958
|
}
|
|
959
|
+
/** Define a scheduled sync for a connector (Pro+ required). */
|
|
960
|
+
async createSchedule(connectorId, cronExpression, prefixFilter = null) {
|
|
961
|
+
const data = await this._t.post(`/connectors/${connectorId}/schedules`, {
|
|
962
|
+
cron_expression: cronExpression,
|
|
963
|
+
prefix_filter: prefixFilter
|
|
964
|
+
});
|
|
965
|
+
return syncScheduleFromDict(data);
|
|
966
|
+
}
|
|
967
|
+
/** Active schedules for a connector. */
|
|
968
|
+
async listSchedules(connectorId) {
|
|
969
|
+
const data = await this._t.get(`/connectors/${connectorId}/schedules`);
|
|
970
|
+
return (data ?? []).map(syncScheduleFromDict);
|
|
971
|
+
}
|
|
972
|
+
/** Delete a scheduled sync. */
|
|
973
|
+
async deleteSchedule(connectorId, scheduleId) {
|
|
974
|
+
await this._t.delete(`/connectors/${connectorId}/schedules/${scheduleId}`);
|
|
975
|
+
}
|
|
976
|
+
/** Run a schedule immediately instead of waiting for its cron time. */
|
|
977
|
+
async triggerSchedule(connectorId, scheduleId) {
|
|
978
|
+
const data = await this._t.post(
|
|
979
|
+
`/connectors/${connectorId}/schedules/${scheduleId}/trigger`
|
|
980
|
+
);
|
|
981
|
+
return syncLogFromDict(data);
|
|
982
|
+
}
|
|
983
|
+
/** Recent sync run logs for a schedule. */
|
|
984
|
+
async scheduleLogs(connectorId, scheduleId) {
|
|
985
|
+
const data = await this._t.get(
|
|
986
|
+
`/connectors/${connectorId}/schedules/${scheduleId}/logs`
|
|
987
|
+
);
|
|
988
|
+
return (data ?? []).map(syncLogFromDict);
|
|
989
|
+
}
|
|
651
990
|
};
|
|
652
991
|
|
|
653
992
|
// src/client.ts
|
|
654
993
|
var DEFAULT_BASE_URL = "https://api.flexorch.com/v1";
|
|
994
|
+
function firstJobOrThrow(uploadResponse, filename, transport) {
|
|
995
|
+
const jobs = uploadResponse["jobs"] ?? [];
|
|
996
|
+
if (jobs.length > 0) {
|
|
997
|
+
return Job.fromDict(jobs[0], transport);
|
|
998
|
+
}
|
|
999
|
+
const rejected = uploadResponse["rejected"] ?? [];
|
|
1000
|
+
const reason = rejected.length > 0 ? String(rejected[0]["error"]) : "unknown error";
|
|
1001
|
+
throw new ValidationError(`${filename} was rejected: ${reason}`);
|
|
1002
|
+
}
|
|
655
1003
|
var FlexOrchClient = class {
|
|
656
1004
|
jobs;
|
|
657
1005
|
datasets;
|
|
1006
|
+
documents;
|
|
658
1007
|
usage;
|
|
659
1008
|
webhooks;
|
|
660
1009
|
connectors;
|
|
@@ -676,6 +1025,7 @@ var FlexOrchClient = class {
|
|
|
676
1025
|
);
|
|
677
1026
|
this.jobs = new JobsResource(this._transport);
|
|
678
1027
|
this.datasets = new DatasetsResource(this._transport);
|
|
1028
|
+
this.documents = new DocumentsResource(this._transport);
|
|
679
1029
|
this.usage = new UsageResource(this._transport);
|
|
680
1030
|
this.webhooks = new WebhooksResource(this._transport);
|
|
681
1031
|
this.connectors = new ConnectorsResource(this._transport);
|
|
@@ -693,13 +1043,13 @@ var FlexOrchClient = class {
|
|
|
693
1043
|
chunks.push(chunk);
|
|
694
1044
|
}
|
|
695
1045
|
const blob = new Blob([Buffer.concat(chunks)], { type: "application/octet-stream" });
|
|
696
|
-
form.append("
|
|
1046
|
+
form.append("files", blob, basename(filePath));
|
|
697
1047
|
form.append("locale", opts.locale ?? "und");
|
|
698
1048
|
if (opts.pipelineConfig) {
|
|
699
1049
|
form.append("pipeline_config", JSON.stringify(opts.pipelineConfig));
|
|
700
1050
|
}
|
|
701
1051
|
const data = await this._transport.postForm("/data-process/async", form);
|
|
702
|
-
return
|
|
1052
|
+
return firstJobOrThrow(data, basename(filePath), this._transport);
|
|
703
1053
|
}
|
|
704
1054
|
async processMany(filePaths, opts = {}) {
|
|
705
1055
|
const jobs = [];
|
|
@@ -718,7 +1068,7 @@ var FlexOrchClient = class {
|
|
|
718
1068
|
form.append("pipeline_config", JSON.stringify(opts.pipelineConfig));
|
|
719
1069
|
}
|
|
720
1070
|
const data = await this._transport.postForm("/data-process/async", form);
|
|
721
|
-
jobs.push(
|
|
1071
|
+
jobs.push(firstJobOrThrow(data, key, this._transport));
|
|
722
1072
|
}
|
|
723
1073
|
return jobs;
|
|
724
1074
|
}
|
|
@@ -925,12 +1275,13 @@ var FlexOrchReader = class {
|
|
|
925
1275
|
};
|
|
926
1276
|
|
|
927
1277
|
// src/index.ts
|
|
928
|
-
var version = "0.
|
|
1278
|
+
var version = "0.3.1";
|
|
929
1279
|
// Annotate the CommonJS export names for ESM import in node:
|
|
930
1280
|
0 && (module.exports = {
|
|
931
1281
|
AuthError,
|
|
932
1282
|
Connector,
|
|
933
1283
|
Dataset,
|
|
1284
|
+
Document,
|
|
934
1285
|
FlexOrchClient,
|
|
935
1286
|
FlexOrchError,
|
|
936
1287
|
FlexOrchReader,
|