df-script 1.5.0 → 1.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/README.md +124 -8
- package/dist/api.d.ts +1 -1
- package/dist/columnExpressions/ColumnExpr.d.ts +2 -2
- package/dist/columnExpressions/functions/coalesce.d.ts +2 -2
- package/dist/columnExpressions/functions/element.d.ts +1 -1
- package/dist/columnExpressions/functions/when.d.ts +2 -2
- package/dist/columnExpressions/index.d.ts +1 -1
- package/dist/columnExpressions/mixins/AggregationExpr.d.ts +2 -2
- package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +11 -10
- package/dist/columnExpressions/mixins/ArrayExpr.d.ts +39 -0
- package/dist/columnExpressions/mixins/ListExpr.d.ts +2 -2
- package/dist/columnExpressions/mixins/StringExpr.d.ts +2 -2
- package/dist/columnExpressions/types.d.ts +1 -0
- package/dist/constants.d.ts +11 -0
- package/dist/dataframe/dataframe.d.ts +1 -1
- package/dist/datatypes/index.d.ts +3 -2
- package/dist/datatypes/types.d.ts +7 -7
- package/dist/index.js +6 -6
- package/dist/types.d.ts +4 -2
- package/dist/utils/array.d.ts +217 -0
- package/dist/utils/binary.d.ts +3 -0
- package/dist/utils/date.d.ts +21 -35
- package/dist/utils/guards.d.ts +11 -10
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/list.d.ts +23 -1
- package/dist/utils/number.d.ts +14 -29
- package/dist/utils/object.d.ts +26 -0
- package/dist/utils/string.d.ts +3 -5
- package/package.json +2 -2
- package/dist/api.js +0 -26
- package/dist/bundle.min.js +0 -1
- package/dist/columnExpressions/ColumnExpr.js +0 -219
- package/dist/columnExpressions/ExprBase.js +0 -92
- package/dist/columnExpressions/constants.js +0 -7
- package/dist/columnExpressions/functions/all.js +0 -11
- package/dist/columnExpressions/functions/coalesce.js +0 -44
- package/dist/columnExpressions/functions/element.js +0 -11
- package/dist/columnExpressions/functions/exclude.js +0 -13
- package/dist/columnExpressions/functions/implode.js +0 -7
- package/dist/columnExpressions/functions/lit.js +0 -17
- package/dist/columnExpressions/functions/repeat.d.ts +0 -47
- package/dist/columnExpressions/functions/repeat.js +0 -131
- package/dist/columnExpressions/functions/seq_range.js +0 -91
- package/dist/columnExpressions/functions/when.js +0 -85
- package/dist/columnExpressions/index.js +0 -38
- package/dist/columnExpressions/mixins/AggregationExpr.js +0 -76
- package/dist/columnExpressions/mixins/ArithmeticExpr.js +0 -131
- package/dist/columnExpressions/mixins/BooleanExpr.d.ts +0 -40
- package/dist/columnExpressions/mixins/BooleanExpr.js +0 -67
- package/dist/columnExpressions/mixins/ComparisonExpr.js +0 -250
- package/dist/columnExpressions/mixins/ListExpr.js +0 -224
- package/dist/columnExpressions/mixins/LogicalExpr.js +0 -53
- package/dist/columnExpressions/mixins/ManipulationExpr.js +0 -71
- package/dist/columnExpressions/mixins/NumericExpr.d.ts +0 -92
- package/dist/columnExpressions/mixins/NumericExpr.js +0 -259
- package/dist/columnExpressions/mixins/StringExpr.js +0 -237
- package/dist/columnExpressions/mixins/StructExpr.js +0 -139
- package/dist/columnExpressions/mixins/TemporalExpr.js +0 -126
- package/dist/columnExpressions/mixins/WindowExpr.js +0 -151
- package/dist/columnExpressions/types.js +0 -2
- package/dist/columnExpressions/utils.js +0 -45
- package/dist/dataframe/constants.js +0 -7
- package/dist/dataframe/dataframe.js +0 -990
- package/dist/dataframe/grouped/grouped.js +0 -114
- package/dist/dataframe/index.js +0 -20
- package/dist/dataframe/types.js +0 -2
- package/dist/dataframe/utils.js +0 -307
- package/dist/datatypes/DataType.js +0 -76
- package/dist/datatypes/index.js +0 -46
- package/dist/datatypes/types/Binary.d.ts +0 -9
- package/dist/datatypes/types/Binary.js +0 -18
- package/dist/datatypes/types/Boolean.d.ts +0 -9
- package/dist/datatypes/types/Boolean.js +0 -19
- package/dist/datatypes/types/Date.d.ts +0 -8
- package/dist/datatypes/types/Date.js +0 -21
- package/dist/datatypes/types/Datetime.d.ts +0 -8
- package/dist/datatypes/types/Datetime.js +0 -17
- package/dist/datatypes/types/Decimal.d.ts +0 -10
- package/dist/datatypes/types/Decimal.js +0 -28
- package/dist/datatypes/types/Duration.d.ts +0 -8
- package/dist/datatypes/types/Duration.js +0 -17
- package/dist/datatypes/types/Float32.d.ts +0 -8
- package/dist/datatypes/types/Float32.js +0 -17
- package/dist/datatypes/types/Float64.d.ts +0 -8
- package/dist/datatypes/types/Float64.js +0 -17
- package/dist/datatypes/types/Int16.d.ts +0 -8
- package/dist/datatypes/types/Int16.js +0 -17
- package/dist/datatypes/types/Int32.d.ts +0 -8
- package/dist/datatypes/types/Int32.js +0 -17
- package/dist/datatypes/types/Int64.d.ts +0 -8
- package/dist/datatypes/types/Int64.js +0 -17
- package/dist/datatypes/types/Int8.d.ts +0 -8
- package/dist/datatypes/types/Int8.js +0 -17
- package/dist/datatypes/types/List.d.ts +0 -10
- package/dist/datatypes/types/List.js +0 -31
- package/dist/datatypes/types/Null.d.ts +0 -9
- package/dist/datatypes/types/Null.js +0 -17
- package/dist/datatypes/types/Object.d.ts +0 -9
- package/dist/datatypes/types/Object.js +0 -17
- package/dist/datatypes/types/Struct.d.ts +0 -14
- package/dist/datatypes/types/Struct.js +0 -39
- package/dist/datatypes/types/Time.d.ts +0 -8
- package/dist/datatypes/types/Time.js +0 -29
- package/dist/datatypes/types/UInt16.d.ts +0 -8
- package/dist/datatypes/types/UInt16.js +0 -17
- package/dist/datatypes/types/UInt32.d.ts +0 -8
- package/dist/datatypes/types/UInt32.js +0 -17
- package/dist/datatypes/types/UInt64.d.ts +0 -8
- package/dist/datatypes/types/UInt64.js +0 -17
- package/dist/datatypes/types/UInt8.d.ts +0 -8
- package/dist/datatypes/types/UInt8.js +0 -17
- package/dist/datatypes/types/Utf8.d.ts +0 -10
- package/dist/datatypes/types/Utf8.js +0 -20
- package/dist/datatypes/types.js +0 -290
- package/dist/exceptions/index.js +0 -46
- package/dist/exceptions/utils.js +0 -28
- package/dist/functions/concat.js +0 -260
- package/dist/functions/index.js +0 -9
- package/dist/functions/read_csv.js +0 -53
- package/dist/functions/read_json.js +0 -21
- package/dist/functions/transpose.d.ts +0 -7
- package/dist/functions/transpose.js +0 -84
- package/dist/types.js +0 -2
- package/dist/utils/boolean.d.ts +0 -1
- package/dist/utils/boolean.js +0 -18
- package/dist/utils/csv.js +0 -313
- package/dist/utils/date.js +0 -348
- package/dist/utils/guards.js +0 -112
- package/dist/utils/index.js +0 -23
- package/dist/utils/json.js +0 -217
- package/dist/utils/list.js +0 -361
- package/dist/utils/number.js +0 -401
- package/dist/utils/string.js +0 -209
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.read_json = read_json;
|
|
4
|
-
const dataframe_1 = require("../dataframe/dataframe");
|
|
5
|
-
const utils_1 = require("../utils");
|
|
6
|
-
const exceptions_1 = require("../exceptions");
|
|
7
|
-
/**
|
|
8
|
-
* Parses JSON content (JSON or NDJSON) and loads it into a new DataFrame.
|
|
9
|
-
*
|
|
10
|
-
* @param content The JSON or NDJSON content string.
|
|
11
|
-
* @param options Parse and configuration options.
|
|
12
|
-
* @returns A new DataFrame instance populated with the parsed records.
|
|
13
|
-
*/
|
|
14
|
-
function read_json(content, { format = "json", trimBeforeParse = true, schema, ...parseOpts } = {}) {
|
|
15
|
-
const parsed = (0, utils_1.safeJsonParse)(content, { format, trimBeforeParse, ...parseOpts });
|
|
16
|
-
if (parsed === content) {
|
|
17
|
-
throw new exceptions_1.DataFrameError(`Invalid JSON input: must be a valid, non-empty JSON ${format} string.`);
|
|
18
|
-
}
|
|
19
|
-
const parsedData = Array.isArray(parsed) ? parsed : ((0, utils_1.isObj)(parsed) ? [parsed] : []);
|
|
20
|
-
return new dataframe_1.DataFrame(parsedData, schema);
|
|
21
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { DataFrame } from "../dataframe/dataframe";
|
|
2
|
-
import type { RowRecord } from "../types";
|
|
3
|
-
import type { TransposeOptions } from "../dataframe/types";
|
|
4
|
-
/**
|
|
5
|
-
* Transposes the rows and columns of a DataFrame.
|
|
6
|
-
*/
|
|
7
|
-
export declare function transpose<T extends RowRecord = any>(df: DataFrame<T>, { include_header: includeHeader, header_name: headerName, column_names: colNamesOpt }?: TransposeOptions): DataFrame<any>;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.transpose = transpose;
|
|
4
|
-
const dataframe_1 = require("../dataframe/dataframe");
|
|
5
|
-
const datatypes_1 = require("../datatypes");
|
|
6
|
-
const utils_1 = require("../dataframe/utils");
|
|
7
|
-
const exceptions_1 = require("../exceptions");
|
|
8
|
-
/**
|
|
9
|
-
* Transposes the rows and columns of a DataFrame.
|
|
10
|
-
*/
|
|
11
|
-
function transpose(df, { include_header: includeHeader = false, header_name: headerName = "column", column_names: colNamesOpt } = {}) {
|
|
12
|
-
const height = df.height;
|
|
13
|
-
if (height === 0) {
|
|
14
|
-
const cols = {};
|
|
15
|
-
const schema = {};
|
|
16
|
-
if (includeHeader) {
|
|
17
|
-
cols[headerName] = (0, utils_1.coerceColumn)([], datatypes_1.DataTypeRegistry.Utf8, 0);
|
|
18
|
-
schema[headerName] = datatypes_1.DataTypeRegistry.Utf8;
|
|
19
|
-
}
|
|
20
|
-
return dataframe_1.DataFrame._createDirect(cols, schema, 0);
|
|
21
|
-
}
|
|
22
|
-
let dataColumns = df.columns;
|
|
23
|
-
if (typeof colNamesOpt === "string") {
|
|
24
|
-
(0, exceptions_1.assertColumnExists)(colNamesOpt, df._columns, "column_names");
|
|
25
|
-
dataColumns = dataColumns.filter(c => c !== colNamesOpt);
|
|
26
|
-
}
|
|
27
|
-
let newColNames = [];
|
|
28
|
-
if (typeof colNamesOpt === "string") {
|
|
29
|
-
const keyCol = df._columns[colNamesOpt];
|
|
30
|
-
newColNames = new Array(height);
|
|
31
|
-
for (let i = 0; i < height; i++) {
|
|
32
|
-
const val = keyCol[i];
|
|
33
|
-
if (val == null) {
|
|
34
|
-
throw new exceptions_1.DataFrameError(`Transpose column_names column "${colNamesOpt}" contains null/undefined at index ${i}`);
|
|
35
|
-
}
|
|
36
|
-
newColNames[i] = String(val);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
else if (colNamesOpt != null && typeof colNamesOpt !== "string" && Symbol.iterator in Object(colNamesOpt)) {
|
|
40
|
-
const colNamesArr = Array.from(colNamesOpt);
|
|
41
|
-
if (colNamesArr.length !== height) {
|
|
42
|
-
throw new exceptions_1.DataFrameError(`column_names length (${colNamesArr.length}) must match the height of the DataFrame (${height})`);
|
|
43
|
-
}
|
|
44
|
-
newColNames = new Array(height);
|
|
45
|
-
for (let i = 0; i < height; i++) {
|
|
46
|
-
newColNames[i] = String(colNamesArr[i]);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
newColNames = new Array(height);
|
|
51
|
-
for (let i = 0; i < height; i++) {
|
|
52
|
-
newColNames[i] = `column_${i}`;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const uniqueNames = new Set();
|
|
56
|
-
if (includeHeader) {
|
|
57
|
-
uniqueNames.add(headerName);
|
|
58
|
-
}
|
|
59
|
-
for (let i = 0; i < newColNames.length; i++) {
|
|
60
|
-
const name = newColNames[i];
|
|
61
|
-
if (uniqueNames.has(name)) {
|
|
62
|
-
throw new exceptions_1.DataFrameError(`Duplicate column name in transposed DataFrame: "${name}"`);
|
|
63
|
-
}
|
|
64
|
-
uniqueNames.add(name);
|
|
65
|
-
}
|
|
66
|
-
const numDataCols = dataColumns.length;
|
|
67
|
-
const newCols = {};
|
|
68
|
-
const newSchema = {};
|
|
69
|
-
if (includeHeader) {
|
|
70
|
-
newCols[headerName] = (0, utils_1.coerceColumn)(dataColumns, datatypes_1.DataTypeRegistry.Utf8, numDataCols);
|
|
71
|
-
newSchema[headerName] = datatypes_1.DataTypeRegistry.Utf8;
|
|
72
|
-
}
|
|
73
|
-
for (let i = 0; i < height; i++) {
|
|
74
|
-
const colName = newColNames[i];
|
|
75
|
-
const rawVals = new Array(numDataCols);
|
|
76
|
-
for (let j = 0; j < numDataCols; j++) {
|
|
77
|
-
rawVals[j] = df._columns[dataColumns[j]][i];
|
|
78
|
-
}
|
|
79
|
-
const type = (0, utils_1.inferColumnType)(rawVals);
|
|
80
|
-
newCols[colName] = (0, utils_1.coerceColumn)(rawVals, type, numDataCols);
|
|
81
|
-
newSchema[colName] = type;
|
|
82
|
-
}
|
|
83
|
-
return dataframe_1.DataFrame._createDirect(newCols, newSchema, numDataCols);
|
|
84
|
-
}
|
package/dist/types.js
DELETED
package/dist/utils/boolean.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function tryParseBoolean(v: unknown): boolean | undefined;
|
package/dist/utils/boolean.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.tryParseBoolean = tryParseBoolean;
|
|
4
|
-
const boolMap = {
|
|
5
|
-
true: true, "1": true, yes: true, y: true, on: true,
|
|
6
|
-
false: false, "0": false, no: false, n: false, off: false
|
|
7
|
-
};
|
|
8
|
-
function tryParseBoolean(v) {
|
|
9
|
-
if (typeof v === "boolean")
|
|
10
|
-
return v;
|
|
11
|
-
if (v === 1)
|
|
12
|
-
return true;
|
|
13
|
-
if (v === 0)
|
|
14
|
-
return false;
|
|
15
|
-
if (typeof v !== "string")
|
|
16
|
-
return undefined;
|
|
17
|
-
return boolMap[v.trim().toLowerCase()];
|
|
18
|
-
}
|
package/dist/utils/csv.js
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatCsvValue = formatCsvValue;
|
|
4
|
-
exports.stringifyCSV = stringifyCSV;
|
|
5
|
-
exports.parseCSV = parseCSV;
|
|
6
|
-
exports.inferAndCoerceCSVColumn = inferAndCoerceCSVColumn;
|
|
7
|
-
const date_1 = require("./date");
|
|
8
|
-
const json_1 = require("./json");
|
|
9
|
-
const number_1 = require("./number");
|
|
10
|
-
const constants_1 = require("../dataframe/constants");
|
|
11
|
-
const datatypes_1 = require("../datatypes");
|
|
12
|
-
// Removed stringifyCsvObject
|
|
13
|
-
function formatCsvValueInternal(options = {}) {
|
|
14
|
-
const nullValue = options.nullValue !== undefined ? options.nullValue : "";
|
|
15
|
-
const formatNum = (0, number_1.formatNumber)(options.numericFormatOptions);
|
|
16
|
-
const replacerOptions = options.replacerOptions || {};
|
|
17
|
-
const formatDate = (v) => {
|
|
18
|
-
if (options.datetimeFormat)
|
|
19
|
-
return (0, date_1.strftime)(v, options.datetimeFormat);
|
|
20
|
-
if (options.dateFormat)
|
|
21
|
-
return (0, date_1.strftime)(v, options.dateFormat);
|
|
22
|
-
if (options.timeFormat)
|
|
23
|
-
return (0, date_1.strftime)(v, options.timeFormat);
|
|
24
|
-
return v.toISOString();
|
|
25
|
-
};
|
|
26
|
-
const replacer = (0, json_1.createSafeJsonReplacer)({
|
|
27
|
-
formatDate,
|
|
28
|
-
...replacerOptions
|
|
29
|
-
});
|
|
30
|
-
const hasCustomBigInt = typeof replacerOptions.onBigInt === "function";
|
|
31
|
-
return (val) => {
|
|
32
|
-
if (val === null || val === undefined || typeof val === "symbol" || typeof val === "function") {
|
|
33
|
-
return { str: nullValue, isNumeric: false };
|
|
34
|
-
}
|
|
35
|
-
if (typeof val === "bigint" && !hasCustomBigInt && !replacerOptions.voidBigIntReplacement) {
|
|
36
|
-
return { str: formatNum(val), isNumeric: true };
|
|
37
|
-
}
|
|
38
|
-
const processed = replacer.call(null, "", val);
|
|
39
|
-
if (processed === null || processed === undefined || typeof processed === "symbol" || typeof processed === "function") {
|
|
40
|
-
return { str: nullValue, isNumeric: false };
|
|
41
|
-
}
|
|
42
|
-
if (typeof processed === "string")
|
|
43
|
-
return { str: processed, isNumeric: false };
|
|
44
|
-
if (typeof processed === "number" || typeof processed === "bigint") {
|
|
45
|
-
return { str: formatNum(processed), isNumeric: true };
|
|
46
|
-
}
|
|
47
|
-
if (typeof processed === "boolean")
|
|
48
|
-
return { str: processed ? "true" : "false", isNumeric: false };
|
|
49
|
-
if (processed instanceof Number)
|
|
50
|
-
return { str: formatNum(processed.valueOf()), isNumeric: true };
|
|
51
|
-
if (processed instanceof String)
|
|
52
|
-
return { str: processed.valueOf(), isNumeric: false };
|
|
53
|
-
if (processed instanceof Boolean)
|
|
54
|
-
return { str: processed.valueOf() ? "true" : "false", isNumeric: false };
|
|
55
|
-
if (typeof processed === "object") {
|
|
56
|
-
// Instantiate a fresh replacer specifically for nested stringification
|
|
57
|
-
// to avoid state carry-over (such as visited circular reference sets)
|
|
58
|
-
return {
|
|
59
|
-
str: JSON.stringify(processed, (0, json_1.createSafeJsonReplacer)({
|
|
60
|
-
formatDate,
|
|
61
|
-
...replacerOptions
|
|
62
|
-
})),
|
|
63
|
-
isNumeric: false
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return { str: String(processed), isNumeric: false };
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
function formatCsvValue(options = {}) {
|
|
70
|
-
const formatted = formatCsvValueInternal(options);
|
|
71
|
-
return (val) => formatted(val).str;
|
|
72
|
-
}
|
|
73
|
-
function stringifyCSV(columns, height, options = {}) {
|
|
74
|
-
const { separator = ",", quoteChar = '"', includeHeader = true, lineTerminator = constants_1.NEWLINE, quoteStyle = "necessary", includeBom = false, onRow, ...formatOptions } = options;
|
|
75
|
-
const keys = Object.keys(columns);
|
|
76
|
-
const numKeys = keys.length;
|
|
77
|
-
const lines = [];
|
|
78
|
-
let isFirstRow = true;
|
|
79
|
-
const formatValue = formatCsvValueInternal(formatOptions);
|
|
80
|
-
const escapeAndQuote = (val, isHeader = false) => {
|
|
81
|
-
let strVal;
|
|
82
|
-
let isNumeric = false;
|
|
83
|
-
if (isHeader) {
|
|
84
|
-
strVal = String(val);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
const formatted = formatValue(val);
|
|
88
|
-
strVal = formatted.str;
|
|
89
|
-
isNumeric = formatted.isNumeric;
|
|
90
|
-
}
|
|
91
|
-
if (quoteStyle === "never") {
|
|
92
|
-
return strVal;
|
|
93
|
-
}
|
|
94
|
-
if (quoteStyle === "always") {
|
|
95
|
-
const escaped = strVal.split(quoteChar).join(quoteChar + quoteChar);
|
|
96
|
-
return quoteChar + escaped + quoteChar;
|
|
97
|
-
}
|
|
98
|
-
if (quoteStyle === "non_numeric") {
|
|
99
|
-
if (!isNumeric && val != null) {
|
|
100
|
-
const escaped = strVal.split(quoteChar).join(quoteChar + quoteChar);
|
|
101
|
-
return quoteChar + escaped + quoteChar;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// Default: "necessary"
|
|
105
|
-
const needsQuoting = strVal.includes(separator) ||
|
|
106
|
-
strVal.includes(quoteChar) ||
|
|
107
|
-
strVal.includes(constants_1.NEWLINE) ||
|
|
108
|
-
strVal.includes(constants_1.CARRIAGE_RETURN);
|
|
109
|
-
if (needsQuoting) {
|
|
110
|
-
const escaped = strVal.split(quoteChar).join(quoteChar + quoteChar);
|
|
111
|
-
return quoteChar + escaped + quoteChar;
|
|
112
|
-
}
|
|
113
|
-
return strVal;
|
|
114
|
-
};
|
|
115
|
-
const outputLine = (line) => {
|
|
116
|
-
if (isFirstRow) {
|
|
117
|
-
const initial = includeBom ? constants_1.UTF8_BOM + line : line;
|
|
118
|
-
if (onRow) {
|
|
119
|
-
onRow(initial);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
lines.push(initial);
|
|
123
|
-
}
|
|
124
|
-
isFirstRow = false;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
if (onRow) {
|
|
128
|
-
onRow(lineTerminator + line);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
lines.push(line);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
// Headers
|
|
136
|
-
if (includeHeader) {
|
|
137
|
-
const headerRow = new Array(numKeys);
|
|
138
|
-
for (let i = 0; i < numKeys; i++) {
|
|
139
|
-
headerRow[i] = escapeAndQuote(keys[i], true);
|
|
140
|
-
}
|
|
141
|
-
outputLine(headerRow.join(separator));
|
|
142
|
-
}
|
|
143
|
-
// Rows
|
|
144
|
-
for (let r = 0; r < height; r++) {
|
|
145
|
-
const row = new Array(numKeys);
|
|
146
|
-
for (let i = 0; i < numKeys; i++) {
|
|
147
|
-
row[i] = escapeAndQuote(columns[keys[i]][r], false);
|
|
148
|
-
}
|
|
149
|
-
outputLine(row.join(separator));
|
|
150
|
-
}
|
|
151
|
-
return onRow ? (includeBom ? constants_1.UTF8_BOM : "") : lines.join(lineTerminator);
|
|
152
|
-
}
|
|
153
|
-
function parseCSV(content, options = {}) {
|
|
154
|
-
const separator = options.separator || ",";
|
|
155
|
-
const quoteChar = options.quoteChar || '"';
|
|
156
|
-
let csvContent = content;
|
|
157
|
-
if (csvContent.startsWith(constants_1.UTF8_BOM)) {
|
|
158
|
-
csvContent = csvContent.substring(constants_1.UTF8_BOM.length);
|
|
159
|
-
}
|
|
160
|
-
const rows = [];
|
|
161
|
-
let currentRow = [];
|
|
162
|
-
let currentCell = "";
|
|
163
|
-
let inQuotes = false;
|
|
164
|
-
let hasAnyData = false;
|
|
165
|
-
let lastCharWasSeparator = false;
|
|
166
|
-
const len = csvContent.length;
|
|
167
|
-
for (let i = 0; i < len; i++) {
|
|
168
|
-
const char = csvContent[i];
|
|
169
|
-
if (inQuotes) {
|
|
170
|
-
hasAnyData = true;
|
|
171
|
-
lastCharWasSeparator = false;
|
|
172
|
-
if (char === quoteChar) {
|
|
173
|
-
if (i + 1 < len && csvContent[i + 1] === quoteChar) {
|
|
174
|
-
currentCell += quoteChar;
|
|
175
|
-
i++; // Skip escaped quote
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
inQuotes = false;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
currentCell += char;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
if (char === quoteChar) {
|
|
187
|
-
hasAnyData = true;
|
|
188
|
-
lastCharWasSeparator = false;
|
|
189
|
-
inQuotes = true;
|
|
190
|
-
}
|
|
191
|
-
else if (char === separator) {
|
|
192
|
-
currentRow.push(currentCell);
|
|
193
|
-
currentCell = "";
|
|
194
|
-
lastCharWasSeparator = true;
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
let isLineBreak = false;
|
|
198
|
-
if (char === constants_1.CARRIAGE_RETURN) {
|
|
199
|
-
isLineBreak = true;
|
|
200
|
-
if (i + 1 < len && csvContent[i + 1] === constants_1.NEWLINE) {
|
|
201
|
-
i++;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else if (char === constants_1.NEWLINE) {
|
|
205
|
-
isLineBreak = true;
|
|
206
|
-
}
|
|
207
|
-
if (isLineBreak) {
|
|
208
|
-
if (hasAnyData || currentRow.length > 0 || currentCell !== "" || lastCharWasSeparator) {
|
|
209
|
-
currentRow.push(currentCell);
|
|
210
|
-
rows.push(currentRow);
|
|
211
|
-
currentRow = [];
|
|
212
|
-
currentCell = "";
|
|
213
|
-
hasAnyData = false;
|
|
214
|
-
lastCharWasSeparator = false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
hasAnyData = true;
|
|
219
|
-
lastCharWasSeparator = false;
|
|
220
|
-
currentCell += char;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (hasAnyData || currentRow.length > 0 || currentCell !== "" || lastCharWasSeparator) {
|
|
226
|
-
currentRow.push(currentCell);
|
|
227
|
-
rows.push(currentRow);
|
|
228
|
-
}
|
|
229
|
-
return rows;
|
|
230
|
-
}
|
|
231
|
-
function inferAndCoerceCSVColumn(values, options = {}) {
|
|
232
|
-
const nullValues = new Set(options.nullValues ?? ["", "NA", "null", "NaN"]);
|
|
233
|
-
const len = values.length;
|
|
234
|
-
let isAllBoolean = true;
|
|
235
|
-
let isAllNumber = true;
|
|
236
|
-
let isAllBigInt = true;
|
|
237
|
-
let isAllDate = true;
|
|
238
|
-
let hasValidData = false;
|
|
239
|
-
for (let i = 0; i < len; i++) {
|
|
240
|
-
const val = values[i].trim();
|
|
241
|
-
if (nullValues.has(val))
|
|
242
|
-
continue;
|
|
243
|
-
hasValidData = true;
|
|
244
|
-
if (isAllBoolean) {
|
|
245
|
-
const lower = val.toLowerCase();
|
|
246
|
-
if (lower !== "true" && lower !== "false" && lower !== "1" && lower !== "0") {
|
|
247
|
-
isAllBoolean = false;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
if (isAllBigInt) {
|
|
251
|
-
if ((0, number_1.toValidBigInt)(val, { truncate: false }) === null) {
|
|
252
|
-
isAllBigInt = false;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (isAllNumber) {
|
|
256
|
-
if ((0, number_1.toValidNumber)(val, { allowNonFiniteNumbers: true }) === null) {
|
|
257
|
-
isAllNumber = false;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
if (isAllDate) {
|
|
261
|
-
if ((0, date_1.toValidDate)(val) === null) {
|
|
262
|
-
isAllDate = false;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
// Fast exit if it's strictly a string column
|
|
266
|
-
if (!isAllBoolean && !isAllNumber && !isAllBigInt && !isAllDate) {
|
|
267
|
-
break;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
const out = new Array(len);
|
|
271
|
-
if (!hasValidData || (!isAllBoolean && !isAllNumber && !isAllBigInt && !isAllDate)) {
|
|
272
|
-
for (let i = 0; i < len; i++) {
|
|
273
|
-
const val = values[i];
|
|
274
|
-
out[i] = nullValues.has(val.trim()) ? null : val;
|
|
275
|
-
}
|
|
276
|
-
return { type: datatypes_1.Utf8, values: out };
|
|
277
|
-
}
|
|
278
|
-
if (isAllBoolean) {
|
|
279
|
-
for (let i = 0; i < len; i++) {
|
|
280
|
-
const val = values[i].trim();
|
|
281
|
-
if (nullValues.has(val)) {
|
|
282
|
-
out[i] = null;
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
const lower = val.toLowerCase();
|
|
286
|
-
out[i] = (lower === "true" || lower === "1");
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return { type: datatypes_1.Boolean, values: out };
|
|
290
|
-
}
|
|
291
|
-
if (isAllBigInt) {
|
|
292
|
-
for (let i = 0; i < len; i++) {
|
|
293
|
-
const val = values[i].trim();
|
|
294
|
-
out[i] = nullValues.has(val) ? null : (0, number_1.toValidBigInt)(val, { truncate: false });
|
|
295
|
-
}
|
|
296
|
-
return { type: datatypes_1.Int64, values: out };
|
|
297
|
-
}
|
|
298
|
-
if (isAllNumber) {
|
|
299
|
-
for (let i = 0; i < len; i++) {
|
|
300
|
-
const val = values[i].trim();
|
|
301
|
-
out[i] = nullValues.has(val) ? null : (0, number_1.toValidNumber)(val, { allowNonFiniteNumbers: true });
|
|
302
|
-
}
|
|
303
|
-
return { type: datatypes_1.Float64, values: out };
|
|
304
|
-
}
|
|
305
|
-
if (isAllDate) {
|
|
306
|
-
for (let i = 0; i < len; i++) {
|
|
307
|
-
const val = values[i].trim();
|
|
308
|
-
out[i] = nullValues.has(val) ? null : (0, date_1.toValidDate)(val);
|
|
309
|
-
}
|
|
310
|
-
return { type: datatypes_1.Datetime, values: out };
|
|
311
|
-
}
|
|
312
|
-
return { type: datatypes_1.Utf8, values: out };
|
|
313
|
-
}
|