df-script 1.4.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/LICENSE +21 -0
- package/README.md +269 -0
- package/dist/api.d.ts +39 -0
- package/dist/api.js +18 -0
- package/dist/bundle.min.js +1 -0
- package/dist/columnExpressions/ColumnExpr.d.ts +368 -0
- package/dist/columnExpressions/ColumnExpr.js +23 -0
- package/dist/columnExpressions/ExprBase.d.ts +24 -0
- package/dist/columnExpressions/ExprBase.js +133 -0
- package/dist/columnExpressions/constants.d.ts +2 -0
- package/dist/columnExpressions/constants.js +5 -0
- package/dist/columnExpressions/functions/all.d.ts +5 -0
- package/dist/columnExpressions/functions/all.js +11 -0
- package/dist/columnExpressions/functions/coalesce.d.ts +3 -0
- package/dist/columnExpressions/functions/coalesce.js +40 -0
- package/dist/columnExpressions/functions/exclude.d.ts +5 -0
- package/dist/columnExpressions/functions/exclude.js +13 -0
- package/dist/columnExpressions/functions/lit.d.ts +5 -0
- package/dist/columnExpressions/functions/lit.js +22 -0
- package/dist/columnExpressions/functions/when.d.ts +24 -0
- package/dist/columnExpressions/functions/when.js +81 -0
- package/dist/columnExpressions/index.d.ts +19 -0
- package/dist/columnExpressions/index.js +81 -0
- package/dist/columnExpressions/mixins/AggregationExpr.d.ts +50 -0
- package/dist/columnExpressions/mixins/AggregationExpr.js +172 -0
- package/dist/columnExpressions/mixins/ArithmeticExpr.d.ts +67 -0
- package/dist/columnExpressions/mixins/ArithmeticExpr.js +143 -0
- package/dist/columnExpressions/mixins/ComparisonExpr.d.ts +60 -0
- package/dist/columnExpressions/mixins/ComparisonExpr.js +389 -0
- package/dist/columnExpressions/mixins/ListExpr.d.ts +63 -0
- package/dist/columnExpressions/mixins/ListExpr.js +248 -0
- package/dist/columnExpressions/mixins/LogicalExpr.d.ts +33 -0
- package/dist/columnExpressions/mixins/LogicalExpr.js +54 -0
- package/dist/columnExpressions/mixins/ManipulationExpr.d.ts +31 -0
- package/dist/columnExpressions/mixins/ManipulationExpr.js +35 -0
- package/dist/columnExpressions/mixins/StringExpr.d.ts +79 -0
- package/dist/columnExpressions/mixins/StringExpr.js +249 -0
- package/dist/columnExpressions/mixins/TemporalExpr.d.ts +69 -0
- package/dist/columnExpressions/mixins/TemporalExpr.js +127 -0
- package/dist/columnExpressions/mixins/WindowExpr.d.ts +50 -0
- package/dist/columnExpressions/mixins/WindowExpr.js +281 -0
- package/dist/columnExpressions/types.d.ts +7 -0
- package/dist/columnExpressions/types.js +2 -0
- package/dist/dataframe/constants.d.ts +1 -0
- package/dist/dataframe/constants.js +4 -0
- package/dist/dataframe/dataframe.d.ts +42 -0
- package/dist/dataframe/dataframe.js +749 -0
- package/dist/dataframe/grouped/grouped.d.ts +15 -0
- package/dist/dataframe/grouped/grouped.js +113 -0
- package/dist/dataframe/index.d.ts +4 -0
- package/dist/dataframe/index.js +20 -0
- package/dist/dataframe/types.d.ts +33 -0
- package/dist/dataframe/types.js +2 -0
- package/dist/dataframe/utils.d.ts +11 -0
- package/dist/dataframe/utils.js +215 -0
- package/dist/datatypes/DataType.d.ts +40 -0
- package/dist/datatypes/DataType.js +47 -0
- package/dist/datatypes/index.d.ts +29 -0
- package/dist/datatypes/index.js +46 -0
- package/dist/datatypes/types/Binary.d.ts +9 -0
- package/dist/datatypes/types/Binary.js +18 -0
- package/dist/datatypes/types/Boolean.d.ts +9 -0
- package/dist/datatypes/types/Boolean.js +19 -0
- package/dist/datatypes/types/Date.d.ts +8 -0
- package/dist/datatypes/types/Date.js +21 -0
- package/dist/datatypes/types/Datetime.d.ts +8 -0
- package/dist/datatypes/types/Datetime.js +17 -0
- package/dist/datatypes/types/Decimal.d.ts +10 -0
- package/dist/datatypes/types/Decimal.js +28 -0
- package/dist/datatypes/types/Duration.d.ts +8 -0
- package/dist/datatypes/types/Duration.js +17 -0
- package/dist/datatypes/types/Float32.d.ts +8 -0
- package/dist/datatypes/types/Float32.js +17 -0
- package/dist/datatypes/types/Float64.d.ts +8 -0
- package/dist/datatypes/types/Float64.js +17 -0
- package/dist/datatypes/types/Int16.d.ts +8 -0
- package/dist/datatypes/types/Int16.js +17 -0
- package/dist/datatypes/types/Int32.d.ts +8 -0
- package/dist/datatypes/types/Int32.js +17 -0
- package/dist/datatypes/types/Int64.d.ts +8 -0
- package/dist/datatypes/types/Int64.js +17 -0
- package/dist/datatypes/types/Int8.d.ts +8 -0
- package/dist/datatypes/types/Int8.js +17 -0
- package/dist/datatypes/types/List.d.ts +10 -0
- package/dist/datatypes/types/List.js +31 -0
- package/dist/datatypes/types/Null.d.ts +9 -0
- package/dist/datatypes/types/Null.js +17 -0
- package/dist/datatypes/types/Object.d.ts +9 -0
- package/dist/datatypes/types/Object.js +17 -0
- package/dist/datatypes/types/Struct.d.ts +14 -0
- package/dist/datatypes/types/Struct.js +39 -0
- package/dist/datatypes/types/Time.d.ts +8 -0
- package/dist/datatypes/types/Time.js +29 -0
- package/dist/datatypes/types/UInt16.d.ts +8 -0
- package/dist/datatypes/types/UInt16.js +17 -0
- package/dist/datatypes/types/UInt32.d.ts +8 -0
- package/dist/datatypes/types/UInt32.js +17 -0
- package/dist/datatypes/types/UInt64.d.ts +8 -0
- package/dist/datatypes/types/UInt64.js +17 -0
- package/dist/datatypes/types/UInt8.d.ts +8 -0
- package/dist/datatypes/types/UInt8.js +17 -0
- package/dist/datatypes/types/Utf8.d.ts +10 -0
- package/dist/datatypes/types/Utf8.js +20 -0
- package/dist/datatypes/types.d.ts +172 -0
- package/dist/datatypes/types.js +286 -0
- package/dist/exceptions/index.d.ts +13 -0
- package/dist/exceptions/index.js +43 -0
- package/dist/exceptions/utils.d.ts +2 -0
- package/dist/exceptions/utils.js +9 -0
- package/dist/functions/concat.d.ts +4 -0
- package/dist/functions/concat.js +248 -0
- package/dist/functions/index.d.ts +1 -0
- package/dist/functions/index.js +17 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.js +2 -0
- package/dist/utils/boolean.d.ts +1 -0
- package/dist/utils/boolean.js +18 -0
- package/dist/utils/date.d.ts +57 -0
- package/dist/utils/date.js +349 -0
- package/dist/utils/guards.d.ts +14 -0
- package/dist/utils/guards.js +143 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/json.d.ts +2 -0
- package/dist/utils/json.js +33 -0
- package/dist/utils/list.d.ts +23 -0
- package/dist/utils/list.js +128 -0
- package/dist/utils/number.d.ts +86 -0
- package/dist/utils/number.js +223 -0
- package/dist/utils/string.d.ts +52 -0
- package/dist/utils/string.js +120 -0
- package/package.json +34 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toValidArray = toValidArray;
|
|
4
|
+
exports.isArrayOfType = isArrayOfType;
|
|
5
|
+
exports.sortList = sortList;
|
|
6
|
+
exports.getListStats = getListStats;
|
|
7
|
+
const guards_1 = require("./guards");
|
|
8
|
+
const date_1 = require("./date");
|
|
9
|
+
const number_1 = require("./number");
|
|
10
|
+
function toValidArray(val) {
|
|
11
|
+
if (val == null)
|
|
12
|
+
return [];
|
|
13
|
+
if (Array.isArray(val))
|
|
14
|
+
return val;
|
|
15
|
+
if ((0, guards_1.isTypedArray)(val))
|
|
16
|
+
return Array.from(val);
|
|
17
|
+
return [val];
|
|
18
|
+
}
|
|
19
|
+
function isArrayOfType(arr, type, { mode = "every", allowNulls = false, allowEmpty = true } = {}) {
|
|
20
|
+
if (!(0, guards_1.isArrayOrTypedArray)(arr))
|
|
21
|
+
return false;
|
|
22
|
+
const len = arr.length;
|
|
23
|
+
if (len === 0) {
|
|
24
|
+
if (!allowEmpty)
|
|
25
|
+
return false;
|
|
26
|
+
return mode === "every";
|
|
27
|
+
}
|
|
28
|
+
const check = (v) => {
|
|
29
|
+
if (v == null)
|
|
30
|
+
return allowNulls;
|
|
31
|
+
if (typeof type === "function") {
|
|
32
|
+
return (0, guards_1.isClass)(type) ? v instanceof type : type(v);
|
|
33
|
+
}
|
|
34
|
+
if (type === "date")
|
|
35
|
+
return (0, date_1.isValidDateObj)(v);
|
|
36
|
+
if (type === "object")
|
|
37
|
+
return (0, guards_1.isObj)(v);
|
|
38
|
+
if (type === "plainObject")
|
|
39
|
+
return (0, guards_1.isPlainObj)(v);
|
|
40
|
+
if (type === "number")
|
|
41
|
+
return (0, number_1.isValidNumber)(v);
|
|
42
|
+
return typeof v === type;
|
|
43
|
+
};
|
|
44
|
+
if (mode === "every") {
|
|
45
|
+
for (let i = 0; i < len; i++) {
|
|
46
|
+
if (!check(arr[i]))
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
for (let i = 0; i < len; i++) {
|
|
53
|
+
if (check(arr[i]))
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function sortList(arr, descending = false) {
|
|
60
|
+
if (!(0, guards_1.isArrayOrTypedArray)(arr))
|
|
61
|
+
return [];
|
|
62
|
+
const list = Array.from(arr);
|
|
63
|
+
list.sort((a, b) => {
|
|
64
|
+
if (a == null && b == null)
|
|
65
|
+
return 0;
|
|
66
|
+
if (a == null)
|
|
67
|
+
return 1;
|
|
68
|
+
if (b == null)
|
|
69
|
+
return -1;
|
|
70
|
+
if (a < b)
|
|
71
|
+
return descending ? 1 : -1;
|
|
72
|
+
if (a > b)
|
|
73
|
+
return descending ? -1 : 1;
|
|
74
|
+
return 0;
|
|
75
|
+
});
|
|
76
|
+
return list;
|
|
77
|
+
}
|
|
78
|
+
const DEFAULT_STATS = { sum: null, count: 0, min: null, max: null, mean: null, variance: 0, std: 0, nullCount: 0, len: 0, hasNulls: false, isNumeric: false };
|
|
79
|
+
function getListStats(arr) {
|
|
80
|
+
if (!(0, guards_1.isArrayOrTypedArray)(arr)) {
|
|
81
|
+
return { ...DEFAULT_STATS };
|
|
82
|
+
}
|
|
83
|
+
const len = arr.length;
|
|
84
|
+
if (len === 0) {
|
|
85
|
+
return { ...DEFAULT_STATS };
|
|
86
|
+
}
|
|
87
|
+
let minVal = null;
|
|
88
|
+
let maxVal = null;
|
|
89
|
+
let count = 0;
|
|
90
|
+
let nullCount = 0;
|
|
91
|
+
let total = 0;
|
|
92
|
+
let mean = 0;
|
|
93
|
+
let M2 = 0;
|
|
94
|
+
for (let i = 0; i < len; i++) {
|
|
95
|
+
const val = arr[i];
|
|
96
|
+
if (val == null) {
|
|
97
|
+
nullCount++;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (minVal == null || val < minVal)
|
|
101
|
+
minVal = val;
|
|
102
|
+
if (maxVal == null || val > maxVal)
|
|
103
|
+
maxVal = val;
|
|
104
|
+
const n = (0, number_1.toValidNumber)(val);
|
|
105
|
+
if (n !== null) {
|
|
106
|
+
total += n;
|
|
107
|
+
count++;
|
|
108
|
+
const delta = n - mean;
|
|
109
|
+
mean += delta / count;
|
|
110
|
+
const delta2 = n - mean;
|
|
111
|
+
M2 += delta * delta2;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const variance = count > 1 ? M2 / (count - 1) : 0;
|
|
115
|
+
return {
|
|
116
|
+
sum: count > 0 ? total : null,
|
|
117
|
+
count,
|
|
118
|
+
min: minVal,
|
|
119
|
+
max: maxVal,
|
|
120
|
+
mean: count > 0 ? total / count : null,
|
|
121
|
+
variance,
|
|
122
|
+
std: Math.sqrt(variance),
|
|
123
|
+
nullCount,
|
|
124
|
+
len,
|
|
125
|
+
hasNulls: nullCount > 0,
|
|
126
|
+
isNumeric: count > 0 && count === (len - nullCount)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export declare function isValidNumber(v: unknown): v is number;
|
|
2
|
+
export declare function toValidNumber(v: unknown): number | null;
|
|
3
|
+
export declare function clamp<T extends number | bigint>(opts: {
|
|
4
|
+
val: T;
|
|
5
|
+
min: T;
|
|
6
|
+
max: T;
|
|
7
|
+
}): T;
|
|
8
|
+
export type FloatPrecision = "Float32" | "Float64";
|
|
9
|
+
export declare const FLOAT_32_BOUNDARY = 3.4028234663852886e+38;
|
|
10
|
+
export declare const FLOAT_RANGES: {
|
|
11
|
+
readonly Float32: {
|
|
12
|
+
readonly min: number;
|
|
13
|
+
readonly max: 3.4028234663852886e+38;
|
|
14
|
+
};
|
|
15
|
+
readonly Float64: {
|
|
16
|
+
readonly min: number;
|
|
17
|
+
readonly max: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function isValidFloat(v: unknown, precision?: FloatPrecision): boolean;
|
|
21
|
+
export declare function toValidFloat(v: unknown, precision?: FloatPrecision): number | null;
|
|
22
|
+
export declare const INT_RANGES: {
|
|
23
|
+
readonly Int8: {
|
|
24
|
+
readonly min: -128;
|
|
25
|
+
readonly max: 127;
|
|
26
|
+
};
|
|
27
|
+
readonly Int16: {
|
|
28
|
+
readonly min: -32768;
|
|
29
|
+
readonly max: 32767;
|
|
30
|
+
};
|
|
31
|
+
readonly Int32: {
|
|
32
|
+
readonly min: -2147483648;
|
|
33
|
+
readonly max: 2147483647;
|
|
34
|
+
};
|
|
35
|
+
readonly UInt8: {
|
|
36
|
+
readonly min: 0;
|
|
37
|
+
readonly max: 255;
|
|
38
|
+
};
|
|
39
|
+
readonly UInt16: {
|
|
40
|
+
readonly min: 0;
|
|
41
|
+
readonly max: 65535;
|
|
42
|
+
};
|
|
43
|
+
readonly UInt32: {
|
|
44
|
+
readonly min: 0;
|
|
45
|
+
readonly max: 4294967295;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export type IntRangeType = keyof typeof INT_RANGES;
|
|
49
|
+
export type IntRange = {
|
|
50
|
+
min: number;
|
|
51
|
+
max: number;
|
|
52
|
+
} | IntRangeType;
|
|
53
|
+
export declare const BIGINT_RANGES: {
|
|
54
|
+
readonly Int64: {
|
|
55
|
+
readonly min: -9223372036854775808n;
|
|
56
|
+
readonly max: 9223372036854775807n;
|
|
57
|
+
};
|
|
58
|
+
readonly UInt64: {
|
|
59
|
+
readonly min: 0n;
|
|
60
|
+
readonly max: 18446744073709551615n;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
export type BigIntRangeType = keyof typeof BIGINT_RANGES;
|
|
64
|
+
export type BigIntRange = {
|
|
65
|
+
min: bigint;
|
|
66
|
+
max: bigint;
|
|
67
|
+
} | BigIntRangeType;
|
|
68
|
+
export type IntCoerceType = "round" | "floor" | "ceil" | "truncate";
|
|
69
|
+
export interface IntOptions {
|
|
70
|
+
coerce?: IntCoerceType;
|
|
71
|
+
}
|
|
72
|
+
export declare function isValidInt(v: unknown, range?: IntRange): v is number;
|
|
73
|
+
export declare function isValidBigInt(v: unknown, range?: BigIntRange): v is bigint;
|
|
74
|
+
export declare function toValidInt(v: unknown, range?: IntRange, opts?: IntOptions): number | null;
|
|
75
|
+
export declare function toValidBigInt(v: unknown, range?: BigIntRange): bigint | null;
|
|
76
|
+
export interface DecimalOptions {
|
|
77
|
+
precision?: number;
|
|
78
|
+
scale?: number;
|
|
79
|
+
}
|
|
80
|
+
export declare function isValidDecimal(v: unknown, opts?: DecimalOptions): boolean;
|
|
81
|
+
export declare function toValidDecimal(v: unknown, opts?: DecimalOptions): number | null;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a seedable pseudo-random number generator using the Mulberry32 PRNG algorithm.
|
|
84
|
+
* Returns a function that generates a pseudo-random float in the range [0, 1).
|
|
85
|
+
*/
|
|
86
|
+
export declare function mulberry32(seed: number): () => number;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BIGINT_RANGES = exports.INT_RANGES = exports.FLOAT_RANGES = exports.FLOAT_32_BOUNDARY = void 0;
|
|
4
|
+
exports.isValidNumber = isValidNumber;
|
|
5
|
+
exports.toValidNumber = toValidNumber;
|
|
6
|
+
exports.clamp = clamp;
|
|
7
|
+
exports.isValidFloat = isValidFloat;
|
|
8
|
+
exports.toValidFloat = toValidFloat;
|
|
9
|
+
exports.isValidInt = isValidInt;
|
|
10
|
+
exports.isValidBigInt = isValidBigInt;
|
|
11
|
+
exports.toValidInt = toValidInt;
|
|
12
|
+
exports.toValidBigInt = toValidBigInt;
|
|
13
|
+
exports.isValidDecimal = isValidDecimal;
|
|
14
|
+
exports.toValidDecimal = toValidDecimal;
|
|
15
|
+
exports.mulberry32 = mulberry32;
|
|
16
|
+
const NUMERIC_CLEAN_REGEX = /[,\s_]/g;
|
|
17
|
+
const VALID_DECIMAL_REGEX = /^[+-]?\d+(?:\.\d+)?$/;
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// /** Generic Number Helpers */
|
|
20
|
+
// ============================================================================
|
|
21
|
+
function isValidNumber(v) {
|
|
22
|
+
return typeof v === "number" && !Number.isNaN(v) && Number.isFinite(v);
|
|
23
|
+
}
|
|
24
|
+
function toValidNumber(v) {
|
|
25
|
+
if (v == null)
|
|
26
|
+
return null;
|
|
27
|
+
if (typeof v === "symbol")
|
|
28
|
+
return null;
|
|
29
|
+
if (isValidNumber(v)) {
|
|
30
|
+
return v;
|
|
31
|
+
}
|
|
32
|
+
if (typeof v === "boolean") {
|
|
33
|
+
return v ? 1 : 0;
|
|
34
|
+
}
|
|
35
|
+
if (typeof v === "bigint") {
|
|
36
|
+
const n = Number(v);
|
|
37
|
+
return isValidNumber(n) ? n : null;
|
|
38
|
+
}
|
|
39
|
+
if (v instanceof Date) {
|
|
40
|
+
const t = v.getTime();
|
|
41
|
+
return isValidNumber(t) ? t : null;
|
|
42
|
+
}
|
|
43
|
+
if (typeof v === "string") {
|
|
44
|
+
const clean = v.trim().replace(NUMERIC_CLEAN_REGEX, "");
|
|
45
|
+
if (clean === "")
|
|
46
|
+
return null;
|
|
47
|
+
const n = Number(clean);
|
|
48
|
+
return isValidNumber(n) ? n : null;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function clamp(opts) {
|
|
53
|
+
const { val, min, max } = opts;
|
|
54
|
+
if (val < min)
|
|
55
|
+
return min;
|
|
56
|
+
if (val > max)
|
|
57
|
+
return max;
|
|
58
|
+
return val;
|
|
59
|
+
}
|
|
60
|
+
exports.FLOAT_32_BOUNDARY = 3.4028234663852886e+38;
|
|
61
|
+
exports.FLOAT_RANGES = {
|
|
62
|
+
Float32: { min: -exports.FLOAT_32_BOUNDARY, max: exports.FLOAT_32_BOUNDARY },
|
|
63
|
+
Float64: { min: -Number.MAX_VALUE, max: Number.MAX_VALUE }
|
|
64
|
+
};
|
|
65
|
+
function isValidFloat(v, precision) {
|
|
66
|
+
if (!isValidNumber(v))
|
|
67
|
+
return false;
|
|
68
|
+
if (precision) {
|
|
69
|
+
const limits = exports.FLOAT_RANGES[precision];
|
|
70
|
+
return v >= limits.min && v <= limits.max;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
function toValidFloat(v, precision = "Float64") {
|
|
75
|
+
const num = toValidNumber(v);
|
|
76
|
+
if (num === null)
|
|
77
|
+
return null;
|
|
78
|
+
return precision === "Float32" ? Math.fround(num) : num;
|
|
79
|
+
}
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// /** Integer & BigInt Functions */
|
|
82
|
+
// ============================================================================
|
|
83
|
+
exports.INT_RANGES = {
|
|
84
|
+
Int8: { min: -128, max: 127 },
|
|
85
|
+
Int16: { min: -32768, max: 32767 },
|
|
86
|
+
Int32: { min: -2147483648, max: 2147483647 },
|
|
87
|
+
UInt8: { min: 0, max: 255 },
|
|
88
|
+
UInt16: { min: 0, max: 65535 },
|
|
89
|
+
UInt32: { min: 0, max: 4294967295 }
|
|
90
|
+
};
|
|
91
|
+
exports.BIGINT_RANGES = {
|
|
92
|
+
Int64: { min: -9223372036854775808n, max: 9223372036854775807n },
|
|
93
|
+
UInt64: { min: 0n, max: 18446744073709551615n }
|
|
94
|
+
};
|
|
95
|
+
function isValidInt(v, range) {
|
|
96
|
+
if (!isValidNumber(v))
|
|
97
|
+
return false;
|
|
98
|
+
if (!Number.isInteger(v))
|
|
99
|
+
return false;
|
|
100
|
+
if (!range)
|
|
101
|
+
return true;
|
|
102
|
+
const limits = typeof range === "string" ? exports.INT_RANGES[range] : range;
|
|
103
|
+
return v >= limits.min && v <= limits.max;
|
|
104
|
+
}
|
|
105
|
+
function isValidBigInt(v, range) {
|
|
106
|
+
if (typeof v !== "bigint")
|
|
107
|
+
return false;
|
|
108
|
+
if (!range)
|
|
109
|
+
return true;
|
|
110
|
+
const limits = typeof range === "string" ? exports.BIGINT_RANGES[range] : range;
|
|
111
|
+
return v >= limits.min && v <= limits.max;
|
|
112
|
+
}
|
|
113
|
+
function toValidInt(v, range = "Int32", opts = {}) {
|
|
114
|
+
const num = toValidNumber(v);
|
|
115
|
+
if (num === null)
|
|
116
|
+
return null;
|
|
117
|
+
let n = num;
|
|
118
|
+
const coerce = opts.coerce || "truncate";
|
|
119
|
+
switch (coerce) {
|
|
120
|
+
case "round":
|
|
121
|
+
n = Math.round(n);
|
|
122
|
+
break;
|
|
123
|
+
case "floor":
|
|
124
|
+
n = Math.floor(n);
|
|
125
|
+
break;
|
|
126
|
+
case "ceil":
|
|
127
|
+
n = Math.ceil(n);
|
|
128
|
+
break;
|
|
129
|
+
case "truncate":
|
|
130
|
+
n = Math.trunc(n);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
const limits = typeof range === "string" ? exports.INT_RANGES[range] : range;
|
|
134
|
+
return clamp({ val: n, min: limits.min, max: limits.max });
|
|
135
|
+
}
|
|
136
|
+
function toValidBigInt(v, range = "Int64") {
|
|
137
|
+
if (v == null)
|
|
138
|
+
return null;
|
|
139
|
+
if (typeof v === "symbol")
|
|
140
|
+
return null;
|
|
141
|
+
let bigintVal = null;
|
|
142
|
+
if (typeof v === "bigint") {
|
|
143
|
+
bigintVal = v;
|
|
144
|
+
}
|
|
145
|
+
else if (typeof v === "boolean") {
|
|
146
|
+
bigintVal = v ? 1n : 0n;
|
|
147
|
+
}
|
|
148
|
+
else if (typeof v === "string") {
|
|
149
|
+
const clean = v.trim().replace(NUMERIC_CLEAN_REGEX, "");
|
|
150
|
+
if (clean === "")
|
|
151
|
+
return null;
|
|
152
|
+
if (!VALID_DECIMAL_REGEX.test(clean)) {
|
|
153
|
+
const num = toValidNumber(v);
|
|
154
|
+
if (num === null)
|
|
155
|
+
return null;
|
|
156
|
+
bigintVal = BigInt(Math.trunc(num));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
bigintVal = BigInt(clean.split(".")[0]);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const num = toValidNumber(v);
|
|
164
|
+
if (num === null)
|
|
165
|
+
return null;
|
|
166
|
+
bigintVal = BigInt(Math.trunc(num));
|
|
167
|
+
}
|
|
168
|
+
const limits = typeof range === "string" ? exports.BIGINT_RANGES[range] : range;
|
|
169
|
+
return clamp({ val: bigintVal, min: limits.min, max: limits.max });
|
|
170
|
+
}
|
|
171
|
+
function isValidDecimal(v, opts = {}) {
|
|
172
|
+
if (!isValidNumber(v))
|
|
173
|
+
return false;
|
|
174
|
+
const { precision, scale = 0 } = opts;
|
|
175
|
+
if (precision !== undefined) {
|
|
176
|
+
const integerDigits = precision - scale;
|
|
177
|
+
const maxVal = Math.pow(10, integerDigits) - Math.pow(10, -scale);
|
|
178
|
+
if (integerDigits > 0 && Math.abs(v) > maxVal) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (scale !== undefined) {
|
|
183
|
+
const str = v.toString();
|
|
184
|
+
const dotIdx = str.indexOf(".");
|
|
185
|
+
if (dotIdx !== -1 && str.slice(dotIdx + 1).length > scale) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
function toValidDecimal(v, opts = {}) {
|
|
192
|
+
const num = toValidNumber(v);
|
|
193
|
+
if (num === null)
|
|
194
|
+
return null;
|
|
195
|
+
const { precision, scale } = opts;
|
|
196
|
+
let n = num;
|
|
197
|
+
if (scale !== undefined) {
|
|
198
|
+
const multiplier = Math.pow(10, scale);
|
|
199
|
+
n = Math.round(n * multiplier) / multiplier;
|
|
200
|
+
}
|
|
201
|
+
if (precision !== undefined) {
|
|
202
|
+
const scaleVal = scale || 0;
|
|
203
|
+
const integerDigits = precision - scaleVal;
|
|
204
|
+
if (integerDigits > 0) {
|
|
205
|
+
const maxVal = Math.pow(10, integerDigits) - Math.pow(10, -scaleVal);
|
|
206
|
+
n = clamp({ val: n, min: -maxVal, max: maxVal });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return n;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates a seedable pseudo-random number generator using the Mulberry32 PRNG algorithm.
|
|
213
|
+
* Returns a function that generates a pseudo-random float in the range [0, 1).
|
|
214
|
+
*/
|
|
215
|
+
function mulberry32(seed) {
|
|
216
|
+
let s = seed | 0;
|
|
217
|
+
return function () {
|
|
218
|
+
let t = s = (s + 0x6D2B79F5) | 0;
|
|
219
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
220
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
221
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
222
|
+
};
|
|
223
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type StripMode = "both" | "start" | "end";
|
|
2
|
+
export type StripCharsOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* The strip mode: "both" (default), "start", or "end".
|
|
5
|
+
*/
|
|
6
|
+
mode?: StripMode;
|
|
7
|
+
/**
|
|
8
|
+
* If true, returns an empty string instead of null when the result is empty or input is null.
|
|
9
|
+
*/
|
|
10
|
+
returnStringOnNull?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The maximum number of non-matching characters allowed to be skipped from the start
|
|
13
|
+
* before a match block is found. Passing -1 or null means scan the full length.
|
|
14
|
+
*/
|
|
15
|
+
maxScanStart?: number | null;
|
|
16
|
+
/**
|
|
17
|
+
* The maximum number of non-matching characters allowed to be skipped from the end
|
|
18
|
+
* before a match block is found. Passing -1 or null means scan the full length.
|
|
19
|
+
*/
|
|
20
|
+
maxScanEnd?: number | null;
|
|
21
|
+
/**
|
|
22
|
+
* The maximum number of non-contiguous matching blocks allowed to be stripped from the start.
|
|
23
|
+
* Passing -1 or null means strip all matching blocks.
|
|
24
|
+
*/
|
|
25
|
+
maxMatchesStart?: number | null;
|
|
26
|
+
/**
|
|
27
|
+
* The maximum number of non-contiguous matching blocks allowed to be stripped from the end.
|
|
28
|
+
* Passing -1 or null means strip all matching blocks.
|
|
29
|
+
*/
|
|
30
|
+
maxMatchesEnd?: number | null;
|
|
31
|
+
/**
|
|
32
|
+
* If true, trims standard whitespace first before performing character stripping.
|
|
33
|
+
*/
|
|
34
|
+
trimFirst?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Options that apply only when the characters parameter is a string (and not a RegExp).
|
|
37
|
+
*/
|
|
38
|
+
stringOptions?: {
|
|
39
|
+
/**
|
|
40
|
+
* If true, treats the characters string as a literal substring rather than a set of characters.
|
|
41
|
+
*/
|
|
42
|
+
literal?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* If true, performs case-insensitive character and substring matching.
|
|
45
|
+
*/
|
|
46
|
+
caseInsensitive?: boolean;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Strips characters from the start, end, or both ends of a string.
|
|
51
|
+
*/
|
|
52
|
+
export declare function stripChars(str: string | null | undefined, characters?: string | RegExp | null, { mode, returnStringOnNull, maxScanStart, maxScanEnd, maxMatchesStart, maxMatchesEnd, trimFirst, stringOptions: { literal, caseInsensitive } }?: StripCharsOptions): string | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stripChars = stripChars;
|
|
4
|
+
/**
|
|
5
|
+
* Strips characters from the start, end, or both ends of a string.
|
|
6
|
+
*/
|
|
7
|
+
function stripChars(str, characters = null, { mode = "both", returnStringOnNull = false, maxScanStart = 1, maxScanEnd = 1, maxMatchesStart = 1, maxMatchesEnd = 1, trimFirst = false, stringOptions: { literal = false, caseInsensitive = false } = {} } = {}) {
|
|
8
|
+
if (str == null) {
|
|
9
|
+
return returnStringOnNull ? "" : null;
|
|
10
|
+
}
|
|
11
|
+
const trimString = (s, m = "both") => {
|
|
12
|
+
if (m === "start")
|
|
13
|
+
return s.trimStart();
|
|
14
|
+
if (m === "end")
|
|
15
|
+
return s.trimEnd();
|
|
16
|
+
return s.trim();
|
|
17
|
+
};
|
|
18
|
+
let workStr = str;
|
|
19
|
+
if (trimFirst && characters != null) {
|
|
20
|
+
workStr = trimString(str, mode);
|
|
21
|
+
}
|
|
22
|
+
if (characters == null) {
|
|
23
|
+
const result = trimString(workStr, mode);
|
|
24
|
+
return (returnStringOnNull || result !== "") ? result : null;
|
|
25
|
+
}
|
|
26
|
+
const matches = characters instanceof RegExp
|
|
27
|
+
? (char) => characters.test(char)
|
|
28
|
+
: (() => {
|
|
29
|
+
const targetSet = new Set(caseInsensitive ? characters.toLowerCase() : characters);
|
|
30
|
+
return (char) => targetSet.has(caseInsensitive ? char.toLowerCase() : char);
|
|
31
|
+
})();
|
|
32
|
+
const len = workStr.length;
|
|
33
|
+
const stripped = new Uint8Array(len);
|
|
34
|
+
const scanNonLiteral = ({ isStart, limit, maxMatches }) => {
|
|
35
|
+
if (len === 0 || maxMatches === 0) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const start = isStart ? 0 : len - 1;
|
|
39
|
+
const end = isStart ? len : -1;
|
|
40
|
+
const step = isStart ? 1 : -1;
|
|
41
|
+
let inBlock = false;
|
|
42
|
+
let matchesFound = 0;
|
|
43
|
+
let totalSkipped = 0;
|
|
44
|
+
for (let i = start; i !== end; i += step) {
|
|
45
|
+
if (matches(workStr[i])) {
|
|
46
|
+
if (!inBlock) {
|
|
47
|
+
if (limit !== null && limit >= 0 && totalSkipped >= limit) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (maxMatches !== null && maxMatches >= 0 && matchesFound >= maxMatches) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
inBlock = true;
|
|
54
|
+
matchesFound++;
|
|
55
|
+
}
|
|
56
|
+
stripped[i] = 1;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
inBlock = false;
|
|
60
|
+
totalSkipped++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const scanLiteral = ({ isStart, limit, maxMatches }) => {
|
|
65
|
+
if (len === 0 || maxMatches === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const patLen = characters.length;
|
|
69
|
+
if (patLen === 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const searchStr = caseInsensitive ? workStr.toLowerCase() : workStr;
|
|
73
|
+
const patStr = caseInsensitive ? characters.toLowerCase() : characters;
|
|
74
|
+
let currentIdx = isStart ? 0 : len - 1;
|
|
75
|
+
let matchesFound = 0;
|
|
76
|
+
let totalSkipped = 0;
|
|
77
|
+
while (currentIdx >= 0 && currentIdx < len) {
|
|
78
|
+
if (maxMatches !== null && maxMatches >= 0 && matchesFound >= maxMatches) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
const searchStart = isStart ? currentIdx : (currentIdx - patLen + 1);
|
|
82
|
+
if (!isStart && searchStart < 0) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
const matchIdx = isStart
|
|
86
|
+
? searchStr.indexOf(patStr, searchStart)
|
|
87
|
+
: searchStr.lastIndexOf(patStr, searchStart);
|
|
88
|
+
if (matchIdx === -1) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
const skippedInThisStep = isStart
|
|
92
|
+
? (matchIdx - currentIdx)
|
|
93
|
+
: (currentIdx - (matchIdx + patLen - 1));
|
|
94
|
+
totalSkipped += skippedInThisStep;
|
|
95
|
+
if (limit !== null && limit >= 0 && totalSkipped >= limit) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
for (let i = 0; i < patLen; i++) {
|
|
99
|
+
stripped[matchIdx + i] = 1;
|
|
100
|
+
}
|
|
101
|
+
matchesFound++;
|
|
102
|
+
currentIdx = isStart ? (matchIdx + patLen) : (matchIdx - 1);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const isLiteral = literal && typeof characters === "string";
|
|
106
|
+
const scan = isLiteral ? scanLiteral : scanNonLiteral;
|
|
107
|
+
if (mode === "both" || mode === "start") {
|
|
108
|
+
scan({ isStart: true, limit: maxScanStart, maxMatches: maxMatchesStart });
|
|
109
|
+
}
|
|
110
|
+
if (mode === "both" || mode === "end") {
|
|
111
|
+
scan({ isStart: false, limit: maxScanEnd, maxMatches: maxMatchesEnd });
|
|
112
|
+
}
|
|
113
|
+
let result = "";
|
|
114
|
+
for (let i = 0; i < len; i++) {
|
|
115
|
+
if (stripped[i] === 0) {
|
|
116
|
+
result += workStr[i];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return (returnStringOnNull || result !== "") ? result : null;
|
|
120
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "df-script",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "A zero-dependency, high-performance, expression-based DataFrame library for TypeScript/JavaScript.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"LICENSE",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && esbuild src/index.ts --bundle --minify --outfile=dist/index.js --platform=node",
|
|
14
|
+
"test": "tsx _tests/run_all_project_tests.ts",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"dataframe",
|
|
19
|
+
"polars",
|
|
20
|
+
"pandas",
|
|
21
|
+
"data-analysis",
|
|
22
|
+
"typescript",
|
|
23
|
+
"columnar",
|
|
24
|
+
"data-science",
|
|
25
|
+
"zero-dependency"
|
|
26
|
+
],
|
|
27
|
+
"author": "Trent Morris",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^5.4.5",
|
|
31
|
+
"tsx": "^4.15.5",
|
|
32
|
+
"@types/node": "^20.14.2"
|
|
33
|
+
}
|
|
34
|
+
}
|