@parsrun/core 0.2.6 → 0.2.10
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/decimal.d.ts +79 -9
- package/dist/decimal.js +158 -76
- package/dist/decimal.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +158 -76
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/decimal.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import DecimalJS from 'decimal.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @parsrun/core - Decimal Utilities
|
|
3
5
|
* Precise decimal calculations for financial and quantity operations.
|
|
4
|
-
* Edge-compatible -
|
|
6
|
+
* Edge-compatible - wraps decimal.js for arbitrary precision arithmetic.
|
|
5
7
|
*
|
|
6
8
|
* @example
|
|
7
9
|
* ```typescript
|
|
@@ -15,14 +17,20 @@
|
|
|
15
17
|
* const total = price.mul(quantity).round(2);
|
|
16
18
|
* console.log(total.toString()); // '59.97'
|
|
17
19
|
*
|
|
20
|
+
* // Precision info
|
|
21
|
+
* const d = new Decimal('123.45');
|
|
22
|
+
* d.precision(); // 5 (total significant digits)
|
|
23
|
+
* d.decimalPlaces(); // 2 (digits after decimal point)
|
|
24
|
+
*
|
|
18
25
|
* // Static helpers
|
|
19
26
|
* const sum = Decimal.sum(['10.50', '20.25', '15.75']);
|
|
20
27
|
* const avg = Decimal.avg([100, 200, 300]);
|
|
21
28
|
* ```
|
|
22
29
|
*/
|
|
30
|
+
|
|
23
31
|
/**
|
|
24
32
|
* Decimal class for precise arithmetic operations.
|
|
25
|
-
*
|
|
33
|
+
* Wraps decimal.js to provide arbitrary precision decimal arithmetic.
|
|
26
34
|
*
|
|
27
35
|
* @example
|
|
28
36
|
* ```typescript
|
|
@@ -33,10 +41,8 @@
|
|
|
33
41
|
* ```
|
|
34
42
|
*/
|
|
35
43
|
declare class Decimal {
|
|
36
|
-
private
|
|
37
|
-
constructor(value: number | string | Decimal);
|
|
38
|
-
private normalizeNumber;
|
|
39
|
-
private normalizeString;
|
|
44
|
+
private readonly _value;
|
|
45
|
+
constructor(value: number | string | Decimal | DecimalJS);
|
|
40
46
|
/**
|
|
41
47
|
* Add another value to this decimal.
|
|
42
48
|
* @param other - Value to add
|
|
@@ -159,8 +165,39 @@ declare class Decimal {
|
|
|
159
165
|
* @returns True if value is negative
|
|
160
166
|
*/
|
|
161
167
|
isNegative(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Check if this decimal is an integer (no decimal places).
|
|
170
|
+
* @returns True if value is an integer
|
|
171
|
+
*/
|
|
172
|
+
isInteger(): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Get the number of decimal places (digits after the decimal point).
|
|
175
|
+
* @returns Number of decimal places
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* new Decimal('123.45').decimalPlaces(); // 2
|
|
180
|
+
* new Decimal('100').decimalPlaces(); // 0
|
|
181
|
+
* new Decimal('1.500').decimalPlaces(); // 1 (trailing zeros removed)
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
decimalPlaces(): number;
|
|
185
|
+
/**
|
|
186
|
+
* Get the precision (total number of significant digits).
|
|
187
|
+
* @param includeZeros - If true, include trailing zeros in the count
|
|
188
|
+
* @returns The precision
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```typescript
|
|
192
|
+
* new Decimal('123.45').precision(); // 5
|
|
193
|
+
* new Decimal('100').precision(); // 1
|
|
194
|
+
* new Decimal('100').precision(true); // 3
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
precision(includeZeros?: boolean): number;
|
|
162
198
|
/**
|
|
163
199
|
* Convert this decimal to a JavaScript number.
|
|
200
|
+
* Warning: May lose precision for very large or very precise numbers.
|
|
164
201
|
* @returns The numeric value
|
|
165
202
|
*/
|
|
166
203
|
toNumber(): number;
|
|
@@ -180,6 +217,12 @@ declare class Decimal {
|
|
|
180
217
|
* @returns The string value for JSON serialization
|
|
181
218
|
*/
|
|
182
219
|
toJSON(): string;
|
|
220
|
+
/**
|
|
221
|
+
* Get the underlying decimal.js instance.
|
|
222
|
+
* Useful for advanced operations not covered by this wrapper.
|
|
223
|
+
* @returns The underlying DecimalJS instance
|
|
224
|
+
*/
|
|
225
|
+
toDecimalJS(): DecimalJS;
|
|
183
226
|
/**
|
|
184
227
|
* Create a Decimal from a value (alias for constructor).
|
|
185
228
|
* @param value - The value to convert
|
|
@@ -212,6 +255,18 @@ declare class Decimal {
|
|
|
212
255
|
* @throws Error if no values provided
|
|
213
256
|
*/
|
|
214
257
|
static max(...values: (number | string | Decimal)[]): Decimal;
|
|
258
|
+
/**
|
|
259
|
+
* Check if a value is a valid decimal representation.
|
|
260
|
+
* @param value - The value to check
|
|
261
|
+
* @returns True if the value can be converted to a Decimal
|
|
262
|
+
*/
|
|
263
|
+
static isValid(value: unknown): boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Create a Decimal or return null if the value is invalid.
|
|
266
|
+
* @param value - The value to convert
|
|
267
|
+
* @returns A Decimal or null
|
|
268
|
+
*/
|
|
269
|
+
static tryParse(value: unknown): Decimal | null;
|
|
215
270
|
}
|
|
216
271
|
/**
|
|
217
272
|
* Utility functions for working with decimals in database operations.
|
|
@@ -296,12 +351,27 @@ declare const DecimalUtils: {
|
|
|
296
351
|
*/
|
|
297
352
|
prepareForDatabase<T extends Record<string, unknown>>(data: T, decimalFields: string[]): T;
|
|
298
353
|
/**
|
|
299
|
-
* Parse an object from database by converting decimal string fields to
|
|
354
|
+
* Parse an object from database by converting decimal string fields to Decimal instances.
|
|
300
355
|
* @param data - The object from database
|
|
301
|
-
* @param decimalFields - Array of field names that should be converted
|
|
302
|
-
* @returns A new object with specified fields converted to
|
|
356
|
+
* @param decimalFields - Array of field names that should be converted to Decimal
|
|
357
|
+
* @returns A new object with specified fields converted to Decimal instances
|
|
303
358
|
*/
|
|
304
359
|
parseFromDatabase<T extends Record<string, unknown>>(data: T, decimalFields: string[]): T;
|
|
360
|
+
/**
|
|
361
|
+
* Validate that a value matches the specified precision and scale.
|
|
362
|
+
* @param value - The value to validate
|
|
363
|
+
* @param precision - Total number of digits (integer + decimal)
|
|
364
|
+
* @param scale - Number of decimal places
|
|
365
|
+
* @returns An error message if invalid, or null if valid
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* DecimalUtils.validate('123.45', 5, 2); // null (valid)
|
|
370
|
+
* DecimalUtils.validate('123.456', 5, 2); // "max 2 decimal places allowed"
|
|
371
|
+
* DecimalUtils.validate('1234.56', 5, 2); // "max 3 integer digits allowed"
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
validate(value: number | string | Decimal, precision: number, scale: number): string | null;
|
|
305
375
|
};
|
|
306
376
|
/**
|
|
307
377
|
* Shorthand function for creating a Decimal instance.
|
package/dist/decimal.js
CHANGED
|
@@ -1,38 +1,30 @@
|
|
|
1
1
|
// src/decimal.ts
|
|
2
|
-
|
|
2
|
+
import DecimalJS from "decimal.js";
|
|
3
|
+
DecimalJS.set({
|
|
4
|
+
precision: 40,
|
|
5
|
+
rounding: DecimalJS.ROUND_HALF_UP,
|
|
6
|
+
toExpNeg: -9,
|
|
7
|
+
toExpPos: 21
|
|
8
|
+
});
|
|
3
9
|
var Decimal = class _Decimal {
|
|
4
|
-
|
|
10
|
+
_value;
|
|
5
11
|
constructor(value) {
|
|
6
12
|
if (value instanceof _Decimal) {
|
|
7
|
-
this.
|
|
8
|
-
} else if (
|
|
9
|
-
this.
|
|
13
|
+
this._value = value._value;
|
|
14
|
+
} else if (value instanceof DecimalJS) {
|
|
15
|
+
this._value = value;
|
|
10
16
|
} else {
|
|
11
|
-
this.
|
|
17
|
+
this._value = new DecimalJS(value);
|
|
12
18
|
}
|
|
13
19
|
}
|
|
14
|
-
normalizeNumber(n) {
|
|
15
|
-
if (!isFinite(n)) {
|
|
16
|
-
throw new Error(`Invalid number: ${n}`);
|
|
17
|
-
}
|
|
18
|
-
return n.toFixed(PRECISION).replace(/\.?0+$/, "") || "0";
|
|
19
|
-
}
|
|
20
|
-
normalizeString(s) {
|
|
21
|
-
const trimmed = s.trim();
|
|
22
|
-
if (!/^-?\d*\.?\d+$/.test(trimmed)) {
|
|
23
|
-
throw new Error(`Invalid decimal string: ${s}`);
|
|
24
|
-
}
|
|
25
|
-
return trimmed.replace(/^(-?)0+(?=\d)/, "$1").replace(/\.?0+$/, "") || "0";
|
|
26
|
-
}
|
|
27
20
|
/**
|
|
28
21
|
* Add another value to this decimal.
|
|
29
22
|
* @param other - Value to add
|
|
30
23
|
* @returns A new Decimal with the result
|
|
31
24
|
*/
|
|
32
25
|
add(other) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
return new _Decimal(a + b);
|
|
26
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
27
|
+
return new _Decimal(this._value.plus(otherValue));
|
|
36
28
|
}
|
|
37
29
|
/**
|
|
38
30
|
* Subtract a value from this decimal.
|
|
@@ -40,9 +32,8 @@ var Decimal = class _Decimal {
|
|
|
40
32
|
* @returns A new Decimal with the result
|
|
41
33
|
*/
|
|
42
34
|
sub(other) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return new _Decimal(a - b);
|
|
35
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
36
|
+
return new _Decimal(this._value.minus(otherValue));
|
|
46
37
|
}
|
|
47
38
|
/**
|
|
48
39
|
* Multiply this decimal by another value.
|
|
@@ -50,9 +41,8 @@ var Decimal = class _Decimal {
|
|
|
50
41
|
* @returns A new Decimal with the result
|
|
51
42
|
*/
|
|
52
43
|
mul(other) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
return new _Decimal(a * b);
|
|
44
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
45
|
+
return new _Decimal(this._value.times(otherValue));
|
|
56
46
|
}
|
|
57
47
|
/**
|
|
58
48
|
* Divide this decimal by another value.
|
|
@@ -61,12 +51,12 @@ var Decimal = class _Decimal {
|
|
|
61
51
|
* @throws Error if dividing by zero
|
|
62
52
|
*/
|
|
63
53
|
div(other) {
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
if (
|
|
54
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
55
|
+
const divisor = new DecimalJS(otherValue);
|
|
56
|
+
if (divisor.isZero()) {
|
|
67
57
|
throw new Error("Division by zero");
|
|
68
58
|
}
|
|
69
|
-
return new _Decimal(
|
|
59
|
+
return new _Decimal(this._value.dividedBy(divisor));
|
|
70
60
|
}
|
|
71
61
|
/**
|
|
72
62
|
* Get the modulo (remainder) of dividing this decimal by another value.
|
|
@@ -74,9 +64,8 @@ var Decimal = class _Decimal {
|
|
|
74
64
|
* @returns A new Decimal with the remainder
|
|
75
65
|
*/
|
|
76
66
|
mod(other) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
return new _Decimal(a % b);
|
|
67
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
68
|
+
return new _Decimal(this._value.modulo(otherValue));
|
|
80
69
|
}
|
|
81
70
|
/**
|
|
82
71
|
* Raise this decimal to a power.
|
|
@@ -84,8 +73,7 @@ var Decimal = class _Decimal {
|
|
|
84
73
|
* @returns A new Decimal with the result
|
|
85
74
|
*/
|
|
86
75
|
pow(exp) {
|
|
87
|
-
|
|
88
|
-
return new _Decimal(Math.pow(a, exp));
|
|
76
|
+
return new _Decimal(this._value.pow(exp));
|
|
89
77
|
}
|
|
90
78
|
/**
|
|
91
79
|
* Calculate the square root of this decimal.
|
|
@@ -93,27 +81,24 @@ var Decimal = class _Decimal {
|
|
|
93
81
|
* @throws Error if the value is negative
|
|
94
82
|
*/
|
|
95
83
|
sqrt() {
|
|
96
|
-
|
|
97
|
-
if (a < 0) {
|
|
84
|
+
if (this._value.isNegative()) {
|
|
98
85
|
throw new Error("Square root of negative number");
|
|
99
86
|
}
|
|
100
|
-
return new _Decimal(
|
|
87
|
+
return new _Decimal(this._value.sqrt());
|
|
101
88
|
}
|
|
102
89
|
/**
|
|
103
90
|
* Get the absolute value of this decimal.
|
|
104
91
|
* @returns A new Decimal with the absolute value
|
|
105
92
|
*/
|
|
106
93
|
abs() {
|
|
107
|
-
|
|
108
|
-
return new _Decimal(Math.abs(a));
|
|
94
|
+
return new _Decimal(this._value.abs());
|
|
109
95
|
}
|
|
110
96
|
/**
|
|
111
97
|
* Negate this decimal (multiply by -1).
|
|
112
98
|
* @returns A new Decimal with the negated value
|
|
113
99
|
*/
|
|
114
100
|
neg() {
|
|
115
|
-
|
|
116
|
-
return new _Decimal(-a);
|
|
101
|
+
return new _Decimal(this._value.negated());
|
|
117
102
|
}
|
|
118
103
|
/**
|
|
119
104
|
* Round to the specified number of decimal places using standard rounding.
|
|
@@ -121,9 +106,7 @@ var Decimal = class _Decimal {
|
|
|
121
106
|
* @returns A new Decimal with the rounded value
|
|
122
107
|
*/
|
|
123
108
|
round(decimals = 0) {
|
|
124
|
-
|
|
125
|
-
const factor = Math.pow(10, decimals);
|
|
126
|
-
return new _Decimal(Math.round(a * factor) / factor);
|
|
109
|
+
return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_HALF_UP));
|
|
127
110
|
}
|
|
128
111
|
/**
|
|
129
112
|
* Round down to the specified number of decimal places.
|
|
@@ -131,9 +114,7 @@ var Decimal = class _Decimal {
|
|
|
131
114
|
* @returns A new Decimal with the floored value
|
|
132
115
|
*/
|
|
133
116
|
floor(decimals = 0) {
|
|
134
|
-
|
|
135
|
-
const factor = Math.pow(10, decimals);
|
|
136
|
-
return new _Decimal(Math.floor(a * factor) / factor);
|
|
117
|
+
return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_FLOOR));
|
|
137
118
|
}
|
|
138
119
|
/**
|
|
139
120
|
* Round up to the specified number of decimal places.
|
|
@@ -141,9 +122,7 @@ var Decimal = class _Decimal {
|
|
|
141
122
|
* @returns A new Decimal with the ceiled value
|
|
142
123
|
*/
|
|
143
124
|
ceil(decimals = 0) {
|
|
144
|
-
|
|
145
|
-
const factor = Math.pow(10, decimals);
|
|
146
|
-
return new _Decimal(Math.ceil(a * factor) / factor);
|
|
125
|
+
return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_CEIL));
|
|
147
126
|
}
|
|
148
127
|
/**
|
|
149
128
|
* Compare this decimal to another value.
|
|
@@ -151,11 +130,8 @@ var Decimal = class _Decimal {
|
|
|
151
130
|
* @returns -1 if less, 0 if equal, 1 if greater
|
|
152
131
|
*/
|
|
153
132
|
cmp(other) {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
if (a < b) return -1;
|
|
157
|
-
if (a > b) return 1;
|
|
158
|
-
return 0;
|
|
133
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
134
|
+
return this._value.comparedTo(otherValue);
|
|
159
135
|
}
|
|
160
136
|
/**
|
|
161
137
|
* Check if this decimal equals another value.
|
|
@@ -163,7 +139,8 @@ var Decimal = class _Decimal {
|
|
|
163
139
|
* @returns True if values are equal
|
|
164
140
|
*/
|
|
165
141
|
eq(other) {
|
|
166
|
-
|
|
142
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
143
|
+
return this._value.equals(otherValue);
|
|
167
144
|
}
|
|
168
145
|
/**
|
|
169
146
|
* Check if this decimal is greater than another value.
|
|
@@ -171,7 +148,8 @@ var Decimal = class _Decimal {
|
|
|
171
148
|
* @returns True if this is greater
|
|
172
149
|
*/
|
|
173
150
|
gt(other) {
|
|
174
|
-
|
|
151
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
152
|
+
return this._value.greaterThan(otherValue);
|
|
175
153
|
}
|
|
176
154
|
/**
|
|
177
155
|
* Check if this decimal is greater than or equal to another value.
|
|
@@ -179,7 +157,8 @@ var Decimal = class _Decimal {
|
|
|
179
157
|
* @returns True if this is greater or equal
|
|
180
158
|
*/
|
|
181
159
|
gte(other) {
|
|
182
|
-
|
|
160
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
161
|
+
return this._value.greaterThanOrEqualTo(otherValue);
|
|
183
162
|
}
|
|
184
163
|
/**
|
|
185
164
|
* Check if this decimal is less than another value.
|
|
@@ -187,7 +166,8 @@ var Decimal = class _Decimal {
|
|
|
187
166
|
* @returns True if this is less
|
|
188
167
|
*/
|
|
189
168
|
lt(other) {
|
|
190
|
-
|
|
169
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
170
|
+
return this._value.lessThan(otherValue);
|
|
191
171
|
}
|
|
192
172
|
/**
|
|
193
173
|
* Check if this decimal is less than or equal to another value.
|
|
@@ -195,42 +175,80 @@ var Decimal = class _Decimal {
|
|
|
195
175
|
* @returns True if this is less or equal
|
|
196
176
|
*/
|
|
197
177
|
lte(other) {
|
|
198
|
-
|
|
178
|
+
const otherValue = other instanceof _Decimal ? other._value : other;
|
|
179
|
+
return this._value.lessThanOrEqualTo(otherValue);
|
|
199
180
|
}
|
|
200
181
|
/**
|
|
201
182
|
* Check if this decimal is exactly zero.
|
|
202
183
|
* @returns True if value is zero
|
|
203
184
|
*/
|
|
204
185
|
isZero() {
|
|
205
|
-
return
|
|
186
|
+
return this._value.isZero();
|
|
206
187
|
}
|
|
207
188
|
/**
|
|
208
189
|
* Check if this decimal is positive (greater than zero).
|
|
209
190
|
* @returns True if value is positive
|
|
210
191
|
*/
|
|
211
192
|
isPositive() {
|
|
212
|
-
return
|
|
193
|
+
return this._value.isPositive() && !this._value.isZero();
|
|
213
194
|
}
|
|
214
195
|
/**
|
|
215
196
|
* Check if this decimal is negative (less than zero).
|
|
216
197
|
* @returns True if value is negative
|
|
217
198
|
*/
|
|
218
199
|
isNegative() {
|
|
219
|
-
return
|
|
200
|
+
return this._value.isNegative();
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Check if this decimal is an integer (no decimal places).
|
|
204
|
+
* @returns True if value is an integer
|
|
205
|
+
*/
|
|
206
|
+
isInteger() {
|
|
207
|
+
return this._value.isInteger();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the number of decimal places (digits after the decimal point).
|
|
211
|
+
* @returns Number of decimal places
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* new Decimal('123.45').decimalPlaces(); // 2
|
|
216
|
+
* new Decimal('100').decimalPlaces(); // 0
|
|
217
|
+
* new Decimal('1.500').decimalPlaces(); // 1 (trailing zeros removed)
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
decimalPlaces() {
|
|
221
|
+
return this._value.decimalPlaces();
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Get the precision (total number of significant digits).
|
|
225
|
+
* @param includeZeros - If true, include trailing zeros in the count
|
|
226
|
+
* @returns The precision
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* new Decimal('123.45').precision(); // 5
|
|
231
|
+
* new Decimal('100').precision(); // 1
|
|
232
|
+
* new Decimal('100').precision(true); // 3
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
precision(includeZeros = false) {
|
|
236
|
+
return this._value.precision(includeZeros);
|
|
220
237
|
}
|
|
221
238
|
/**
|
|
222
239
|
* Convert this decimal to a JavaScript number.
|
|
240
|
+
* Warning: May lose precision for very large or very precise numbers.
|
|
223
241
|
* @returns The numeric value
|
|
224
242
|
*/
|
|
225
243
|
toNumber() {
|
|
226
|
-
return
|
|
244
|
+
return this._value.toNumber();
|
|
227
245
|
}
|
|
228
246
|
/**
|
|
229
247
|
* Convert this decimal to its string representation.
|
|
230
248
|
* @returns The string value
|
|
231
249
|
*/
|
|
232
250
|
toString() {
|
|
233
|
-
return this.
|
|
251
|
+
return this._value.toString();
|
|
234
252
|
}
|
|
235
253
|
/**
|
|
236
254
|
* Format this decimal with a fixed number of decimal places.
|
|
@@ -238,14 +256,22 @@ var Decimal = class _Decimal {
|
|
|
238
256
|
* @returns Formatted string
|
|
239
257
|
*/
|
|
240
258
|
toFixed(decimals = 2) {
|
|
241
|
-
return
|
|
259
|
+
return this._value.toFixed(decimals);
|
|
242
260
|
}
|
|
243
261
|
/**
|
|
244
262
|
* Convert to JSON (returns string representation for serialization).
|
|
245
263
|
* @returns The string value for JSON serialization
|
|
246
264
|
*/
|
|
247
265
|
toJSON() {
|
|
248
|
-
return this.
|
|
266
|
+
return this._value.toString();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get the underlying decimal.js instance.
|
|
270
|
+
* Useful for advanced operations not covered by this wrapper.
|
|
271
|
+
* @returns The underlying DecimalJS instance
|
|
272
|
+
*/
|
|
273
|
+
toDecimalJS() {
|
|
274
|
+
return this._value;
|
|
249
275
|
}
|
|
250
276
|
/**
|
|
251
277
|
* Create a Decimal from a value (alias for constructor).
|
|
@@ -301,6 +327,30 @@ var Decimal = class _Decimal {
|
|
|
301
327
|
return d.gt(max) ? d : max;
|
|
302
328
|
}, new _Decimal(values[0]));
|
|
303
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Check if a value is a valid decimal representation.
|
|
332
|
+
* @param value - The value to check
|
|
333
|
+
* @returns True if the value can be converted to a Decimal
|
|
334
|
+
*/
|
|
335
|
+
static isValid(value) {
|
|
336
|
+
if (value === null || value === void 0) return false;
|
|
337
|
+
if (value instanceof _Decimal) return true;
|
|
338
|
+
try {
|
|
339
|
+
new DecimalJS(value);
|
|
340
|
+
return true;
|
|
341
|
+
} catch {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Create a Decimal or return null if the value is invalid.
|
|
347
|
+
* @param value - The value to convert
|
|
348
|
+
* @returns A Decimal or null
|
|
349
|
+
*/
|
|
350
|
+
static tryParse(value) {
|
|
351
|
+
if (!_Decimal.isValid(value)) return null;
|
|
352
|
+
return new _Decimal(value);
|
|
353
|
+
}
|
|
304
354
|
};
|
|
305
355
|
var DecimalUtils = {
|
|
306
356
|
/**
|
|
@@ -393,30 +443,62 @@ var DecimalUtils = {
|
|
|
393
443
|
for (const field of decimalFields) {
|
|
394
444
|
if (field in result && result[field] !== void 0 && result[field] !== null) {
|
|
395
445
|
const value = result[field];
|
|
396
|
-
if (typeof value === "number") {
|
|
446
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
397
447
|
result[field] = DecimalUtils.toDecimalString(value);
|
|
448
|
+
} else if (value instanceof Decimal) {
|
|
449
|
+
result[field] = value.toString();
|
|
398
450
|
}
|
|
399
451
|
}
|
|
400
452
|
}
|
|
401
453
|
return result;
|
|
402
454
|
},
|
|
403
455
|
/**
|
|
404
|
-
* Parse an object from database by converting decimal string fields to
|
|
456
|
+
* Parse an object from database by converting decimal string fields to Decimal instances.
|
|
405
457
|
* @param data - The object from database
|
|
406
|
-
* @param decimalFields - Array of field names that should be converted
|
|
407
|
-
* @returns A new object with specified fields converted to
|
|
458
|
+
* @param decimalFields - Array of field names that should be converted to Decimal
|
|
459
|
+
* @returns A new object with specified fields converted to Decimal instances
|
|
408
460
|
*/
|
|
409
461
|
parseFromDatabase(data, decimalFields) {
|
|
410
462
|
const result = { ...data };
|
|
411
463
|
for (const field of decimalFields) {
|
|
412
464
|
if (field in result && result[field] !== void 0 && result[field] !== null) {
|
|
413
465
|
const value = result[field];
|
|
414
|
-
if (typeof value === "string") {
|
|
415
|
-
result[field] =
|
|
466
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
467
|
+
result[field] = new Decimal(value);
|
|
416
468
|
}
|
|
417
469
|
}
|
|
418
470
|
}
|
|
419
471
|
return result;
|
|
472
|
+
},
|
|
473
|
+
/**
|
|
474
|
+
* Validate that a value matches the specified precision and scale.
|
|
475
|
+
* @param value - The value to validate
|
|
476
|
+
* @param precision - Total number of digits (integer + decimal)
|
|
477
|
+
* @param scale - Number of decimal places
|
|
478
|
+
* @returns An error message if invalid, or null if valid
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```typescript
|
|
482
|
+
* DecimalUtils.validate('123.45', 5, 2); // null (valid)
|
|
483
|
+
* DecimalUtils.validate('123.456', 5, 2); // "max 2 decimal places allowed"
|
|
484
|
+
* DecimalUtils.validate('1234.56', 5, 2); // "max 3 integer digits allowed"
|
|
485
|
+
* ```
|
|
486
|
+
*/
|
|
487
|
+
validate(value, precision, scale) {
|
|
488
|
+
const d = value instanceof Decimal ? value : new Decimal(value);
|
|
489
|
+
const maxIntDigits = precision - scale;
|
|
490
|
+
if (d.decimalPlaces() > scale) {
|
|
491
|
+
return `max ${scale} decimal places allowed`;
|
|
492
|
+
}
|
|
493
|
+
const absValue = d.abs();
|
|
494
|
+
if (!absValue.isZero()) {
|
|
495
|
+
const integerPart = absValue.floor(0);
|
|
496
|
+
const intDigits = integerPart.isZero() ? 0 : integerPart.precision(true);
|
|
497
|
+
if (intDigits > maxIntDigits) {
|
|
498
|
+
return `max ${maxIntDigits} integer digits allowed`;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
420
502
|
}
|
|
421
503
|
};
|
|
422
504
|
function decimal(value) {
|