@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.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { I as ImportLimits } from './write-template-
|
|
2
|
-
export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-
|
|
3
|
-
|
|
1
|
+
import { I as ImportLimits } from './write-template-CzKVVjgT.mjs';
|
|
2
|
+
export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-CzKVVjgT.mjs';
|
|
3
|
+
export { cellText as sampleText } from '@dynamic-entity/core';
|
|
4
4
|
import 'node:stream';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -79,24 +79,6 @@ declare function toErrorBody(error: unknown): {
|
|
|
79
79
|
body: ImportErrorBody;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
/**
|
|
83
|
-
* cell-text.ts — how a typed cell is rendered when text is what has to cross the wire.
|
|
84
|
-
*
|
|
85
|
-
* Its own module because both the reader and the preview need it, and a second copy would be
|
|
86
|
-
* a second place for the date rule to be wrong.
|
|
87
|
-
*/
|
|
88
|
-
/**
|
|
89
|
-
* Render a cell as the text a mapping screen shows.
|
|
90
|
-
*
|
|
91
|
-
* It mirrors `coerceTypedCell`'s date rule on purpose. A preview sample crosses the wire as
|
|
92
|
-
* text and the browser then runs `coerceCell` over that text, so if this rendered a `Date`
|
|
93
|
-
* with `String()` the preview would show — and the browser would coerce — a different day
|
|
94
|
-
* from the one the import will store. That is a preview lying about the only thing it exists
|
|
95
|
-
* to show, and it would be wrong by exactly one day, silently, only for users at a negative
|
|
96
|
-
* UTC offset. `run-import.spec.ts` asserts the two agree rather than trusting this comment.
|
|
97
|
-
*/
|
|
98
|
-
declare function sampleText(raw: unknown): string;
|
|
99
|
-
|
|
100
82
|
/**
|
|
101
83
|
* guard-zip.ts — open the archive ourselves, and hand the parser only what it should see.
|
|
102
84
|
*
|
|
@@ -177,4 +159,4 @@ declare function cellValue(raw: unknown): unknown;
|
|
|
177
159
|
*/
|
|
178
160
|
declare function xlsxRows(source: AsyncIterable<Uint8Array>, limits: ImportLimits): AsyncGenerator<unknown[]>;
|
|
179
161
|
|
|
180
|
-
export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip,
|
|
162
|
+
export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip, toErrorBody, xlsxRows };
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { I as ImportLimits } from './write-template-
|
|
2
|
-
export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-
|
|
3
|
-
|
|
1
|
+
import { I as ImportLimits } from './write-template-CzKVVjgT.js';
|
|
2
|
+
export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-CzKVVjgT.js';
|
|
3
|
+
export { cellText as sampleText } from '@dynamic-entity/core';
|
|
4
4
|
import 'node:stream';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -79,24 +79,6 @@ declare function toErrorBody(error: unknown): {
|
|
|
79
79
|
body: ImportErrorBody;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
/**
|
|
83
|
-
* cell-text.ts — how a typed cell is rendered when text is what has to cross the wire.
|
|
84
|
-
*
|
|
85
|
-
* Its own module because both the reader and the preview need it, and a second copy would be
|
|
86
|
-
* a second place for the date rule to be wrong.
|
|
87
|
-
*/
|
|
88
|
-
/**
|
|
89
|
-
* Render a cell as the text a mapping screen shows.
|
|
90
|
-
*
|
|
91
|
-
* It mirrors `coerceTypedCell`'s date rule on purpose. A preview sample crosses the wire as
|
|
92
|
-
* text and the browser then runs `coerceCell` over that text, so if this rendered a `Date`
|
|
93
|
-
* with `String()` the preview would show — and the browser would coerce — a different day
|
|
94
|
-
* from the one the import will store. That is a preview lying about the only thing it exists
|
|
95
|
-
* to show, and it would be wrong by exactly one day, silently, only for users at a negative
|
|
96
|
-
* UTC offset. `run-import.spec.ts` asserts the two agree rather than trusting this comment.
|
|
97
|
-
*/
|
|
98
|
-
declare function sampleText(raw: unknown): string;
|
|
99
|
-
|
|
100
82
|
/**
|
|
101
83
|
* guard-zip.ts — open the archive ourselves, and hand the parser only what it should see.
|
|
102
84
|
*
|
|
@@ -177,4 +159,4 @@ declare function cellValue(raw: unknown): unknown;
|
|
|
177
159
|
*/
|
|
178
160
|
declare function xlsxRows(source: AsyncIterable<Uint8Array>, limits: ImportLimits): AsyncGenerator<unknown[]>;
|
|
179
161
|
|
|
180
|
-
export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip,
|
|
162
|
+
export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip, toErrorBody, xlsxRows };
|
package/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var core = require('@dynamic-entity/core');
|
|
3
4
|
var zlib = require('zlib');
|
|
4
5
|
var ExcelJS = require('exceljs');
|
|
5
6
|
var stream = require('stream');
|
|
6
|
-
var core = require('@dynamic-entity/core');
|
|
7
7
|
|
|
8
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
9
|
|
|
@@ -140,17 +140,6 @@ function destroySource(source) {
|
|
|
140
140
|
} catch {
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
|
|
144
|
-
// src/cell-text.ts
|
|
145
|
-
function sampleText(raw) {
|
|
146
|
-
if (raw === null || raw === void 0) return "";
|
|
147
|
-
if (raw instanceof Date) {
|
|
148
|
-
if (Number.isNaN(raw.getTime())) return "";
|
|
149
|
-
const iso = raw.toISOString();
|
|
150
|
-
return raw.getTime() % 864e5 === 0 ? iso.slice(0, 10) : iso;
|
|
151
|
-
}
|
|
152
|
-
return typeof raw === "string" ? raw : String(raw);
|
|
153
|
-
}
|
|
154
143
|
var LOCAL_HEADER = 67324752;
|
|
155
144
|
var CENTRAL_HEADER = 33639248;
|
|
156
145
|
var END_OF_CENTRAL = 101010256;
|
|
@@ -467,6 +456,12 @@ async function guardZip(source, limits) {
|
|
|
467
456
|
}
|
|
468
457
|
}
|
|
469
458
|
if (!sheet) {
|
|
459
|
+
if (!kept.has("xl/workbook.xml")) {
|
|
460
|
+
throw new ImportError(
|
|
461
|
+
"UNSUPPORTED_FORMAT",
|
|
462
|
+
"This is a zip archive that is not an Excel workbook. Upload an .xlsx or .csv file."
|
|
463
|
+
);
|
|
464
|
+
}
|
|
470
465
|
throw new ImportError("MALFORMED_FILE", "This workbook has no worksheet.");
|
|
471
466
|
}
|
|
472
467
|
const ordered = [...WANTED, sheet.name].map((wanted) => kept.get(wanted)).filter((entry) => entry !== void 0);
|
|
@@ -557,13 +552,36 @@ function detectFormat(head) {
|
|
|
557
552
|
}
|
|
558
553
|
return "csv";
|
|
559
554
|
}
|
|
560
|
-
async function* csvRows(stream) {
|
|
555
|
+
async function* csvRows(stream, limits, found, forced) {
|
|
561
556
|
const decoder = new TextDecoder("utf-8");
|
|
562
|
-
const
|
|
557
|
+
const maxHeader = limits.maxCellLength * limits.maxColumns + limits.maxColumns;
|
|
558
|
+
let held = "";
|
|
559
|
+
let reader = null;
|
|
560
|
+
const open = (headerLine) => {
|
|
561
|
+
found.delimiter = forced ?? core.detectDelimiter(headerLine);
|
|
562
|
+
return core.createCsvReader({ delimiter: found.delimiter });
|
|
563
|
+
};
|
|
563
564
|
for await (const chunk of stream) {
|
|
564
|
-
|
|
565
|
+
const text = decoder.decode(chunk, { stream: true });
|
|
566
|
+
if (!reader) {
|
|
567
|
+
held += text;
|
|
568
|
+
const line = core.completeFirstLine(held);
|
|
569
|
+
if (line === null) {
|
|
570
|
+
if (held.length > maxHeader) {
|
|
571
|
+
throw new ImportError("SHEET_TOO_LARGE", "The header row is longer than any row may be.");
|
|
572
|
+
}
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
reader = open(line);
|
|
576
|
+
for (const row of reader.push(held)) yield row;
|
|
577
|
+
held = "";
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
for (const row of reader.push(text)) yield row;
|
|
565
581
|
}
|
|
566
|
-
|
|
582
|
+
const rest = held + decoder.decode();
|
|
583
|
+
reader ??= open(core.completeFirstLine(rest) ?? rest);
|
|
584
|
+
for (const row of reader.push(rest)) yield row;
|
|
567
585
|
for (const row of reader.end()) yield row;
|
|
568
586
|
}
|
|
569
587
|
async function* guardRows(rows, width, limits) {
|
|
@@ -598,10 +616,12 @@ async function readSheet(options) {
|
|
|
598
616
|
const counted = limitBytes(toByteStream(options.stream), limits.maxBytes);
|
|
599
617
|
const { head, stream } = await peek(counted, MAGIC_BYTES);
|
|
600
618
|
const format = detectFormat(head);
|
|
601
|
-
const
|
|
619
|
+
const found = {};
|
|
620
|
+
const forced = /\.tsv$/i.test(options.filename ?? "") ? " " : void 0;
|
|
621
|
+
const rows = format === "xlsx" ? xlsxRows(stream, limits) : csvRows(stream, limits, found, forced);
|
|
602
622
|
const iterator = rows[Symbol.asyncIterator]();
|
|
603
623
|
const first = await iterator.next();
|
|
604
|
-
const headers = first.done ? [] : first.value.map(
|
|
624
|
+
const headers = first.done ? [] : first.value.map(core.cellText);
|
|
605
625
|
if (headers.length > limits.maxColumns) {
|
|
606
626
|
throw new ImportError(
|
|
607
627
|
"SHEET_TOO_LARGE",
|
|
@@ -612,7 +632,8 @@ async function readSheet(options) {
|
|
|
612
632
|
return {
|
|
613
633
|
format,
|
|
614
634
|
headers,
|
|
615
|
-
rows: closing(guardRows(remaining, headers.length, limits), options.stream)
|
|
635
|
+
rows: closing(guardRows(remaining, headers.length, limits), options.stream),
|
|
636
|
+
...found.delimiter ? { delimiter: found.delimiter } : {}
|
|
616
637
|
};
|
|
617
638
|
} catch (error) {
|
|
618
639
|
destroySource(options.stream);
|
|
@@ -664,6 +685,7 @@ async function runImport(options) {
|
|
|
664
685
|
filename: options.filename,
|
|
665
686
|
limits
|
|
666
687
|
});
|
|
688
|
+
const decimal = options.decimal ?? core.decimalMarkFor(sheet.delimiter);
|
|
667
689
|
const errors = [];
|
|
668
690
|
let errorCount = 0;
|
|
669
691
|
let imported = 0;
|
|
@@ -679,6 +701,7 @@ async function runImport(options) {
|
|
|
679
701
|
batch = [];
|
|
680
702
|
const result = core.applyMapping(rows, plan, config, {
|
|
681
703
|
lang: options.lang,
|
|
704
|
+
decimal,
|
|
682
705
|
rules: options.rules,
|
|
683
706
|
lookups: options.lookups,
|
|
684
707
|
firstRowNumber: firstRow
|
|
@@ -741,19 +764,22 @@ async function previewSheet(options) {
|
|
|
741
764
|
try {
|
|
742
765
|
for await (const row of sheet.rows) {
|
|
743
766
|
rowCount++;
|
|
744
|
-
if (sample.length < limits.sampleRows) sample.push(row.map(
|
|
767
|
+
if (sample.length < limits.sampleRows) sample.push(row.map(core.cellText));
|
|
745
768
|
}
|
|
746
769
|
} catch (error) {
|
|
747
770
|
destroySource(options.stream);
|
|
748
771
|
throw error;
|
|
749
772
|
}
|
|
750
|
-
const
|
|
773
|
+
const arrayBound = core.arrayBoundFor(sheet.headers, options.config, null, options.lang);
|
|
774
|
+
const { columns } = core.deriveImportColumns(options.config, { lang: options.lang, maxArrayRows: arrayBound });
|
|
751
775
|
return {
|
|
752
776
|
headers: sheet.headers,
|
|
753
777
|
sample,
|
|
754
778
|
rowCount,
|
|
755
779
|
suggestion: core.suggestMapping(sheet.headers, columns, options.config?.entity ?? ""),
|
|
756
|
-
format: sheet.format
|
|
780
|
+
format: sheet.format,
|
|
781
|
+
...sheet.delimiter ? { delimiter: sheet.delimiter } : {},
|
|
782
|
+
arrayBound
|
|
757
783
|
};
|
|
758
784
|
}
|
|
759
785
|
var TEMPLATE_EXTENSION = { csv: "csv", xlsx: "xlsx" };
|
|
@@ -802,6 +828,10 @@ function sheetName(name) {
|
|
|
802
828
|
return (cleaned || "Import").slice(0, 31);
|
|
803
829
|
}
|
|
804
830
|
|
|
831
|
+
Object.defineProperty(exports, "sampleText", {
|
|
832
|
+
enumerable: true,
|
|
833
|
+
get: function () { return core.cellText; }
|
|
834
|
+
});
|
|
805
835
|
exports.DEFAULT_LIMITS = DEFAULT_LIMITS;
|
|
806
836
|
exports.ImportError = ImportError;
|
|
807
837
|
exports.TEMPLATE_EXTENSION = TEMPLATE_EXTENSION;
|
|
@@ -817,7 +847,6 @@ exports.previewSheet = previewSheet;
|
|
|
817
847
|
exports.readSheet = readSheet;
|
|
818
848
|
exports.resolveLimits = resolveLimits;
|
|
819
849
|
exports.runImport = runImport;
|
|
820
|
-
exports.sampleText = sampleText;
|
|
821
850
|
exports.toByteStream = toByteStream;
|
|
822
851
|
exports.toErrorBody = toErrorBody;
|
|
823
852
|
exports.writeTemplate = writeTemplate;
|