@objectstack/rest 12.4.0 → 12.6.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 +79 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +75 -20
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -519,6 +519,17 @@ async function coerceRow(rawRow, metaMap, ctx) {
|
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
// src/import-runner.ts
|
|
522
|
+
import { bulkWrite, withTransientRetry } from "@objectstack/core";
|
|
523
|
+
function extractRecordId(rec) {
|
|
524
|
+
const id = rec?.id ?? rec?.record?.id;
|
|
525
|
+
return id != null ? String(id) : void 0;
|
|
526
|
+
}
|
|
527
|
+
function toFailedResult(rowNo, err) {
|
|
528
|
+
const code = err?.code ?? "IMPORT_ROW_FAILED";
|
|
529
|
+
const message = typeof err?.message === "string" ? err.message.slice(0, 300) : "Row failed";
|
|
530
|
+
return { row: rowNo, ok: false, action: "failed", error: message, code };
|
|
531
|
+
}
|
|
532
|
+
var MAX_CREATE_BATCH_SIZE = 200;
|
|
522
533
|
function runImport(opts) {
|
|
523
534
|
const {
|
|
524
535
|
p,
|
|
@@ -606,7 +617,7 @@ function runImport(opts) {
|
|
|
606
617
|
return recs[0];
|
|
607
618
|
};
|
|
608
619
|
const writeCtx = { ...context ?? {}, skipAutomations: !runAutomations };
|
|
609
|
-
const results =
|
|
620
|
+
const results = new Array(rows.length);
|
|
610
621
|
let okCount = 0, errCount = 0, created = 0, updated = 0, skipped = 0;
|
|
611
622
|
let cancelled = false;
|
|
612
623
|
const snapshot = (processed) => ({
|
|
@@ -617,6 +628,47 @@ function runImport(opts) {
|
|
|
617
628
|
skipped,
|
|
618
629
|
errors: errCount
|
|
619
630
|
});
|
|
631
|
+
const canBulkCreate = typeof p.createManyData === "function";
|
|
632
|
+
const pendingCreates = [];
|
|
633
|
+
const flushPendingCreates = async () => {
|
|
634
|
+
if (pendingCreates.length === 0) return;
|
|
635
|
+
const batch = pendingCreates.splice(0, pendingCreates.length);
|
|
636
|
+
const writeResults = await bulkWrite(
|
|
637
|
+
batch.map((b) => b.data),
|
|
638
|
+
{
|
|
639
|
+
// Flush cadence follows progressEvery, but the write batch itself is
|
|
640
|
+
// capped independently — a caller-supplied progressEvery far above
|
|
641
|
+
// the issue's suggested 100-500 rows/batch must not translate into
|
|
642
|
+
// one oversized multi-row INSERT statement.
|
|
643
|
+
batchSize: Math.min(progressEvery, MAX_CREATE_BATCH_SIZE),
|
|
644
|
+
writeBatch: (chunk) => p.createManyData({
|
|
645
|
+
object: objectName,
|
|
646
|
+
records: chunk,
|
|
647
|
+
context: writeCtx,
|
|
648
|
+
...environmentId ? { environmentId } : {}
|
|
649
|
+
}).then((r) => r.records),
|
|
650
|
+
writeOne: (row) => p.createData({
|
|
651
|
+
object: objectName,
|
|
652
|
+
data: row,
|
|
653
|
+
context: writeCtx,
|
|
654
|
+
...environmentId ? { environmentId } : {}
|
|
655
|
+
})
|
|
656
|
+
}
|
|
657
|
+
);
|
|
658
|
+
for (const res of writeResults) {
|
|
659
|
+
const { index, rowNo } = batch[res.index];
|
|
660
|
+
if (res.ok) {
|
|
661
|
+
const id = extractRecordId(res.record);
|
|
662
|
+
okCount++;
|
|
663
|
+
created++;
|
|
664
|
+
if (collectUndo && id != null) undoLog.created.push(id);
|
|
665
|
+
results[index] = { row: rowNo, ok: true, action: "created", id };
|
|
666
|
+
} else {
|
|
667
|
+
errCount++;
|
|
668
|
+
results[index] = toFailedResult(rowNo, res.error);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
};
|
|
620
672
|
return (async () => {
|
|
621
673
|
for (let i = 0; i < rows.length; i++) {
|
|
622
674
|
const rowNo = i + 1;
|
|
@@ -630,7 +682,7 @@ function runImport(opts) {
|
|
|
630
682
|
if (errors.length > 0) {
|
|
631
683
|
const first2 = errors[0];
|
|
632
684
|
errCount++;
|
|
633
|
-
results
|
|
685
|
+
results[i] = { row: rowNo, ok: false, action: "failed", field: first2.field, code: first2.code, error: first2.message };
|
|
634
686
|
} else {
|
|
635
687
|
let existing = "none";
|
|
636
688
|
let handled = false;
|
|
@@ -638,11 +690,11 @@ function runImport(opts) {
|
|
|
638
690
|
existing = await findExisting(data);
|
|
639
691
|
if (existing === "ambiguous") {
|
|
640
692
|
errCount++;
|
|
641
|
-
results
|
|
693
|
+
results[i] = { row: rowNo, ok: false, action: "failed", code: "AMBIGUOUS_MATCH", error: `matchFields matched more than one ${objectName} record` };
|
|
642
694
|
handled = true;
|
|
643
695
|
} else if (existing === "blank" && (skipBlankMatchKey || writeMode === "update")) {
|
|
644
696
|
skipped++;
|
|
645
|
-
results
|
|
697
|
+
results[i] = { row: rowNo, ok: true, action: "skipped", code: "BLANK_MATCH_KEY" };
|
|
646
698
|
handled = true;
|
|
647
699
|
}
|
|
648
700
|
}
|
|
@@ -651,45 +703,46 @@ function runImport(opts) {
|
|
|
651
703
|
const willCreate = !willUpdate && (writeMode === "insert" || writeMode === "upsert");
|
|
652
704
|
if (!willUpdate && !willCreate) {
|
|
653
705
|
skipped++;
|
|
654
|
-
results
|
|
706
|
+
results[i] = { row: rowNo, ok: true, action: "skipped", code: "NO_MATCH" };
|
|
655
707
|
} else if (dryRun) {
|
|
656
708
|
okCount++;
|
|
657
709
|
if (willUpdate) {
|
|
658
710
|
updated++;
|
|
659
|
-
results
|
|
711
|
+
results[i] = { row: rowNo, ok: true, action: "updated", id: String(existing.id ?? "") || void 0 };
|
|
660
712
|
} else {
|
|
661
713
|
created++;
|
|
662
|
-
results
|
|
714
|
+
results[i] = { row: rowNo, ok: true, action: "created" };
|
|
663
715
|
}
|
|
664
716
|
} else if (willUpdate) {
|
|
665
717
|
const target = existing;
|
|
666
|
-
const res2 = await p.updateData({ object: objectName, id: target.id, data, context: writeCtx, ...environmentId ? { environmentId } : {} });
|
|
667
|
-
const id = res2
|
|
718
|
+
const res2 = await withTransientRetry(() => p.updateData({ object: objectName, id: target.id, data, context: writeCtx, ...environmentId ? { environmentId } : {} }));
|
|
719
|
+
const id = extractRecordId(res2) ?? String(target.id);
|
|
668
720
|
okCount++;
|
|
669
721
|
updated++;
|
|
670
722
|
if (collectUndo && target.id != null) {
|
|
671
723
|
undoLog.updated.push({ id: String(target.id), before: captureBefore(target, data) });
|
|
672
724
|
}
|
|
673
|
-
results
|
|
725
|
+
results[i] = { row: rowNo, ok: true, action: "updated", id };
|
|
726
|
+
} else if (canBulkCreate) {
|
|
727
|
+
pendingCreates.push({ index: i, rowNo, data });
|
|
674
728
|
} else {
|
|
675
729
|
const res2 = await p.createData({ object: objectName, data, context: writeCtx, ...environmentId ? { environmentId } : {} });
|
|
676
|
-
const id = res2
|
|
730
|
+
const id = extractRecordId(res2);
|
|
677
731
|
okCount++;
|
|
678
732
|
created++;
|
|
679
|
-
if (collectUndo && id != null) undoLog.created.push(
|
|
680
|
-
results
|
|
733
|
+
if (collectUndo && id != null) undoLog.created.push(id);
|
|
734
|
+
results[i] = { row: rowNo, ok: true, action: "created", id };
|
|
681
735
|
}
|
|
682
736
|
}
|
|
683
737
|
}
|
|
684
738
|
} catch (err) {
|
|
685
739
|
errCount++;
|
|
686
|
-
|
|
687
|
-
const message = typeof err?.message === "string" ? err.message.slice(0, 300) : "Row failed";
|
|
688
|
-
results.push({ row: rowNo, ok: false, action: "failed", error: message, code });
|
|
740
|
+
results[i] = toFailedResult(rowNo, err);
|
|
689
741
|
}
|
|
690
742
|
const processed = i + 1;
|
|
691
|
-
if (
|
|
692
|
-
await
|
|
743
|
+
if (processed % progressEvery === 0 || processed === rows.length) {
|
|
744
|
+
await flushPendingCreates();
|
|
745
|
+
if (onProgress) await onProgress(snapshot(processed));
|
|
693
746
|
}
|
|
694
747
|
if (shouldCancel && processed < rows.length && processed % progressEvery === 0) {
|
|
695
748
|
if (await shouldCancel()) {
|
|
@@ -698,10 +751,12 @@ function runImport(opts) {
|
|
|
698
751
|
}
|
|
699
752
|
}
|
|
700
753
|
}
|
|
754
|
+
await flushPendingCreates();
|
|
755
|
+
const compacted = results.filter((r) => r !== void 0);
|
|
701
756
|
return {
|
|
702
|
-
...snapshot(
|
|
757
|
+
...snapshot(compacted.length),
|
|
703
758
|
ok: okCount,
|
|
704
|
-
results,
|
|
759
|
+
results: compacted,
|
|
705
760
|
cancelled,
|
|
706
761
|
...collectUndo ? { undoLog } : {}
|
|
707
762
|
};
|