@deephaven/console 0.22.3-beta.18 → 0.22.3-beta.21
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/Console.js +9 -114
- package/dist/Console.js.map +1 -1
- package/dist/ConsoleInput.js +14 -90
- package/dist/ConsoleInput.js.map +1 -1
- package/dist/ConsoleMenu.js +6 -25
- package/dist/ConsoleMenu.js.map +1 -1
- package/dist/ConsolePropTypes.js.map +1 -1
- package/dist/ConsoleShortcuts.js +1 -1
- package/dist/ConsoleShortcuts.js.map +1 -1
- package/dist/ConsoleStatusBar.js +0 -16
- package/dist/ConsoleStatusBar.js.map +1 -1
- package/dist/HeapUsage.d.ts +1 -1
- package/dist/HeapUsage.d.ts.map +1 -1
- package/dist/HeapUsage.js +2 -18
- package/dist/HeapUsage.js.map +1 -1
- package/dist/StoragePropTypes.js.map +1 -1
- package/dist/command-history/CommandHistory.js +1 -49
- package/dist/command-history/CommandHistory.js.map +1 -1
- package/dist/command-history/CommandHistoryActions.js +0 -6
- package/dist/command-history/CommandHistoryActions.js.map +1 -1
- package/dist/command-history/CommandHistoryItem.d.ts +4 -4
- package/dist/command-history/CommandHistoryItem.d.ts.map +1 -1
- package/dist/command-history/CommandHistoryItem.js +3 -6
- package/dist/command-history/CommandHistoryItem.js.map +1 -1
- package/dist/command-history/CommandHistoryItemTooltip.js +3 -28
- package/dist/command-history/CommandHistoryItemTooltip.js.map +1 -1
- package/dist/command-history/CommandHistoryViewportUpdater.js +0 -3
- package/dist/command-history/CommandHistoryViewportUpdater.js.map +1 -1
- package/dist/command-history/index.js.map +1 -1
- package/dist/common/Code.js +2 -11
- package/dist/common/Code.js.map +1 -1
- package/dist/common/ConsoleConstants.js +0 -2
- package/dist/common/ConsoleConstants.js.map +1 -1
- package/dist/common/ConsoleUtils.js +4 -19
- package/dist/common/ConsoleUtils.js.map +1 -1
- package/dist/common/ObjectIcon.d.ts +1 -1
- package/dist/common/ObjectIcon.d.ts.map +1 -1
- package/dist/common/ObjectIcon.js +2 -8
- package/dist/common/ObjectIcon.js.map +1 -1
- package/dist/common/index.js.map +1 -1
- package/dist/console-history/ConsoleHistory.js +0 -8
- package/dist/console-history/ConsoleHistory.js.map +1 -1
- package/dist/console-history/ConsoleHistoryItem.js +2 -25
- package/dist/console-history/ConsoleHistoryItem.js.map +1 -1
- package/dist/console-history/ConsoleHistoryItemResult.d.ts +6 -6
- package/dist/console-history/ConsoleHistoryItemResult.d.ts.map +1 -1
- package/dist/console-history/ConsoleHistoryItemResult.js +2 -4
- package/dist/console-history/ConsoleHistoryItemResult.js.map +1 -1
- package/dist/console-history/ConsoleHistoryResultErrorMessage.js +0 -22
- package/dist/console-history/ConsoleHistoryResultErrorMessage.js.map +1 -1
- package/dist/console-history/ConsoleHistoryResultInProgress.js +0 -13
- package/dist/console-history/ConsoleHistoryResultInProgress.js.map +1 -1
- package/dist/console-history/index.js.map +1 -1
- package/dist/csv/CsvFormats.js +0 -9
- package/dist/csv/CsvFormats.js.map +1 -1
- package/dist/csv/CsvInputBar.js +18 -51
- package/dist/csv/CsvInputBar.js.map +1 -1
- package/dist/csv/CsvOverlay.js +1 -41
- package/dist/csv/CsvOverlay.js.map +1 -1
- package/dist/csv/CsvParser.js +10 -73
- package/dist/csv/CsvParser.js.map +1 -1
- package/dist/csv/CsvTypeParser.js +15 -85
- package/dist/csv/CsvTypeParser.js.map +1 -1
- package/dist/csv/NewTableColumnTypes.js +0 -9
- package/dist/csv/NewTableColumnTypes.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/log/LogLevel.js.map +1 -1
- package/dist/log/LogLevelMenuItem.js +0 -5
- package/dist/log/LogLevelMenuItem.js.map +1 -1
- package/dist/log/LogView.js +16 -106
- package/dist/log/LogView.js.map +1 -1
- package/dist/monaco/MonacoCompletionProvider.js +2 -14
- package/dist/monaco/MonacoCompletionProvider.js.map +1 -1
- package/dist/monaco/MonacoUtils.d.ts.map +1 -1
- package/dist/monaco/MonacoUtils.js +21 -49
- package/dist/monaco/MonacoUtils.js.map +1 -1
- package/dist/monaco/index.js.map +1 -1
- package/dist/monaco/lang/db.d.ts.map +1 -1
- package/dist/monaco/lang/db.js +22 -13
- package/dist/monaco/lang/db.js.map +1 -1
- package/dist/monaco/lang/groovy.d.ts.map +1 -1
- package/dist/monaco/lang/groovy.js +28 -15
- package/dist/monaco/lang/groovy.js.map +1 -1
- package/dist/monaco/lang/log.js +1 -0
- package/dist/monaco/lang/log.js.map +1 -1
- package/dist/monaco/lang/python.d.ts.map +1 -1
- package/dist/monaco/lang/python.js +30 -16
- package/dist/monaco/lang/python.js.map +1 -1
- package/dist/monaco/lang/scala.js +26 -13
- package/dist/monaco/lang/scala.js.map +1 -1
- package/dist/notebook/Editor.js +2 -21
- package/dist/notebook/Editor.js.map +1 -1
- package/dist/notebook/ScriptEditor.d.ts +1 -1
- package/dist/notebook/ScriptEditor.d.ts.map +1 -1
- package/dist/notebook/ScriptEditor.js +0 -57
- package/dist/notebook/ScriptEditor.js.map +1 -1
- package/dist/notebook/ScriptEditorUtils.js +1 -7
- package/dist/notebook/ScriptEditorUtils.js.map +1 -1
- package/package.json +11 -11
package/dist/csv/CsvParser.js
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
|
-
|
|
3
2
|
import Papa from 'papaparse';
|
|
4
3
|
import Log from '@deephaven/log';
|
|
5
4
|
import { assertNotNull, DbNameValidator } from '@deephaven/utils';
|
|
6
5
|
import CsvTypeParser from "./CsvTypeParser.js";
|
|
7
|
-
var log = Log.module('CsvParser');
|
|
8
|
-
// Want to consolidate to ~10 MB chunks
|
|
6
|
+
var log = Log.module('CsvParser');
|
|
9
7
|
|
|
8
|
+
// This is based on jszip streaming ~15 KB chunks to papa parse
|
|
9
|
+
// Want to consolidate to ~10 MB chunks
|
|
10
10
|
var ZIP_CONSOLIDATE_CHUNKS = 650;
|
|
11
|
-
|
|
12
11
|
/**
|
|
13
12
|
* Parser a CSV file in chunks and returns a table handle for each chunk.
|
|
14
13
|
*/
|
|
15
14
|
class CsvParser {
|
|
16
15
|
// Generates column names A-Z, AA-AZ, BA-BZ, etc...
|
|
16
|
+
|
|
17
17
|
static generateHeaderRecursive(n) {
|
|
18
18
|
var header = '';
|
|
19
19
|
var char = n;
|
|
20
|
-
|
|
21
20
|
if (n >= 26) {
|
|
22
21
|
header = header.concat(CsvParser.generateHeaderRecursive(Math.floor(n / 26) - 1));
|
|
23
22
|
char = n % 26;
|
|
24
23
|
}
|
|
25
|
-
|
|
26
24
|
return header.concat(String.fromCharCode(65 + char));
|
|
27
25
|
}
|
|
28
|
-
|
|
29
26
|
constructor(_ref) {
|
|
30
27
|
var {
|
|
31
28
|
onFileCompleted,
|
|
@@ -38,47 +35,26 @@ class CsvParser {
|
|
|
38
35
|
timeZone,
|
|
39
36
|
isZip
|
|
40
37
|
} = _ref;
|
|
41
|
-
|
|
42
38
|
_defineProperty(this, "onFileCompleted", void 0);
|
|
43
|
-
|
|
44
39
|
_defineProperty(this, "session", void 0);
|
|
45
|
-
|
|
46
40
|
_defineProperty(this, "file", void 0);
|
|
47
|
-
|
|
48
41
|
_defineProperty(this, "isZip", void 0);
|
|
49
|
-
|
|
50
42
|
_defineProperty(this, "type", void 0);
|
|
51
|
-
|
|
52
43
|
_defineProperty(this, "readHeaders", void 0);
|
|
53
|
-
|
|
54
44
|
_defineProperty(this, "timeZone", void 0);
|
|
55
|
-
|
|
56
45
|
_defineProperty(this, "onProgress", void 0);
|
|
57
|
-
|
|
58
46
|
_defineProperty(this, "onError", void 0);
|
|
59
|
-
|
|
60
47
|
_defineProperty(this, "tables", void 0);
|
|
61
|
-
|
|
62
48
|
_defineProperty(this, "headers", void 0);
|
|
63
|
-
|
|
64
49
|
_defineProperty(this, "types", void 0);
|
|
65
|
-
|
|
66
50
|
_defineProperty(this, "chunks", void 0);
|
|
67
|
-
|
|
68
51
|
_defineProperty(this, "totalChunks", void 0);
|
|
69
|
-
|
|
70
52
|
_defineProperty(this, "isComplete", void 0);
|
|
71
|
-
|
|
72
53
|
_defineProperty(this, "zipProgress", void 0);
|
|
73
|
-
|
|
74
54
|
_defineProperty(this, "consolidatedChunks", void 0);
|
|
75
|
-
|
|
76
55
|
_defineProperty(this, "numConsolidated", void 0);
|
|
77
|
-
|
|
78
56
|
_defineProperty(this, "isCancelled", void 0);
|
|
79
|
-
|
|
80
57
|
_defineProperty(this, "config", void 0);
|
|
81
|
-
|
|
82
58
|
this.onFileCompleted = onFileCompleted;
|
|
83
59
|
this.session = session;
|
|
84
60
|
this.file = file;
|
|
@@ -112,48 +88,39 @@ class CsvParser {
|
|
|
112
88
|
fastMode: false
|
|
113
89
|
};
|
|
114
90
|
}
|
|
115
|
-
|
|
116
91
|
cancel() {
|
|
117
92
|
this.isCancelled = true;
|
|
118
93
|
}
|
|
119
|
-
|
|
120
94
|
transpose(numColumns, array) {
|
|
121
95
|
var numRows = array.length;
|
|
122
96
|
var columns = new Array(numColumns).fill(null).map(() => new Array(numRows));
|
|
123
|
-
|
|
124
97
|
for (var r = 0; r < numRows; r += 1) {
|
|
125
98
|
var row = array[r];
|
|
126
|
-
|
|
127
99
|
if (row.length < numColumns) {
|
|
128
100
|
throw new Error("Insufficient columns. Expected ".concat(numColumns, " but found ").concat(row.length, "\n").concat(row));
|
|
129
101
|
}
|
|
130
|
-
|
|
131
102
|
for (var c = 0; c < numColumns; c += 1) {
|
|
132
103
|
var value = this.type.shouldTrim ? array[r][c].trim() : array[r][c];
|
|
133
104
|
columns[c][r] = this.nullCheck(value);
|
|
134
105
|
}
|
|
135
106
|
}
|
|
136
|
-
|
|
137
107
|
return columns;
|
|
138
108
|
}
|
|
139
|
-
|
|
140
109
|
nullCheck(value) {
|
|
141
110
|
return value === this.type.nullString ? '' : value;
|
|
142
111
|
}
|
|
143
|
-
|
|
144
112
|
parse() {
|
|
145
113
|
var handleParseDone = types => {
|
|
146
|
-
var toParse = this.isZip ? this.file.nodeStream(
|
|
114
|
+
var toParse = this.isZip ? this.file.nodeStream(
|
|
115
|
+
// JsZip types are incorrect, thus the funny casting
|
|
147
116
|
// Actual parameter is 'nodebuffer'
|
|
148
117
|
'nodebuffer', this.handleNodeUpdate) : this.file;
|
|
149
118
|
this.types = types;
|
|
150
119
|
Papa.parse(toParse, this.config);
|
|
151
120
|
};
|
|
152
|
-
|
|
153
121
|
var typeParser = new CsvTypeParser(handleParseDone, this.file, this.readHeaders, this.config, this.type.nullString, this.onProgress, this.onError, this.totalChunks, this.isZip, this.type.shouldTrim);
|
|
154
122
|
typeParser.parse();
|
|
155
123
|
}
|
|
156
|
-
|
|
157
124
|
handleChunk(result, parser) {
|
|
158
125
|
var {
|
|
159
126
|
readHeaders,
|
|
@@ -162,18 +129,15 @@ class CsvParser {
|
|
|
162
129
|
isZip,
|
|
163
130
|
tables
|
|
164
131
|
} = this;
|
|
165
|
-
|
|
166
132
|
if (this.isCancelled) {
|
|
167
133
|
log.debug2('CSV parser cancelled.');
|
|
168
134
|
parser.abort();
|
|
169
135
|
tables.forEach(t => t.close());
|
|
170
136
|
return;
|
|
171
137
|
}
|
|
172
|
-
|
|
173
138
|
var {
|
|
174
139
|
data
|
|
175
140
|
} = result;
|
|
176
|
-
|
|
177
141
|
if (!this.headers) {
|
|
178
142
|
if (readHeaders) {
|
|
179
143
|
this.headers = DbNameValidator.legalizeColumnNames(data[0]);
|
|
@@ -182,12 +146,9 @@ class CsvParser {
|
|
|
182
146
|
this.headers = CsvParser.generateHeaders(data[0].length);
|
|
183
147
|
}
|
|
184
148
|
}
|
|
185
|
-
|
|
186
149
|
var columns = [];
|
|
187
|
-
|
|
188
150
|
try {
|
|
189
151
|
columns = this.transpose(this.headers.length, data);
|
|
190
|
-
|
|
191
152
|
if (isZip) {
|
|
192
153
|
// Zip file chunks are tiny, so consolidate them to avoid create thousands of small tables
|
|
193
154
|
this.consolidateChunks(columns, parser);
|
|
@@ -200,7 +161,6 @@ class CsvParser {
|
|
|
200
161
|
onError(e);
|
|
201
162
|
}
|
|
202
163
|
}
|
|
203
|
-
|
|
204
164
|
consolidateChunks(columns, parser) {
|
|
205
165
|
if (!this.consolidatedChunks) {
|
|
206
166
|
this.consolidatedChunks = columns.slice();
|
|
@@ -209,17 +169,13 @@ class CsvParser {
|
|
|
209
169
|
this.consolidatedChunks[i] = this.consolidatedChunks[i].concat(columns[i]);
|
|
210
170
|
}
|
|
211
171
|
}
|
|
212
|
-
|
|
213
172
|
this.numConsolidated += 1;
|
|
214
|
-
|
|
215
173
|
if (this.numConsolidated >= ZIP_CONSOLIDATE_CHUNKS || this.isComplete) {
|
|
216
174
|
this.uploadConsolidatedChunks(parser);
|
|
217
175
|
}
|
|
218
176
|
}
|
|
219
|
-
|
|
220
177
|
uploadConsolidatedChunks(parser) {
|
|
221
178
|
var _this$consolidatedChu;
|
|
222
|
-
|
|
223
179
|
var {
|
|
224
180
|
handleCreateTable
|
|
225
181
|
} = this;
|
|
@@ -231,7 +187,6 @@ class CsvParser {
|
|
|
231
187
|
assertNotNull(toUpload);
|
|
232
188
|
handleCreateTable(index, toUpload, parser);
|
|
233
189
|
}
|
|
234
|
-
|
|
235
190
|
handleCreateTable(index, columns, parser) {
|
|
236
191
|
var {
|
|
237
192
|
session,
|
|
@@ -242,42 +197,33 @@ class CsvParser {
|
|
|
242
197
|
onProgress,
|
|
243
198
|
onError
|
|
244
199
|
} = this;
|
|
245
|
-
|
|
246
200
|
if (parser) {
|
|
247
201
|
parser.pause();
|
|
248
202
|
}
|
|
249
|
-
|
|
250
203
|
assertNotNull(this.headers);
|
|
251
204
|
assertNotNull(types);
|
|
252
205
|
session.newTable(this.headers, types, columns, this.timeZone).then(table => {
|
|
253
206
|
if (this.isCancelled) {
|
|
254
207
|
log.debug2('CSV parser cancelled.');
|
|
255
|
-
|
|
256
208
|
if (parser) {
|
|
257
209
|
parser.abort();
|
|
258
210
|
}
|
|
259
|
-
|
|
260
211
|
tables.forEach(t => t.close());
|
|
261
212
|
return;
|
|
262
213
|
}
|
|
263
|
-
|
|
264
214
|
if (parser) {
|
|
265
215
|
parser.resume();
|
|
266
216
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
217
|
+
tables[index] = table;
|
|
218
|
+
// This accounts for 50% of parsing plus 50% already done by the type parser
|
|
270
219
|
var progress = 0;
|
|
271
|
-
|
|
272
220
|
if (totalChunks > 0) {
|
|
273
221
|
progress = Math.round(tables.length / totalChunks * 50) + 50;
|
|
274
222
|
} else {
|
|
275
223
|
progress = Math.round(50 + this.zipProgress / 2);
|
|
276
224
|
}
|
|
277
|
-
|
|
278
225
|
log.debug2("CSV parser progress ".concat(progress));
|
|
279
226
|
onProgress(progress);
|
|
280
|
-
|
|
281
227
|
if (this.isComplete && tables.length === this.chunks) {
|
|
282
228
|
log.debug2('CSV parser complete.');
|
|
283
229
|
onFileCompleted(tables);
|
|
@@ -286,44 +232,35 @@ class CsvParser {
|
|
|
286
232
|
if (!this.isComplete && parser) {
|
|
287
233
|
parser.abort();
|
|
288
234
|
}
|
|
289
|
-
|
|
290
235
|
onError(e);
|
|
291
236
|
});
|
|
292
237
|
}
|
|
293
|
-
|
|
294
238
|
handleComplete(results) {
|
|
295
239
|
// results is undefined for a succesful parse, but has meta data for an abort
|
|
296
240
|
if (results == null || results.meta.aborted == null) {
|
|
297
|
-
this.isComplete = true;
|
|
298
|
-
|
|
241
|
+
this.isComplete = true;
|
|
242
|
+
// Check if there are any consolidated chunks left over from a zip file
|
|
299
243
|
if (this.consolidatedChunks) {
|
|
300
244
|
this.uploadConsolidatedChunks(null);
|
|
301
245
|
}
|
|
302
246
|
}
|
|
303
247
|
}
|
|
304
|
-
|
|
305
248
|
handleError(error) {
|
|
306
249
|
var {
|
|
307
250
|
onError
|
|
308
251
|
} = this;
|
|
309
252
|
onError(error);
|
|
310
253
|
}
|
|
311
|
-
|
|
312
254
|
handleNodeUpdate(metadata) {
|
|
313
255
|
this.zipProgress = metadata.percent;
|
|
314
256
|
}
|
|
315
|
-
|
|
316
257
|
}
|
|
317
|
-
|
|
318
258
|
_defineProperty(CsvParser, "generateHeaders", numColumns => {
|
|
319
259
|
var headers = [];
|
|
320
|
-
|
|
321
260
|
for (var i = 0; i < numColumns; i += 1) {
|
|
322
261
|
headers.push(CsvParser.generateHeaderRecursive(i));
|
|
323
262
|
}
|
|
324
|
-
|
|
325
263
|
return headers;
|
|
326
264
|
});
|
|
327
|
-
|
|
328
265
|
export default CsvParser;
|
|
329
266
|
//# sourceMappingURL=CsvParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CsvParser.js","names":["Papa","Log","assertNotNull","DbNameValidator","CsvTypeParser","log","module","ZIP_CONSOLIDATE_CHUNKS","CsvParser","generateHeaderRecursive","n","header","char","concat","Math","floor","String","fromCharCode","constructor","onFileCompleted","session","file","type","readHeaders","onProgress","onError","timeZone","isZip","tables","chunks","totalChunks","ceil","size","LocalChunkSize","isComplete","zipProgress","numConsolidated","isCancelled","handleChunk","bind","handleError","handleComplete","handleNodeUpdate","handleCreateTable","config","delimiter","newline","escapeChar","dynamicTyping","error","skipEmptyLines","chunk","complete","fastMode","cancel","transpose","numColumns","array","numRows","length","columns","Array","fill","map","r","row","Error","c","value","shouldTrim","trim","nullCheck","nullString","parse","handleParseDone","types","toParse","nodeStream","typeParser","result","parser","debug2","abort","forEach","t","close","data","headers","legalizeColumnNames","slice","generateHeaders","consolidateChunks","index","e","consolidatedChunks","i","uploadConsolidatedChunks","toUpload","undefined","pause","newTable","then","table","resume","progress","round","catch","results","meta","aborted","metadata","percent","push"],"sources":["../../src/csv/CsvParser.ts"],"sourcesContent":["import Papa, { ParseLocalConfig, Parser, ParseResult } from 'papaparse';\nimport Log from '@deephaven/log';\nimport { assertNotNull, DbNameValidator } from '@deephaven/utils';\nimport { IdeSession, Table } from '@deephaven/jsapi-shim';\nimport type { JSZipObject } from 'jszip';\nimport CsvTypeParser from './CsvTypeParser';\nimport { CsvTypes } from './CsvFormats';\n\nconst log = Log.module('CsvParser');\n\n// This is based on jszip streaming ~15 KB chunks to papa parse\n// Want to consolidate to ~10 MB chunks\nconst ZIP_CONSOLIDATE_CHUNKS = 650;\n\ninterface CsvParserConstructor {\n onFileCompleted: (tables: Table[]) => void;\n session: IdeSession;\n file: Blob | JSZipObject;\n type: CsvTypes;\n readHeaders: boolean;\n onProgress: (progressValue: number) => boolean;\n onError: (e: unknown) => void;\n timeZone: string;\n isZip: boolean;\n}\n\n/**\n * Parser a CSV file in chunks and returns a table handle for each chunk.\n */\nclass CsvParser {\n // Generates column names A-Z, AA-AZ, BA-BZ, etc...\n static generateHeaders = (numColumns: number): string[] => {\n const headers = [];\n for (let i = 0; i < numColumns; i += 1) {\n headers.push(CsvParser.generateHeaderRecursive(i));\n }\n return headers;\n };\n\n static generateHeaderRecursive(n: number): string {\n let header = '';\n let char = n;\n if (n >= 26) {\n header = header.concat(\n CsvParser.generateHeaderRecursive(Math.floor(n / 26) - 1)\n );\n char = n % 26;\n }\n return header.concat(String.fromCharCode(65 + char));\n }\n\n constructor({\n onFileCompleted,\n session,\n file,\n type,\n readHeaders = true,\n onProgress,\n onError,\n timeZone,\n isZip,\n }: CsvParserConstructor) {\n this.onFileCompleted = onFileCompleted;\n this.session = session;\n this.file = file;\n this.isZip = isZip;\n this.type = type;\n this.readHeaders = readHeaders;\n this.timeZone = timeZone;\n this.onProgress = onProgress;\n this.onError = onError;\n this.tables = [];\n this.chunks = 0;\n this.totalChunks = isZip\n ? 0\n : Math.ceil((file as Blob).size / Papa.LocalChunkSize);\n this.isComplete = false;\n this.zipProgress = 0;\n this.numConsolidated = 0;\n this.isCancelled = false;\n\n this.handleChunk = this.handleChunk.bind(this);\n this.handleError = this.handleError.bind(this);\n this.handleComplete = this.handleComplete.bind(this);\n this.handleNodeUpdate = this.handleNodeUpdate.bind(this);\n this.handleCreateTable = this.handleCreateTable.bind(this);\n\n this.config = {\n delimiter: type.delimiter,\n newline: type.newline as '\\r\\n' | '\\n' | '\\r' | undefined,\n escapeChar: type.escapeChar,\n dynamicTyping: false,\n error: this.handleError,\n skipEmptyLines: type.skipEmptyLines,\n chunk: this.handleChunk,\n complete: this.handleComplete,\n fastMode: false,\n };\n }\n\n onFileCompleted: (tables: Table[]) => void;\n\n session: IdeSession;\n\n file: Blob | JSZipObject;\n\n isZip: boolean;\n\n type: CsvTypes;\n\n readHeaders: boolean;\n\n timeZone: string;\n\n onProgress: (progressValue: number) => boolean;\n\n onError: (e: unknown) => void;\n\n tables: Table[];\n\n headers?: string[];\n\n types?: string[];\n\n chunks: number;\n\n totalChunks: number;\n\n isComplete: boolean;\n\n zipProgress: number;\n\n consolidatedChunks?: string[][];\n\n numConsolidated: number;\n\n isCancelled: boolean;\n\n config: ParseLocalConfig<unknown, Blob | NodeJS.ReadableStream>;\n\n cancel(): void {\n this.isCancelled = true;\n }\n\n transpose(numColumns: number, array: string[][]): string[][] {\n const numRows = array.length;\n const columns = new Array(numColumns)\n .fill(null)\n .map(() => new Array(numRows));\n for (let r = 0; r < numRows; r += 1) {\n const row = array[r];\n if (row.length < numColumns) {\n throw new Error(\n `Insufficient columns. Expected ${numColumns} but found ${row.length}\\n${row}`\n );\n }\n for (let c = 0; c < numColumns; c += 1) {\n const value = this.type.shouldTrim ? array[r][c].trim() : array[r][c];\n columns[c][r] = this.nullCheck(value);\n }\n }\n return columns as string[][];\n }\n\n nullCheck(value: string): string {\n return value === this.type.nullString ? '' : value;\n }\n\n parse(): void {\n const handleParseDone = (types: string[]) => {\n const toParse = this.isZip\n ? (this.file as JSZipObject).nodeStream(\n // JsZip types are incorrect, thus the funny casting\n // Actual parameter is 'nodebuffer'\n 'nodebuffer' as 'nodestream',\n this.handleNodeUpdate\n )\n : (this.file as Blob);\n this.types = types;\n Papa.parse(toParse, this.config);\n };\n const typeParser = new CsvTypeParser(\n handleParseDone,\n this.file,\n this.readHeaders,\n this.config,\n this.type.nullString,\n this.onProgress,\n this.onError,\n this.totalChunks,\n this.isZip,\n this.type.shouldTrim\n );\n typeParser.parse();\n }\n\n handleChunk(result: ParseResult<string[]>, parser: Parser): void {\n const { readHeaders, onError, handleCreateTable, isZip, tables } = this;\n if (this.isCancelled) {\n log.debug2('CSV parser cancelled.');\n parser.abort();\n tables.forEach(t => t.close());\n return;\n }\n let { data } = result;\n if (!this.headers) {\n if (readHeaders) {\n this.headers = DbNameValidator.legalizeColumnNames(data[0]);\n data = data.slice(1);\n } else {\n this.headers = CsvParser.generateHeaders(data[0].length);\n }\n }\n\n let columns: string[][] = [];\n try {\n columns = this.transpose(this.headers.length, data);\n if (isZip) {\n // Zip file chunks are tiny, so consolidate them to avoid create thousands of small tables\n this.consolidateChunks(columns, parser);\n } else {\n const index = this.chunks;\n this.chunks += 1;\n handleCreateTable(index, columns, parser);\n }\n } catch (e: unknown) {\n onError(e);\n }\n }\n\n consolidateChunks(columns: string[][], parser: Parser): void {\n if (!this.consolidatedChunks) {\n this.consolidatedChunks = columns.slice();\n } else {\n for (let i = 0; i < columns.length; i += 1) {\n this.consolidatedChunks[i] = this.consolidatedChunks[i].concat(\n columns[i]\n );\n }\n }\n this.numConsolidated += 1;\n if (this.numConsolidated >= ZIP_CONSOLIDATE_CHUNKS || this.isComplete) {\n this.uploadConsolidatedChunks(parser);\n }\n }\n\n uploadConsolidatedChunks(parser: Parser | null): void {\n const { handleCreateTable } = this;\n const index = this.chunks;\n this.chunks += 1;\n const toUpload = this.consolidatedChunks?.slice();\n this.consolidatedChunks = undefined;\n this.numConsolidated = 0;\n assertNotNull(toUpload);\n handleCreateTable(index, toUpload, parser);\n }\n\n handleCreateTable(\n index: number,\n columns: string[][],\n parser: Parser | null\n ): void {\n const {\n session,\n tables,\n onFileCompleted,\n totalChunks,\n types,\n onProgress,\n onError,\n } = this;\n if (parser) {\n parser.pause();\n }\n assertNotNull(this.headers);\n assertNotNull(types);\n session\n .newTable(this.headers, types, columns, this.timeZone)\n .then(table => {\n if (this.isCancelled) {\n log.debug2('CSV parser cancelled.');\n if (parser) {\n parser.abort();\n }\n tables.forEach(t => t.close());\n return;\n }\n if (parser) {\n parser.resume();\n }\n tables[index] = table;\n // This accounts for 50% of parsing plus 50% already done by the type parser\n let progress = 0;\n if (totalChunks > 0) {\n progress = Math.round((tables.length / totalChunks) * 50) + 50;\n } else {\n progress = Math.round(50 + this.zipProgress / 2);\n }\n log.debug2(`CSV parser progress ${progress}`);\n onProgress(progress);\n if (this.isComplete && tables.length === this.chunks) {\n log.debug2('CSV parser complete.');\n onFileCompleted(tables);\n }\n })\n .catch(e => {\n if (!this.isComplete && parser) {\n parser.abort();\n }\n onError(e);\n });\n }\n\n handleComplete(results: ParseResult<unknown>): void {\n // results is undefined for a succesful parse, but has meta data for an abort\n if (results == null || results.meta.aborted == null) {\n this.isComplete = true;\n // Check if there are any consolidated chunks left over from a zip file\n if (this.consolidatedChunks) {\n this.uploadConsolidatedChunks(null);\n }\n }\n }\n\n handleError(error: unknown): void {\n const { onError } = this;\n onError(error);\n }\n\n handleNodeUpdate(metadata: { percent: number }): void {\n this.zipProgress = metadata.percent;\n }\n}\n\nexport default CsvParser;\n"],"mappings":";;AAAA,OAAOA,IAAP,MAA4D,WAA5D;AACA,OAAOC,GAAP,MAAgB,gBAAhB;AACA,SAASC,aAAT,EAAwBC,eAAxB,QAA+C,kBAA/C;OAGOC,a;AAGP,IAAMC,GAAG,GAAGJ,GAAG,CAACK,MAAJ,CAAW,WAAX,CAAZ,C,CAEA;AACA;;AACA,IAAMC,sBAAsB,GAAG,GAA/B;;AAcA;AACA;AACA;AACA,MAAMC,SAAN,CAAgB;EACd;EAS8B,OAAvBC,uBAAuB,CAACC,CAAD,EAAoB;IAChD,IAAIC,MAAM,GAAG,EAAb;IACA,IAAIC,IAAI,GAAGF,CAAX;;IACA,IAAIA,CAAC,IAAI,EAAT,EAAa;MACXC,MAAM,GAAGA,MAAM,CAACE,MAAP,CACPL,SAAS,CAACC,uBAAV,CAAkCK,IAAI,CAACC,KAAL,CAAWL,CAAC,GAAG,EAAf,IAAqB,CAAvD,CADO,CAAT;MAGAE,IAAI,GAAGF,CAAC,GAAG,EAAX;IACD;;IACD,OAAOC,MAAM,CAACE,MAAP,CAAcG,MAAM,CAACC,YAAP,CAAoB,KAAKL,IAAzB,CAAd,CAAP;EACD;;EAEDM,WAAW,OAUc;IAAA,IAVb;MACVC,eADU;MAEVC,OAFU;MAGVC,IAHU;MAIVC,IAJU;MAKVC,WAAW,GAAG,IALJ;MAMVC,UANU;MAOVC,OAPU;MAQVC,QARU;MASVC;IATU,CAUa;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IAAA;;IACvB,KAAKR,eAAL,GAAuBA,eAAvB;IACA,KAAKC,OAAL,GAAeA,OAAf;IACA,KAAKC,IAAL,GAAYA,IAAZ;IACA,KAAKM,KAAL,GAAaA,KAAb;IACA,KAAKL,IAAL,GAAYA,IAAZ;IACA,KAAKC,WAAL,GAAmBA,WAAnB;IACA,KAAKG,QAAL,GAAgBA,QAAhB;IACA,KAAKF,UAAL,GAAkBA,UAAlB;IACA,KAAKC,OAAL,GAAeA,OAAf;IACA,KAAKG,MAAL,GAAc,EAAd;IACA,KAAKC,MAAL,GAAc,CAAd;IACA,KAAKC,WAAL,GAAmBH,KAAK,GACpB,CADoB,GAEpBb,IAAI,CAACiB,IAAL,CAAWV,IAAD,CAAeW,IAAf,GAAsBhC,IAAI,CAACiC,cAArC,CAFJ;IAGA,KAAKC,UAAL,GAAkB,KAAlB;IACA,KAAKC,WAAL,GAAmB,CAAnB;IACA,KAAKC,eAAL,GAAuB,CAAvB;IACA,KAAKC,WAAL,GAAmB,KAAnB;IAEA,KAAKC,WAAL,GAAmB,KAAKA,WAAL,CAAiBC,IAAjB,CAAsB,IAAtB,CAAnB;IACA,KAAKC,WAAL,GAAmB,KAAKA,WAAL,CAAiBD,IAAjB,CAAsB,IAAtB,CAAnB;IACA,KAAKE,cAAL,GAAsB,KAAKA,cAAL,CAAoBF,IAApB,CAAyB,IAAzB,CAAtB;IACA,KAAKG,gBAAL,GAAwB,KAAKA,gBAAL,CAAsBH,IAAtB,CAA2B,IAA3B,CAAxB;IACA,KAAKI,iBAAL,GAAyB,KAAKA,iBAAL,CAAuBJ,IAAvB,CAA4B,IAA5B,CAAzB;IAEA,KAAKK,MAAL,GAAc;MACZC,SAAS,EAAEvB,IAAI,CAACuB,SADJ;MAEZC,OAAO,EAAExB,IAAI,CAACwB,OAFF;MAGZC,UAAU,EAAEzB,IAAI,CAACyB,UAHL;MAIZC,aAAa,EAAE,KAJH;MAKZC,KAAK,EAAE,KAAKT,WALA;MAMZU,cAAc,EAAE5B,IAAI,CAAC4B,cANT;MAOZC,KAAK,EAAE,KAAKb,WAPA;MAQZc,QAAQ,EAAE,KAAKX,cARH;MASZY,QAAQ,EAAE;IATE,CAAd;EAWD;;EA0CDC,MAAM,GAAS;IACb,KAAKjB,WAAL,GAAmB,IAAnB;EACD;;EAEDkB,SAAS,CAACC,UAAD,EAAqBC,KAArB,EAAoD;IAC3D,IAAMC,OAAO,GAAGD,KAAK,CAACE,MAAtB;IACA,IAAMC,OAAO,GAAG,IAAIC,KAAJ,CAAUL,UAAV,EACbM,IADa,CACR,IADQ,EAEbC,GAFa,CAET,MAAM,IAAIF,KAAJ,CAAUH,OAAV,CAFG,CAAhB;;IAGA,KAAK,IAAIM,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGN,OAApB,EAA6BM,CAAC,IAAI,CAAlC,EAAqC;MACnC,IAAMC,GAAG,GAAGR,KAAK,CAACO,CAAD,CAAjB;;MACA,IAAIC,GAAG,CAACN,MAAJ,GAAaH,UAAjB,EAA6B;QAC3B,MAAM,IAAIU,KAAJ,0CAC8BV,UAD9B,wBACsDS,GAAG,CAACN,MAD1D,eACqEM,GADrE,EAAN;MAGD;;MACD,KAAK,IAAIE,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGX,UAApB,EAAgCW,CAAC,IAAI,CAArC,EAAwC;QACtC,IAAMC,KAAK,GAAG,KAAK9C,IAAL,CAAU+C,UAAV,GAAuBZ,KAAK,CAACO,CAAD,CAAL,CAASG,CAAT,EAAYG,IAAZ,EAAvB,GAA4Cb,KAAK,CAACO,CAAD,CAAL,CAASG,CAAT,CAA1D;QACAP,OAAO,CAACO,CAAD,CAAP,CAAWH,CAAX,IAAgB,KAAKO,SAAL,CAAeH,KAAf,CAAhB;MACD;IACF;;IACD,OAAOR,OAAP;EACD;;EAEDW,SAAS,CAACH,KAAD,EAAwB;IAC/B,OAAOA,KAAK,KAAK,KAAK9C,IAAL,CAAUkD,UAApB,GAAiC,EAAjC,GAAsCJ,KAA7C;EACD;;EAEDK,KAAK,GAAS;IACZ,IAAMC,eAAe,GAAIC,KAAD,IAAqB;MAC3C,IAAMC,OAAO,GAAG,KAAKjD,KAAL,GACX,KAAKN,IAAN,CAA2BwD,UAA3B,EACE;MACA;MACA,YAHF,EAIE,KAAKnC,gBAJP,CADY,GAOX,KAAKrB,IAPV;MAQA,KAAKsD,KAAL,GAAaA,KAAb;MACA3E,IAAI,CAACyE,KAAL,CAAWG,OAAX,EAAoB,KAAKhC,MAAzB;IACD,CAXD;;IAYA,IAAMkC,UAAU,GAAG,IAAI1E,aAAJ,CACjBsE,eADiB,EAEjB,KAAKrD,IAFY,EAGjB,KAAKE,WAHY,EAIjB,KAAKqB,MAJY,EAKjB,KAAKtB,IAAL,CAAUkD,UALO,EAMjB,KAAKhD,UANY,EAOjB,KAAKC,OAPY,EAQjB,KAAKK,WARY,EASjB,KAAKH,KATY,EAUjB,KAAKL,IAAL,CAAU+C,UAVO,CAAnB;IAYAS,UAAU,CAACL,KAAX;EACD;;EAEDnC,WAAW,CAACyC,MAAD,EAAgCC,MAAhC,EAAsD;IAC/D,IAAM;MAAEzD,WAAF;MAAeE,OAAf;MAAwBkB,iBAAxB;MAA2ChB,KAA3C;MAAkDC;IAAlD,IAA6D,IAAnE;;IACA,IAAI,KAAKS,WAAT,EAAsB;MACpBhC,GAAG,CAAC4E,MAAJ,CAAW,uBAAX;MACAD,MAAM,CAACE,KAAP;MACAtD,MAAM,CAACuD,OAAP,CAAeC,CAAC,IAAIA,CAAC,CAACC,KAAF,EAApB;MACA;IACD;;IACD,IAAI;MAAEC;IAAF,IAAWP,MAAf;;IACA,IAAI,CAAC,KAAKQ,OAAV,EAAmB;MACjB,IAAIhE,WAAJ,EAAiB;QACf,KAAKgE,OAAL,GAAepF,eAAe,CAACqF,mBAAhB,CAAoCF,IAAI,CAAC,CAAD,CAAxC,CAAf;QACAA,IAAI,GAAGA,IAAI,CAACG,KAAL,CAAW,CAAX,CAAP;MACD,CAHD,MAGO;QACL,KAAKF,OAAL,GAAe/E,SAAS,CAACkF,eAAV,CAA0BJ,IAAI,CAAC,CAAD,CAAJ,CAAQ3B,MAAlC,CAAf;MACD;IACF;;IAED,IAAIC,OAAmB,GAAG,EAA1B;;IACA,IAAI;MACFA,OAAO,GAAG,KAAKL,SAAL,CAAe,KAAKgC,OAAL,CAAa5B,MAA5B,EAAoC2B,IAApC,CAAV;;MACA,IAAI3D,KAAJ,EAAW;QACT;QACA,KAAKgE,iBAAL,CAAuB/B,OAAvB,EAAgCoB,MAAhC;MACD,CAHD,MAGO;QACL,IAAMY,KAAK,GAAG,KAAK/D,MAAnB;QACA,KAAKA,MAAL,IAAe,CAAf;QACAc,iBAAiB,CAACiD,KAAD,EAAQhC,OAAR,EAAiBoB,MAAjB,CAAjB;MACD;IACF,CAVD,CAUE,OAAOa,CAAP,EAAmB;MACnBpE,OAAO,CAACoE,CAAD,CAAP;IACD;EACF;;EAEDF,iBAAiB,CAAC/B,OAAD,EAAsBoB,MAAtB,EAA4C;IAC3D,IAAI,CAAC,KAAKc,kBAAV,EAA8B;MAC5B,KAAKA,kBAAL,GAA0BlC,OAAO,CAAC6B,KAAR,EAA1B;IACD,CAFD,MAEO;MACL,KAAK,IAAIM,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGnC,OAAO,CAACD,MAA5B,EAAoCoC,CAAC,IAAI,CAAzC,EAA4C;QAC1C,KAAKD,kBAAL,CAAwBC,CAAxB,IAA6B,KAAKD,kBAAL,CAAwBC,CAAxB,EAA2BlF,MAA3B,CAC3B+C,OAAO,CAACmC,CAAD,CADoB,CAA7B;MAGD;IACF;;IACD,KAAK3D,eAAL,IAAwB,CAAxB;;IACA,IAAI,KAAKA,eAAL,IAAwB7B,sBAAxB,IAAkD,KAAK2B,UAA3D,EAAuE;MACrE,KAAK8D,wBAAL,CAA8BhB,MAA9B;IACD;EACF;;EAEDgB,wBAAwB,CAAChB,MAAD,EAA8B;IAAA;;IACpD,IAAM;MAAErC;IAAF,IAAwB,IAA9B;IACA,IAAMiD,KAAK,GAAG,KAAK/D,MAAnB;IACA,KAAKA,MAAL,IAAe,CAAf;IACA,IAAMoE,QAAQ,4BAAG,KAAKH,kBAAR,0DAAG,sBAAyBL,KAAzB,EAAjB;IACA,KAAKK,kBAAL,GAA0BI,SAA1B;IACA,KAAK9D,eAAL,GAAuB,CAAvB;IACAlC,aAAa,CAAC+F,QAAD,CAAb;IACAtD,iBAAiB,CAACiD,KAAD,EAAQK,QAAR,EAAkBjB,MAAlB,CAAjB;EACD;;EAEDrC,iBAAiB,CACfiD,KADe,EAEfhC,OAFe,EAGfoB,MAHe,EAIT;IACN,IAAM;MACJ5D,OADI;MAEJQ,MAFI;MAGJT,eAHI;MAIJW,WAJI;MAKJ6C,KALI;MAMJnD,UANI;MAOJC;IAPI,IAQF,IARJ;;IASA,IAAIuD,MAAJ,EAAY;MACVA,MAAM,CAACmB,KAAP;IACD;;IACDjG,aAAa,CAAC,KAAKqF,OAAN,CAAb;IACArF,aAAa,CAACyE,KAAD,CAAb;IACAvD,OAAO,CACJgF,QADH,CACY,KAAKb,OADjB,EAC0BZ,KAD1B,EACiCf,OADjC,EAC0C,KAAKlC,QAD/C,EAEG2E,IAFH,CAEQC,KAAK,IAAI;MACb,IAAI,KAAKjE,WAAT,EAAsB;QACpBhC,GAAG,CAAC4E,MAAJ,CAAW,uBAAX;;QACA,IAAID,MAAJ,EAAY;UACVA,MAAM,CAACE,KAAP;QACD;;QACDtD,MAAM,CAACuD,OAAP,CAAeC,CAAC,IAAIA,CAAC,CAACC,KAAF,EAApB;QACA;MACD;;MACD,IAAIL,MAAJ,EAAY;QACVA,MAAM,CAACuB,MAAP;MACD;;MACD3E,MAAM,CAACgE,KAAD,CAAN,GAAgBU,KAAhB,CAZa,CAab;;MACA,IAAIE,QAAQ,GAAG,CAAf;;MACA,IAAI1E,WAAW,GAAG,CAAlB,EAAqB;QACnB0E,QAAQ,GAAG1F,IAAI,CAAC2F,KAAL,CAAY7E,MAAM,CAAC+B,MAAP,GAAgB7B,WAAjB,GAAgC,EAA3C,IAAiD,EAA5D;MACD,CAFD,MAEO;QACL0E,QAAQ,GAAG1F,IAAI,CAAC2F,KAAL,CAAW,KAAK,KAAKtE,WAAL,GAAmB,CAAnC,CAAX;MACD;;MACD9B,GAAG,CAAC4E,MAAJ,+BAAkCuB,QAAlC;MACAhF,UAAU,CAACgF,QAAD,CAAV;;MACA,IAAI,KAAKtE,UAAL,IAAmBN,MAAM,CAAC+B,MAAP,KAAkB,KAAK9B,MAA9C,EAAsD;QACpDxB,GAAG,CAAC4E,MAAJ,CAAW,sBAAX;QACA9D,eAAe,CAACS,MAAD,CAAf;MACD;IACF,CA5BH,EA6BG8E,KA7BH,CA6BSb,CAAC,IAAI;MACV,IAAI,CAAC,KAAK3D,UAAN,IAAoB8C,MAAxB,EAAgC;QAC9BA,MAAM,CAACE,KAAP;MACD;;MACDzD,OAAO,CAACoE,CAAD,CAAP;IACD,CAlCH;EAmCD;;EAEDpD,cAAc,CAACkE,OAAD,EAAsC;IAClD;IACA,IAAIA,OAAO,IAAI,IAAX,IAAmBA,OAAO,CAACC,IAAR,CAAaC,OAAb,IAAwB,IAA/C,EAAqD;MACnD,KAAK3E,UAAL,GAAkB,IAAlB,CADmD,CAEnD;;MACA,IAAI,KAAK4D,kBAAT,EAA6B;QAC3B,KAAKE,wBAAL,CAA8B,IAA9B;MACD;IACF;EACF;;EAEDxD,WAAW,CAACS,KAAD,EAAuB;IAChC,IAAM;MAAExB;IAAF,IAAc,IAApB;IACAA,OAAO,CAACwB,KAAD,CAAP;EACD;;EAEDP,gBAAgB,CAACoE,QAAD,EAAsC;IACpD,KAAK3E,WAAL,GAAmB2E,QAAQ,CAACC,OAA5B;EACD;;AA9Sa;;gBAAVvG,S,qBAEsBgD,UAAD,IAAkC;EACzD,IAAM+B,OAAO,GAAG,EAAhB;;EACA,KAAK,IAAIQ,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGvC,UAApB,EAAgCuC,CAAC,IAAI,CAArC,EAAwC;IACtCR,OAAO,CAACyB,IAAR,CAAaxG,SAAS,CAACC,uBAAV,CAAkCsF,CAAlC,CAAb;EACD;;EACD,OAAOR,OAAP;AACD,C;;AAySH,eAAe/E,SAAf"}
|
|
1
|
+
{"version":3,"file":"CsvParser.js","names":["Papa","Log","assertNotNull","DbNameValidator","CsvTypeParser","log","module","ZIP_CONSOLIDATE_CHUNKS","CsvParser","generateHeaderRecursive","n","header","char","concat","Math","floor","String","fromCharCode","constructor","onFileCompleted","session","file","type","readHeaders","onProgress","onError","timeZone","isZip","tables","chunks","totalChunks","ceil","size","LocalChunkSize","isComplete","zipProgress","numConsolidated","isCancelled","handleChunk","bind","handleError","handleComplete","handleNodeUpdate","handleCreateTable","config","delimiter","newline","escapeChar","dynamicTyping","error","skipEmptyLines","chunk","complete","fastMode","cancel","transpose","numColumns","array","numRows","length","columns","Array","fill","map","r","row","Error","c","value","shouldTrim","trim","nullCheck","nullString","parse","handleParseDone","types","toParse","nodeStream","typeParser","result","parser","debug2","abort","forEach","t","close","data","headers","legalizeColumnNames","slice","generateHeaders","consolidateChunks","index","e","consolidatedChunks","i","uploadConsolidatedChunks","toUpload","undefined","pause","newTable","then","table","resume","progress","round","catch","results","meta","aborted","metadata","percent","push"],"sources":["../../src/csv/CsvParser.ts"],"sourcesContent":["import Papa, { ParseLocalConfig, Parser, ParseResult } from 'papaparse';\nimport Log from '@deephaven/log';\nimport { assertNotNull, DbNameValidator } from '@deephaven/utils';\nimport { IdeSession, Table } from '@deephaven/jsapi-shim';\nimport type { JSZipObject } from 'jszip';\nimport CsvTypeParser from './CsvTypeParser';\nimport { CsvTypes } from './CsvFormats';\n\nconst log = Log.module('CsvParser');\n\n// This is based on jszip streaming ~15 KB chunks to papa parse\n// Want to consolidate to ~10 MB chunks\nconst ZIP_CONSOLIDATE_CHUNKS = 650;\n\ninterface CsvParserConstructor {\n onFileCompleted: (tables: Table[]) => void;\n session: IdeSession;\n file: Blob | JSZipObject;\n type: CsvTypes;\n readHeaders: boolean;\n onProgress: (progressValue: number) => boolean;\n onError: (e: unknown) => void;\n timeZone: string;\n isZip: boolean;\n}\n\n/**\n * Parser a CSV file in chunks and returns a table handle for each chunk.\n */\nclass CsvParser {\n // Generates column names A-Z, AA-AZ, BA-BZ, etc...\n static generateHeaders = (numColumns: number): string[] => {\n const headers = [];\n for (let i = 0; i < numColumns; i += 1) {\n headers.push(CsvParser.generateHeaderRecursive(i));\n }\n return headers;\n };\n\n static generateHeaderRecursive(n: number): string {\n let header = '';\n let char = n;\n if (n >= 26) {\n header = header.concat(\n CsvParser.generateHeaderRecursive(Math.floor(n / 26) - 1)\n );\n char = n % 26;\n }\n return header.concat(String.fromCharCode(65 + char));\n }\n\n constructor({\n onFileCompleted,\n session,\n file,\n type,\n readHeaders = true,\n onProgress,\n onError,\n timeZone,\n isZip,\n }: CsvParserConstructor) {\n this.onFileCompleted = onFileCompleted;\n this.session = session;\n this.file = file;\n this.isZip = isZip;\n this.type = type;\n this.readHeaders = readHeaders;\n this.timeZone = timeZone;\n this.onProgress = onProgress;\n this.onError = onError;\n this.tables = [];\n this.chunks = 0;\n this.totalChunks = isZip\n ? 0\n : Math.ceil((file as Blob).size / Papa.LocalChunkSize);\n this.isComplete = false;\n this.zipProgress = 0;\n this.numConsolidated = 0;\n this.isCancelled = false;\n\n this.handleChunk = this.handleChunk.bind(this);\n this.handleError = this.handleError.bind(this);\n this.handleComplete = this.handleComplete.bind(this);\n this.handleNodeUpdate = this.handleNodeUpdate.bind(this);\n this.handleCreateTable = this.handleCreateTable.bind(this);\n\n this.config = {\n delimiter: type.delimiter,\n newline: type.newline as '\\r\\n' | '\\n' | '\\r' | undefined,\n escapeChar: type.escapeChar,\n dynamicTyping: false,\n error: this.handleError,\n skipEmptyLines: type.skipEmptyLines,\n chunk: this.handleChunk,\n complete: this.handleComplete,\n fastMode: false,\n };\n }\n\n onFileCompleted: (tables: Table[]) => void;\n\n session: IdeSession;\n\n file: Blob | JSZipObject;\n\n isZip: boolean;\n\n type: CsvTypes;\n\n readHeaders: boolean;\n\n timeZone: string;\n\n onProgress: (progressValue: number) => boolean;\n\n onError: (e: unknown) => void;\n\n tables: Table[];\n\n headers?: string[];\n\n types?: string[];\n\n chunks: number;\n\n totalChunks: number;\n\n isComplete: boolean;\n\n zipProgress: number;\n\n consolidatedChunks?: string[][];\n\n numConsolidated: number;\n\n isCancelled: boolean;\n\n config: ParseLocalConfig<unknown, Blob | NodeJS.ReadableStream>;\n\n cancel(): void {\n this.isCancelled = true;\n }\n\n transpose(numColumns: number, array: string[][]): string[][] {\n const numRows = array.length;\n const columns = new Array(numColumns)\n .fill(null)\n .map(() => new Array(numRows));\n for (let r = 0; r < numRows; r += 1) {\n const row = array[r];\n if (row.length < numColumns) {\n throw new Error(\n `Insufficient columns. Expected ${numColumns} but found ${row.length}\\n${row}`\n );\n }\n for (let c = 0; c < numColumns; c += 1) {\n const value = this.type.shouldTrim ? array[r][c].trim() : array[r][c];\n columns[c][r] = this.nullCheck(value);\n }\n }\n return columns as string[][];\n }\n\n nullCheck(value: string): string {\n return value === this.type.nullString ? '' : value;\n }\n\n parse(): void {\n const handleParseDone = (types: string[]) => {\n const toParse = this.isZip\n ? (this.file as JSZipObject).nodeStream(\n // JsZip types are incorrect, thus the funny casting\n // Actual parameter is 'nodebuffer'\n 'nodebuffer' as 'nodestream',\n this.handleNodeUpdate\n )\n : (this.file as Blob);\n this.types = types;\n Papa.parse(toParse, this.config);\n };\n const typeParser = new CsvTypeParser(\n handleParseDone,\n this.file,\n this.readHeaders,\n this.config,\n this.type.nullString,\n this.onProgress,\n this.onError,\n this.totalChunks,\n this.isZip,\n this.type.shouldTrim\n );\n typeParser.parse();\n }\n\n handleChunk(result: ParseResult<string[]>, parser: Parser): void {\n const { readHeaders, onError, handleCreateTable, isZip, tables } = this;\n if (this.isCancelled) {\n log.debug2('CSV parser cancelled.');\n parser.abort();\n tables.forEach(t => t.close());\n return;\n }\n let { data } = result;\n if (!this.headers) {\n if (readHeaders) {\n this.headers = DbNameValidator.legalizeColumnNames(data[0]);\n data = data.slice(1);\n } else {\n this.headers = CsvParser.generateHeaders(data[0].length);\n }\n }\n\n let columns: string[][] = [];\n try {\n columns = this.transpose(this.headers.length, data);\n if (isZip) {\n // Zip file chunks are tiny, so consolidate them to avoid create thousands of small tables\n this.consolidateChunks(columns, parser);\n } else {\n const index = this.chunks;\n this.chunks += 1;\n handleCreateTable(index, columns, parser);\n }\n } catch (e: unknown) {\n onError(e);\n }\n }\n\n consolidateChunks(columns: string[][], parser: Parser): void {\n if (!this.consolidatedChunks) {\n this.consolidatedChunks = columns.slice();\n } else {\n for (let i = 0; i < columns.length; i += 1) {\n this.consolidatedChunks[i] = this.consolidatedChunks[i].concat(\n columns[i]\n );\n }\n }\n this.numConsolidated += 1;\n if (this.numConsolidated >= ZIP_CONSOLIDATE_CHUNKS || this.isComplete) {\n this.uploadConsolidatedChunks(parser);\n }\n }\n\n uploadConsolidatedChunks(parser: Parser | null): void {\n const { handleCreateTable } = this;\n const index = this.chunks;\n this.chunks += 1;\n const toUpload = this.consolidatedChunks?.slice();\n this.consolidatedChunks = undefined;\n this.numConsolidated = 0;\n assertNotNull(toUpload);\n handleCreateTable(index, toUpload, parser);\n }\n\n handleCreateTable(\n index: number,\n columns: string[][],\n parser: Parser | null\n ): void {\n const {\n session,\n tables,\n onFileCompleted,\n totalChunks,\n types,\n onProgress,\n onError,\n } = this;\n if (parser) {\n parser.pause();\n }\n assertNotNull(this.headers);\n assertNotNull(types);\n session\n .newTable(this.headers, types, columns, this.timeZone)\n .then(table => {\n if (this.isCancelled) {\n log.debug2('CSV parser cancelled.');\n if (parser) {\n parser.abort();\n }\n tables.forEach(t => t.close());\n return;\n }\n if (parser) {\n parser.resume();\n }\n tables[index] = table;\n // This accounts for 50% of parsing plus 50% already done by the type parser\n let progress = 0;\n if (totalChunks > 0) {\n progress = Math.round((tables.length / totalChunks) * 50) + 50;\n } else {\n progress = Math.round(50 + this.zipProgress / 2);\n }\n log.debug2(`CSV parser progress ${progress}`);\n onProgress(progress);\n if (this.isComplete && tables.length === this.chunks) {\n log.debug2('CSV parser complete.');\n onFileCompleted(tables);\n }\n })\n .catch(e => {\n if (!this.isComplete && parser) {\n parser.abort();\n }\n onError(e);\n });\n }\n\n handleComplete(results: ParseResult<unknown>): void {\n // results is undefined for a succesful parse, but has meta data for an abort\n if (results == null || results.meta.aborted == null) {\n this.isComplete = true;\n // Check if there are any consolidated chunks left over from a zip file\n if (this.consolidatedChunks) {\n this.uploadConsolidatedChunks(null);\n }\n }\n }\n\n handleError(error: unknown): void {\n const { onError } = this;\n onError(error);\n }\n\n handleNodeUpdate(metadata: { percent: number }): void {\n this.zipProgress = metadata.percent;\n }\n}\n\nexport default CsvParser;\n"],"mappings":"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"}
|
|
@@ -1,198 +1,143 @@
|
|
|
1
1
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
-
|
|
3
2
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
-
|
|
5
3
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
-
|
|
7
4
|
import { assertNotNull } from '@deephaven/utils';
|
|
8
|
-
import Papa from 'papaparse';
|
|
9
|
-
|
|
5
|
+
import Papa from 'papaparse';
|
|
6
|
+
// Intentionally using isNaN rather than Number.isNaN
|
|
10
7
|
/* eslint-disable no-restricted-globals */
|
|
11
|
-
|
|
12
8
|
import NewTableColumnTypes from "./NewTableColumnTypes.js"; // Initially column types start al unknown
|
|
13
|
-
|
|
14
9
|
var UNKNOWN = 'unknown';
|
|
15
10
|
var MAX_INT = 2147483647;
|
|
16
11
|
var MIN_INT = -2147483648;
|
|
17
12
|
var DATE_TIME_REGEX = /^[0-9]{4}-[0-1][0-9]-[0-3][0-9][ T][0-2][0-9]:[0-5][0-9]:[0-6][0-9](?:\.[0-9]{1,9})?(?: [a-zA-Z]+)?$/;
|
|
18
13
|
var LOCAL_TIME_REGEX = /^([0-9]+T)?([0-9]+):([0-9]+)(:[0-9]+)?(?:\.[0-9]{1,9})?$/;
|
|
14
|
+
|
|
19
15
|
/**
|
|
20
16
|
* Determines the type of each column in a CSV file by parsing it and looking at every value.
|
|
21
17
|
*/
|
|
22
|
-
|
|
23
18
|
class CsvTypeParser {
|
|
24
19
|
static determineType(value, type, nullString) {
|
|
25
20
|
if (!value || value === nullString) {
|
|
26
21
|
// A null tells us nothing about the type
|
|
27
22
|
return type;
|
|
28
23
|
}
|
|
29
|
-
|
|
30
24
|
switch (type) {
|
|
31
25
|
case NewTableColumnTypes.STRING:
|
|
32
26
|
// Strings never get promoted
|
|
33
27
|
return NewTableColumnTypes.STRING;
|
|
34
|
-
|
|
35
28
|
case NewTableColumnTypes.INTEGER:
|
|
36
29
|
return CsvTypeParser.checkInteger(value);
|
|
37
|
-
|
|
38
30
|
case NewTableColumnTypes.LONG:
|
|
39
31
|
return CsvTypeParser.checkLong(value);
|
|
40
|
-
|
|
41
32
|
case NewTableColumnTypes.DOUBLE:
|
|
42
33
|
return CsvTypeParser.checkDouble(value);
|
|
43
|
-
|
|
44
34
|
case NewTableColumnTypes.BOOLEAN:
|
|
45
35
|
return CsvTypeParser.checkBoolean(value);
|
|
46
|
-
|
|
47
36
|
case NewTableColumnTypes.DATE_TIME:
|
|
48
37
|
return CsvTypeParser.checkDateTime(value);
|
|
49
|
-
|
|
50
38
|
case NewTableColumnTypes.LOCAL_TIME:
|
|
51
39
|
return CsvTypeParser.checkLocalTime(value);
|
|
52
|
-
|
|
53
40
|
default:
|
|
54
41
|
return CsvTypeParser.getTypeFromUnknown(value);
|
|
55
42
|
}
|
|
56
|
-
}
|
|
57
|
-
|
|
43
|
+
}
|
|
58
44
|
|
|
45
|
+
// Allows for cusomt rules in addition to isNaN
|
|
59
46
|
static isNotParsableNumber(s) {
|
|
60
47
|
return isNaN(s) || s === 'Infinity' || s === '-Infinity';
|
|
61
48
|
}
|
|
62
|
-
|
|
63
49
|
static checkInteger(value) {
|
|
64
50
|
var noCommas = value.replace(/,/g, '');
|
|
65
|
-
|
|
66
51
|
if (CsvTypeParser.isNotParsableNumber(noCommas)) {
|
|
67
52
|
return NewTableColumnTypes.STRING;
|
|
68
53
|
}
|
|
69
|
-
|
|
70
54
|
return CsvTypeParser.getNumberType(noCommas);
|
|
71
55
|
}
|
|
72
|
-
|
|
73
56
|
static checkLong(value) {
|
|
74
57
|
var noCommas = value.replace(/,/g, '');
|
|
75
|
-
|
|
76
58
|
if (CsvTypeParser.isNotParsableNumber(noCommas)) {
|
|
77
59
|
return NewTableColumnTypes.STRING;
|
|
78
60
|
}
|
|
79
|
-
|
|
80
61
|
if (noCommas.includes('.')) {
|
|
81
62
|
return NewTableColumnTypes.DOUBLE;
|
|
82
63
|
}
|
|
83
|
-
|
|
84
64
|
return NewTableColumnTypes.LONG;
|
|
85
65
|
}
|
|
86
|
-
|
|
87
66
|
static checkDouble(value) {
|
|
88
67
|
var noCommas = value.replace(/,/g, '');
|
|
89
|
-
|
|
90
68
|
if (CsvTypeParser.isNotParsableNumber(noCommas)) {
|
|
91
69
|
return NewTableColumnTypes.STRING;
|
|
92
70
|
}
|
|
93
|
-
|
|
94
71
|
return NewTableColumnTypes.DOUBLE;
|
|
95
72
|
}
|
|
96
|
-
|
|
97
73
|
static checkBoolean(value) {
|
|
98
74
|
var lower = value.toLowerCase();
|
|
99
|
-
|
|
100
75
|
if (lower === 'true' || lower === 'false') {
|
|
101
76
|
return NewTableColumnTypes.BOOLEAN;
|
|
102
77
|
}
|
|
103
|
-
|
|
104
78
|
return NewTableColumnTypes.STRING;
|
|
105
79
|
}
|
|
106
|
-
|
|
107
80
|
static checkDateTime(value) {
|
|
108
81
|
if (DATE_TIME_REGEX.test(value)) {
|
|
109
82
|
return NewTableColumnTypes.DATE_TIME;
|
|
110
83
|
}
|
|
111
|
-
|
|
112
84
|
return NewTableColumnTypes.STRING;
|
|
113
85
|
}
|
|
114
|
-
|
|
115
86
|
static checkLocalTime(value) {
|
|
116
87
|
if (LOCAL_TIME_REGEX.test(value)) {
|
|
117
88
|
return NewTableColumnTypes.LOCAL_TIME;
|
|
118
89
|
}
|
|
119
|
-
|
|
120
90
|
return NewTableColumnTypes.STRING;
|
|
121
91
|
}
|
|
122
|
-
|
|
123
92
|
static getTypeFromUnknown(value) {
|
|
124
93
|
var noCommas = value.replace(/,/g, '');
|
|
125
|
-
|
|
126
94
|
if (CsvTypeParser.isNotParsableNumber(noCommas)) {
|
|
127
95
|
var lower = value.toLowerCase();
|
|
128
|
-
|
|
129
96
|
if (lower === 'true' || lower === 'false') {
|
|
130
97
|
return NewTableColumnTypes.BOOLEAN;
|
|
131
98
|
}
|
|
132
|
-
|
|
133
99
|
if (DATE_TIME_REGEX.test(value) && value.includes(':')) {
|
|
134
100
|
return NewTableColumnTypes.DATE_TIME;
|
|
135
101
|
}
|
|
136
|
-
|
|
137
102
|
if (LOCAL_TIME_REGEX.test(value)) {
|
|
138
103
|
return NewTableColumnTypes.LOCAL_TIME;
|
|
139
104
|
}
|
|
140
|
-
|
|
141
105
|
return NewTableColumnTypes.STRING;
|
|
142
106
|
}
|
|
143
|
-
|
|
144
107
|
return CsvTypeParser.getNumberType(noCommas);
|
|
145
108
|
}
|
|
146
|
-
|
|
147
109
|
static getNumberType(value) {
|
|
148
110
|
if (value.includes('.')) {
|
|
149
111
|
return NewTableColumnTypes.DOUBLE;
|
|
150
|
-
}
|
|
151
|
-
|
|
112
|
+
}
|
|
152
113
|
|
|
114
|
+
// Fast length check
|
|
153
115
|
var maxIntLength = value.startsWith('-') ? 11 : 10;
|
|
154
|
-
|
|
155
116
|
if (value.length > maxIntLength) {
|
|
156
117
|
return NewTableColumnTypes.LONG;
|
|
157
|
-
}
|
|
158
|
-
|
|
118
|
+
}
|
|
159
119
|
|
|
120
|
+
// Slower parseInt check
|
|
160
121
|
var intValue = parseInt(value, 10);
|
|
161
|
-
|
|
162
122
|
if (intValue > MAX_INT || intValue < MIN_INT) {
|
|
163
123
|
return NewTableColumnTypes.LONG;
|
|
164
124
|
}
|
|
165
|
-
|
|
166
125
|
return NewTableColumnTypes.INTEGER;
|
|
167
126
|
}
|
|
168
|
-
|
|
169
127
|
constructor(onFileCompleted, file, readHeaders, parentConfig, nullString, onProgress, onError, totalChunks, isZip, shouldTrim) {
|
|
170
128
|
_defineProperty(this, "onFileCompleted", void 0);
|
|
171
|
-
|
|
172
129
|
_defineProperty(this, "file", void 0);
|
|
173
|
-
|
|
174
130
|
_defineProperty(this, "readHeaders", void 0);
|
|
175
|
-
|
|
176
131
|
_defineProperty(this, "nullString", void 0);
|
|
177
|
-
|
|
178
132
|
_defineProperty(this, "onProgress", void 0);
|
|
179
|
-
|
|
180
133
|
_defineProperty(this, "onError", void 0);
|
|
181
|
-
|
|
182
134
|
_defineProperty(this, "types", void 0);
|
|
183
|
-
|
|
184
135
|
_defineProperty(this, "chunks", void 0);
|
|
185
|
-
|
|
186
136
|
_defineProperty(this, "totalChunks", void 0);
|
|
187
|
-
|
|
188
137
|
_defineProperty(this, "isZip", void 0);
|
|
189
|
-
|
|
190
138
|
_defineProperty(this, "shouldTrim", void 0);
|
|
191
|
-
|
|
192
139
|
_defineProperty(this, "zipProgress", void 0);
|
|
193
|
-
|
|
194
140
|
_defineProperty(this, "config", void 0);
|
|
195
|
-
|
|
196
141
|
this.onFileCompleted = onFileCompleted;
|
|
197
142
|
this.file = file;
|
|
198
143
|
this.readHeaders = readHeaders;
|
|
@@ -214,34 +159,29 @@ class CsvTypeParser {
|
|
|
214
159
|
complete: this.handleComplete
|
|
215
160
|
});
|
|
216
161
|
}
|
|
217
|
-
|
|
218
162
|
parse() {
|
|
219
|
-
var toParse = this.isZip ? this.file.nodeStream(
|
|
163
|
+
var toParse = this.isZip ? this.file.nodeStream(
|
|
164
|
+
// JsZip types are incorrect, thus the funny casting
|
|
220
165
|
// Actual parameter is 'nodebuffer'
|
|
221
166
|
'nodebuffer', this.handleNodeUpdate) : this.file;
|
|
222
167
|
Papa.parse(toParse, this.config);
|
|
223
168
|
}
|
|
224
|
-
|
|
225
169
|
handleChunk(result, parser) {
|
|
226
170
|
var {
|
|
227
171
|
data
|
|
228
172
|
} = result;
|
|
229
|
-
|
|
230
173
|
if (!this.types) {
|
|
231
174
|
if (data == null || data.length === 0) {
|
|
232
175
|
parser.abort();
|
|
233
176
|
this.onError('Error parsing CSV: no data in file.');
|
|
234
177
|
return;
|
|
235
178
|
}
|
|
236
|
-
|
|
237
179
|
this.types = new Array(data[0].length).fill(UNKNOWN);
|
|
238
|
-
|
|
239
180
|
if (this.readHeaders) {
|
|
240
181
|
// If headers are being read from the file, remove them from type analysis
|
|
241
182
|
data = data.slice(1);
|
|
242
183
|
}
|
|
243
184
|
}
|
|
244
|
-
|
|
245
185
|
assertNotNull(this.types);
|
|
246
186
|
var cloneTypes = [...this.types];
|
|
247
187
|
data.forEach(row => {
|
|
@@ -249,55 +189,45 @@ class CsvTypeParser {
|
|
|
249
189
|
for (var i = 0; i < cloneTypes.length; i += 1) {
|
|
250
190
|
cloneTypes[i] = CsvTypeParser.determineType(this.shouldTrim ? row[i].trim() : row[i], cloneTypes[i], this.nullString);
|
|
251
191
|
}
|
|
252
|
-
|
|
253
192
|
this.types = cloneTypes;
|
|
254
193
|
} else {
|
|
255
194
|
parser.abort();
|
|
256
195
|
this.onError("Error parsing CSV: Insufficient data in row.\nExpected length ".concat(cloneTypes.length, " but found ").concat(row.length, ".\nRow = ").concat(row));
|
|
257
196
|
}
|
|
258
197
|
});
|
|
259
|
-
this.chunks += 1;
|
|
260
|
-
|
|
198
|
+
this.chunks += 1;
|
|
199
|
+
// 50 because the type parsing accounts for 50% of the parsing
|
|
261
200
|
var progress = 0;
|
|
262
|
-
|
|
263
201
|
if (this.totalChunks > 0) {
|
|
264
202
|
progress = Math.round(this.chunks / this.totalChunks * 50);
|
|
265
203
|
} else {
|
|
266
204
|
progress = Math.round(this.zipProgress / 2);
|
|
267
205
|
}
|
|
268
|
-
|
|
269
206
|
var isCancelled = this.onProgress(progress);
|
|
270
|
-
|
|
271
207
|
if (isCancelled) {
|
|
272
208
|
parser.abort();
|
|
273
209
|
}
|
|
274
210
|
}
|
|
275
|
-
|
|
276
211
|
handleComplete(results) {
|
|
277
212
|
var {
|
|
278
213
|
types,
|
|
279
214
|
onFileCompleted
|
|
280
|
-
} = this;
|
|
281
|
-
|
|
215
|
+
} = this;
|
|
216
|
+
// results is undefined for a succesful parse, but has meta data for an abort
|
|
282
217
|
assertNotNull(types);
|
|
283
|
-
|
|
284
218
|
if (results == null || !results.meta.aborted) {
|
|
285
219
|
onFileCompleted(types.map(type => type === UNKNOWN ? NewTableColumnTypes.STRING : type));
|
|
286
220
|
}
|
|
287
221
|
}
|
|
288
|
-
|
|
289
222
|
handleError(error) {
|
|
290
223
|
var {
|
|
291
224
|
onError
|
|
292
225
|
} = this;
|
|
293
226
|
onError(error);
|
|
294
227
|
}
|
|
295
|
-
|
|
296
228
|
handleNodeUpdate(metadata) {
|
|
297
229
|
this.zipProgress = metadata.percent;
|
|
298
230
|
}
|
|
299
|
-
|
|
300
231
|
}
|
|
301
|
-
|
|
302
232
|
export default CsvTypeParser;
|
|
303
233
|
//# sourceMappingURL=CsvTypeParser.js.map
|