@dynamic-entity/server 2.2.0 → 2.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 +14 -1
- package/express.d.mts +1 -1
- package/express.d.ts +1 -1
- package/express.js +49 -21
- package/express.js.map +1 -1
- package/express.mjs +50 -22
- package/express.mjs.map +1 -1
- package/index.d.mts +4 -22
- package/index.d.ts +4 -22
- package/index.js +52 -23
- package/index.js.map +1 -1
- package/index.mjs +50 -23
- package/index.mjs.map +1 -1
- package/package.json +2 -2
- package/{write-template-C2dCEp48.d.mts → write-template-CzKVVjgT.d.mts} +20 -3
- package/{write-template-C2dCEp48.d.ts → write-template-CzKVVjgT.d.ts} +20 -3
package/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { padRow, cellText, decimalMarkFor, arrayBoundFor, deriveImportColumns, suggestMapping, toCsv, escapeFormula, applyMapping, completeFirstLine, validateMappingPlan, detectDelimiter, createCsvReader } from '@dynamic-entity/core';
|
|
2
|
+
export { cellText as sampleText } from '@dynamic-entity/core';
|
|
1
3
|
import zlib from 'zlib';
|
|
2
4
|
import ExcelJS from 'exceljs';
|
|
3
5
|
import { Readable } from 'stream';
|
|
4
|
-
import { padRow, deriveImportColumns, suggestMapping, toCsv, escapeFormula, applyMapping, createCsvReader, validateMappingPlan } from '@dynamic-entity/core';
|
|
5
6
|
|
|
6
7
|
// src/limits.ts
|
|
7
8
|
var DEFAULT_LIMITS = {
|
|
@@ -133,17 +134,6 @@ function destroySource(source) {
|
|
|
133
134
|
} catch {
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
|
-
|
|
137
|
-
// src/cell-text.ts
|
|
138
|
-
function sampleText(raw) {
|
|
139
|
-
if (raw === null || raw === void 0) return "";
|
|
140
|
-
if (raw instanceof Date) {
|
|
141
|
-
if (Number.isNaN(raw.getTime())) return "";
|
|
142
|
-
const iso = raw.toISOString();
|
|
143
|
-
return raw.getTime() % 864e5 === 0 ? iso.slice(0, 10) : iso;
|
|
144
|
-
}
|
|
145
|
-
return typeof raw === "string" ? raw : String(raw);
|
|
146
|
-
}
|
|
147
137
|
var LOCAL_HEADER = 67324752;
|
|
148
138
|
var CENTRAL_HEADER = 33639248;
|
|
149
139
|
var END_OF_CENTRAL = 101010256;
|
|
@@ -460,6 +450,12 @@ async function guardZip(source, limits) {
|
|
|
460
450
|
}
|
|
461
451
|
}
|
|
462
452
|
if (!sheet) {
|
|
453
|
+
if (!kept.has("xl/workbook.xml")) {
|
|
454
|
+
throw new ImportError(
|
|
455
|
+
"UNSUPPORTED_FORMAT",
|
|
456
|
+
"This is a zip archive that is not an Excel workbook. Upload an .xlsx or .csv file."
|
|
457
|
+
);
|
|
458
|
+
}
|
|
463
459
|
throw new ImportError("MALFORMED_FILE", "This workbook has no worksheet.");
|
|
464
460
|
}
|
|
465
461
|
const ordered = [...WANTED, sheet.name].map((wanted) => kept.get(wanted)).filter((entry) => entry !== void 0);
|
|
@@ -550,13 +546,36 @@ function detectFormat(head) {
|
|
|
550
546
|
}
|
|
551
547
|
return "csv";
|
|
552
548
|
}
|
|
553
|
-
async function* csvRows(stream) {
|
|
549
|
+
async function* csvRows(stream, limits, found, forced) {
|
|
554
550
|
const decoder = new TextDecoder("utf-8");
|
|
555
|
-
const
|
|
551
|
+
const maxHeader = limits.maxCellLength * limits.maxColumns + limits.maxColumns;
|
|
552
|
+
let held = "";
|
|
553
|
+
let reader = null;
|
|
554
|
+
const open = (headerLine) => {
|
|
555
|
+
found.delimiter = forced ?? detectDelimiter(headerLine);
|
|
556
|
+
return createCsvReader({ delimiter: found.delimiter });
|
|
557
|
+
};
|
|
556
558
|
for await (const chunk of stream) {
|
|
557
|
-
|
|
559
|
+
const text = decoder.decode(chunk, { stream: true });
|
|
560
|
+
if (!reader) {
|
|
561
|
+
held += text;
|
|
562
|
+
const line = completeFirstLine(held);
|
|
563
|
+
if (line === null) {
|
|
564
|
+
if (held.length > maxHeader) {
|
|
565
|
+
throw new ImportError("SHEET_TOO_LARGE", "The header row is longer than any row may be.");
|
|
566
|
+
}
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
reader = open(line);
|
|
570
|
+
for (const row of reader.push(held)) yield row;
|
|
571
|
+
held = "";
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
for (const row of reader.push(text)) yield row;
|
|
558
575
|
}
|
|
559
|
-
|
|
576
|
+
const rest = held + decoder.decode();
|
|
577
|
+
reader ??= open(completeFirstLine(rest) ?? rest);
|
|
578
|
+
for (const row of reader.push(rest)) yield row;
|
|
560
579
|
for (const row of reader.end()) yield row;
|
|
561
580
|
}
|
|
562
581
|
async function* guardRows(rows, width, limits) {
|
|
@@ -591,10 +610,12 @@ async function readSheet(options) {
|
|
|
591
610
|
const counted = limitBytes(toByteStream(options.stream), limits.maxBytes);
|
|
592
611
|
const { head, stream } = await peek(counted, MAGIC_BYTES);
|
|
593
612
|
const format = detectFormat(head);
|
|
594
|
-
const
|
|
613
|
+
const found = {};
|
|
614
|
+
const forced = /\.tsv$/i.test(options.filename ?? "") ? " " : void 0;
|
|
615
|
+
const rows = format === "xlsx" ? xlsxRows(stream, limits) : csvRows(stream, limits, found, forced);
|
|
595
616
|
const iterator = rows[Symbol.asyncIterator]();
|
|
596
617
|
const first = await iterator.next();
|
|
597
|
-
const headers = first.done ? [] : first.value.map(
|
|
618
|
+
const headers = first.done ? [] : first.value.map(cellText);
|
|
598
619
|
if (headers.length > limits.maxColumns) {
|
|
599
620
|
throw new ImportError(
|
|
600
621
|
"SHEET_TOO_LARGE",
|
|
@@ -605,7 +626,8 @@ async function readSheet(options) {
|
|
|
605
626
|
return {
|
|
606
627
|
format,
|
|
607
628
|
headers,
|
|
608
|
-
rows: closing(guardRows(remaining, headers.length, limits), options.stream)
|
|
629
|
+
rows: closing(guardRows(remaining, headers.length, limits), options.stream),
|
|
630
|
+
...found.delimiter ? { delimiter: found.delimiter } : {}
|
|
609
631
|
};
|
|
610
632
|
} catch (error) {
|
|
611
633
|
destroySource(options.stream);
|
|
@@ -657,6 +679,7 @@ async function runImport(options) {
|
|
|
657
679
|
filename: options.filename,
|
|
658
680
|
limits
|
|
659
681
|
});
|
|
682
|
+
const decimal = options.decimal ?? decimalMarkFor(sheet.delimiter);
|
|
660
683
|
const errors = [];
|
|
661
684
|
let errorCount = 0;
|
|
662
685
|
let imported = 0;
|
|
@@ -672,6 +695,7 @@ async function runImport(options) {
|
|
|
672
695
|
batch = [];
|
|
673
696
|
const result = applyMapping(rows, plan, config, {
|
|
674
697
|
lang: options.lang,
|
|
698
|
+
decimal,
|
|
675
699
|
rules: options.rules,
|
|
676
700
|
lookups: options.lookups,
|
|
677
701
|
firstRowNumber: firstRow
|
|
@@ -734,19 +758,22 @@ async function previewSheet(options) {
|
|
|
734
758
|
try {
|
|
735
759
|
for await (const row of sheet.rows) {
|
|
736
760
|
rowCount++;
|
|
737
|
-
if (sample.length < limits.sampleRows) sample.push(row.map(
|
|
761
|
+
if (sample.length < limits.sampleRows) sample.push(row.map(cellText));
|
|
738
762
|
}
|
|
739
763
|
} catch (error) {
|
|
740
764
|
destroySource(options.stream);
|
|
741
765
|
throw error;
|
|
742
766
|
}
|
|
743
|
-
const
|
|
767
|
+
const arrayBound = arrayBoundFor(sheet.headers, options.config, null, options.lang);
|
|
768
|
+
const { columns } = deriveImportColumns(options.config, { lang: options.lang, maxArrayRows: arrayBound });
|
|
744
769
|
return {
|
|
745
770
|
headers: sheet.headers,
|
|
746
771
|
sample,
|
|
747
772
|
rowCount,
|
|
748
773
|
suggestion: suggestMapping(sheet.headers, columns, options.config?.entity ?? ""),
|
|
749
|
-
format: sheet.format
|
|
774
|
+
format: sheet.format,
|
|
775
|
+
...sheet.delimiter ? { delimiter: sheet.delimiter } : {},
|
|
776
|
+
arrayBound
|
|
750
777
|
};
|
|
751
778
|
}
|
|
752
779
|
var TEMPLATE_EXTENSION = { csv: "csv", xlsx: "xlsx" };
|
|
@@ -795,6 +822,6 @@ function sheetName(name) {
|
|
|
795
822
|
return (cleaned || "Import").slice(0, 31);
|
|
796
823
|
}
|
|
797
824
|
|
|
798
|
-
export { DEFAULT_LIMITS, ImportError, TEMPLATE_EXTENSION, TEMPLATE_MEDIA_TYPE, cellValue, destroySource, detectFormat, guardRows, guardZip, limitBytes, peek, previewSheet, readSheet, resolveLimits, runImport,
|
|
825
|
+
export { DEFAULT_LIMITS, ImportError, TEMPLATE_EXTENSION, TEMPLATE_MEDIA_TYPE, cellValue, destroySource, detectFormat, guardRows, guardZip, limitBytes, peek, previewSheet, readSheet, resolveLimits, runImport, toByteStream, toErrorBody, writeTemplate, xlsxRows };
|
|
799
826
|
//# sourceMappingURL=index.mjs.map
|
|
800
827
|
//# sourceMappingURL=index.mjs.map
|