@wzo/calc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,449 @@
1
+ //#region src/utils/format.d.ts
2
+ /**
3
+ * Rounding strategy. Includes JS-style aliases: `'round'`≡`'halfUp'` (same as `Math.round`),
4
+ * `'trunc'`≡`'truncate'` (same as `Math.trunc`, truncate toward zero),
5
+ * `'halfEven'`≡`'banker'` (same as `Intl.NumberFormat` `roundingMode: 'halfEven'`, banker's rounding).
6
+ */
7
+ type Rounding = 'truncate' | 'trunc' | 'halfUp' | 'round' | 'banker' | 'halfEven' | 'ceil';
8
+ /**
9
+ * Format options object — passed to {@link fmt} / `calc`'s `_fmt` / chaining terminators.
10
+ * Equivalent to a format token string but with full type hints.
11
+ */
12
+ interface IFormat {
13
+ /** Decimal places: number = fixed (`=N`); object = range (`{ max }`≡`<=N`, `{ min }`≡`>=N`) */
14
+ decimals?: number | {
15
+ min?: number;
16
+ max?: number;
17
+ };
18
+ /** Rounding strategy (`~5`/`~6`/`~-`/`~+`) */
19
+ rounding?: Rounding;
20
+ /** Thousands separator: `true` = US style; or `'us'`/`'eu'`/`'in'` (≡ `,` / `!t:preset`) */
21
+ thousands?: boolean | 'us' | 'eu' | 'in';
22
+ /** Compact notation: `true` = K/M/B/T; or `'zh'` = 万/亿 (≡ `!c` / `!c:preset`) */
23
+ compact?: boolean | 'zh';
24
+ /** Clamp value to `[min, max]`; out-of-range values are clamped to the boundary (≡ `[min,max]`) */
25
+ clamp?: [number | string, number | string];
26
+ /** Output form (mutually exclusive): accepts human-readable words or token symbols (≡ `%%` / `//` / `!e` / `!n`) */
27
+ output?: 'percent' | '%%' | 'fraction' | '//' | 'scientific' | 'e' | 'number' | 'num';
28
+ /** Show explicit plus sign (≡ `+`) */
29
+ plus?: boolean;
30
+ /** Left-pad the integer part with zeros to N digits (≡ `!i:N`) */
31
+ pad?: number;
32
+ }
33
+ /** Options for {@link fmt}: formatting fields (see {@link IFormat}) plus `_`-prefixed control options */
34
+ interface IFmtOptions extends IFormat {
35
+ /** Error fallback value: defaults to the global `_error` (typically `'-'`). **Only `fmt` has a fallback */
36
+ _error?: string | number;
37
+ /** Division precision used when evaluating expressions (defaults to the global `_precision`) */
38
+ _precision?: number;
39
+ /** Enable unit mode (`%` etc., same as `calc`'s `_unit`) */
40
+ _unit?: boolean;
41
+ }
42
+ declare const fmt: (value: string | number | bigint, options?: IFmtOptions) => string | number;
43
+ //#endregion
44
+ //#region src/utils/config.d.ts
45
+ interface IGlobalConfig {
46
+ /** Fallback value on error: defaults to `'-'`; set to `0` to return `'0'` on error. */
47
+ _error: string | number;
48
+ /** Global default format ({@link IFormat} object). */
49
+ _fmt: IFormat | undefined;
50
+ /** Division precision (maximum decimal places). */
51
+ _precision: number;
52
+ }
53
+ /** Per-call precision override: optional last argument accepted by `div` / `divStr` / `chainDiv` / `calcAvg`. */
54
+ interface IPrecisionOption {
55
+ /** Division precision for this call, overrides the global `_precision` (does not affect the global config). */
56
+ _precision?: number;
57
+ }
58
+ /**
59
+ * Partially updates the global configuration (only the provided fields are overwritten).
60
+ *
61
+ * @param patch Configuration fields to update
62
+ * @example
63
+ * setConfig({ _precision: 10, _fmt: { decimals: 2 } })
64
+ */
65
+ declare const setConfig: (patch: Partial<IGlobalConfig>) => void;
66
+ /**
67
+ * Resets the global configuration to its default values.
68
+ *
69
+ * @example
70
+ * resetConfig()
71
+ */
72
+ declare const resetConfig: () => void;
73
+ /**
74
+ * Returns the current global configuration object (by reference — do not mutate directly; use {@link setConfig}).
75
+ *
76
+ * @returns The current {@link IGlobalConfig}
77
+ */
78
+ declare const getConfig: () => IGlobalConfig;
79
+ //#endregion
80
+ //#region src/utils/aggregate.d.ts
81
+ type Val$2 = string | number | bigint;
82
+ type Item = Record<string, Val$2 | null | undefined>;
83
+ /**
84
+ * Computes the sum. Accepts two call forms: a direct value array, or a field name with an array of objects.
85
+ *
86
+ * @param keyOrArr Value array (`[1, 2, 3]`) or the field name to sum (`'price'`)
87
+ * @param list Array of objects, required when the first argument is a field name
88
+ * @returns Total sum (`string`, high precision)
89
+ * @example
90
+ * calcSum([1, 2, 3]) // '6'
91
+ * calcSum('price', [{ price: 10 }, { price: 20 }]) // '30'
92
+ */
93
+ declare const calcSum: (keyOrArr: string | Val$2[], list?: Item[]) => string;
94
+ /**
95
+ * Computes the average (sum / count). Returns `'0'` for an empty collection.
96
+ *
97
+ * Precision defaults to the global `_precision`; pass `{ _precision }` as the **last** argument
98
+ * to override it for this call only (does not affect the global config).
99
+ *
100
+ * The first argument is either a value array (`[1,2,3]`) or a field name (`'price'`
101
+ * used together with an array of objects as the second argument).
102
+ *
103
+ * @returns Average value (`string`)
104
+ * @example
105
+ * calcAvg([1, 2, 3]) // '2'
106
+ * calcAvg('score', [{ score: 80 }, { score: 90 }]) // '85'
107
+ * calcAvg([10, 20, 25], { _precision: 2 }) // '18.33'
108
+ */
109
+ declare function calcAvg(arr: Val$2[], opt?: IPrecisionOption): string;
110
+ declare function calcAvg(key: string, list: Item[], opt?: IPrecisionOption): string;
111
+ /**
112
+ * Returns the maximum value (numeric comparison, not lexicographic).
113
+ *
114
+ * @param keyOrArr Value array or field name
115
+ * @param list Array of objects, required when the first argument is a field name
116
+ * @returns Maximum value (`string`); returns `'0'` for an empty collection
117
+ * @example
118
+ * calcMax([3, 10, 2]) // '10'
119
+ */
120
+ declare const calcMax: (keyOrArr: string | Val$2[], list?: Item[]) => string;
121
+ /**
122
+ * Returns the minimum value (numeric comparison).
123
+ *
124
+ * @param keyOrArr Value array or field name
125
+ * @param list Array of objects, required when the first argument is a field name
126
+ * @returns Minimum value (`string`); returns `'0'` for an empty collection
127
+ * @example
128
+ * calcMin([3, 10, 2]) // '2'
129
+ */
130
+ declare const calcMin: (keyOrArr: string | Val$2[], list?: Item[]) => string;
131
+ //#endregion
132
+ //#region src/utils/calc.d.ts
133
+ /** Control options for {@link calc} (all prefixed with `_`; variables are not supported — embed values via template interpolation) */
134
+ interface ICalcOptions {
135
+ /** true ⇒ enable unit mode (% is treated as a unit marker rather than division by 100; the result retains the % suffix) */
136
+ _unit?: boolean;
137
+ /** Explicit format: an {@link IFormat} options object */
138
+ _fmt?: IFormat;
139
+ /** Division precision (defaults to the global `_precision`) */
140
+ _precision?: number;
141
+ /**
142
+ * Step-by-step evaluation debug:
143
+ * - `true` ⇒ prints to console
144
+ * - pass a function ⇒ receives {@link IDebugInfo} via callback, no console output
145
+ */
146
+ _debug?: boolean | ((info: IDebugInfo) => void);
147
+ }
148
+ /** Evaluation info collected by `_debug` */
149
+ interface IDebugInfo {
150
+ /** The original expression */
151
+ expr: string;
152
+ /** Step-by-step evaluation trace (one entry per step) */
153
+ steps: string[];
154
+ /** Raw result before formatting */
155
+ value: string;
156
+ /** Final returned value */
157
+ result: string | number;
158
+ }
159
+ /**
160
+ * Main entry point: evaluates an arithmetic expression string and optionally formats the output.
161
+ *
162
+ * Expressions are pure arithmetic: the four basic operations, parentheses, and math functions
163
+ * (`max`/`min`/`clamp`…). **Variables are not supported** — embed values directly in the
164
+ * expression via template interpolation: `` calc(`${price} * ${qty}`) ``.
165
+ * Formatting is specified via `options._fmt` (an {@link IFormat} object).
166
+ *
167
+ * `calc` is designed for **computation**: on error (invalid expression, etc.) it **throws
168
+ * directly** and the caller is responsible for handling it.
169
+ * For **display** scenarios that need a fallback on error, use {@link fmt} instead
170
+ * (same API and supports arithmetic, but returns `_error` on failure rather than throwing).
171
+ *
172
+ * @param expr Arithmetic expression, e.g. `'1 + 2 * 3'`, `'(1 + 2) / 3'`
173
+ * @param options Control options (see {@link ICalcOptions})
174
+ * @returns Computation result (`string`; `number` when `_fmt.output` is `'number'`)
175
+ * @throws Throws when the expression is invalid
176
+ * @example
177
+ * calc('1 + 2 * 3') // '7'
178
+ * calc(`${price} * ${qty}`) // use template interpolation instead of variables
179
+ * calc('1 + 2', { _fmt: { decimals: 2 } }) // '3.00'
180
+ */
181
+ declare const calc: (expr: string, options?: ICalcOptions) => string | number;
182
+ //#endregion
183
+ //#region src/utils/chain.d.ts
184
+ type Val$1 = string | number | bigint;
185
+ /**
186
+ * A chaining computation object. Every arithmetic method returns itself for further chaining;
187
+ * calling it as a function terminates the chain and returns the result.
188
+ */
189
+ interface IChain {
190
+ /** Continues accumulating additions; returns itself for chaining. */
191
+ add: (...args: Val$1[]) => IChain;
192
+ /** Continues accumulating subtractions; returns itself. */
193
+ sub: (...args: Val$1[]) => IChain;
194
+ /** Continues accumulating multiplications; returns itself. */
195
+ mul: (...args: Val$1[]) => IChain;
196
+ /** Continues accumulating divisions (uses the instance's `_precision`); returns itself. */
197
+ div: (...args: Val$1[]) => IChain;
198
+ /**
199
+ * Terminates the chain and retrieves the result: no argument ⇒ returns the current value (`string`);
200
+ * pass an {@link IFormat} object ⇒ returns `string | number` according to the formatting rules.
201
+ */
202
+ (format?: IFormat): string | number;
203
+ }
204
+ /**
205
+ * Starts a chaining computation with addition (`a + b + c ...`).
206
+ *
207
+ * @param args Initial values to accumulate via addition
208
+ * @returns An {@link IChain} supporting further `.add().sub().mul().div()` calls
209
+ * @example
210
+ * chainAdd(1, 2).mul(3)() // '9'
211
+ * chainAdd(1, 2).mul(3)({ decimals: 2 }) // '9.00'
212
+ */
213
+ declare const chainAdd: (...args: Val$1[]) => IChain;
214
+ /**
215
+ * Starts a chaining computation with subtraction (`a - b - c ...`).
216
+ *
217
+ * @param args Initial minuend and subtrahends
218
+ * @returns An {@link IChain} supporting further chaining
219
+ * @example
220
+ * chainSub(10, 1, 2)() // '7'
221
+ */
222
+ declare const chainSub: (...args: Val$1[]) => IChain;
223
+ /**
224
+ * Starts a chaining computation with multiplication (`a * b * c ...`).
225
+ *
226
+ * @param args Initial factors to multiply together
227
+ * @returns An {@link IChain} supporting further chaining
228
+ * @example
229
+ * chainMul(2, 3).add(4)() // '10'
230
+ */
231
+ declare const chainMul: (...args: Val$1[]) => IChain;
232
+ /**
233
+ * Starts a chaining computation with division (`a / b / c ...`).
234
+ *
235
+ * Precision defaults to the global `_precision`; pass `{ _precision }` as the **last** argument
236
+ * to override the division precision for this chain (including subsequent `.div()` calls)
237
+ * without affecting the global config.
238
+ *
239
+ * @param args Initial dividend and divisors, with an optional {@link IPrecisionOption} at the end
240
+ * @returns An {@link IChain} supporting further chaining
241
+ * @example
242
+ * chainDiv(100, 4)() // '25'
243
+ * chainDiv(100, 3, { _precision: 5 })() // '33.33333'
244
+ */
245
+ declare function chainDiv(...args: Val$1[]): IChain;
246
+ declare function chainDiv(...args: [...Val$1[], IPrecisionOption]): IChain;
247
+ //#endregion
248
+ //#region src/utils/precision.d.ts
249
+ /** Internal decimal representation: a number = `sign * digits / 10^exp` */
250
+ interface IDecimal {
251
+ /** Sign: `1` for positive, `-1` for negative. */
252
+ sign: 1 | -1;
253
+ /** Significant digits as a non-negative integer (decimal point removed). */
254
+ digits: bigint;
255
+ /** Number of decimal places (negative exponent of `10`). */
256
+ exp: number;
257
+ }
258
+ /**
259
+ * Parses a string, number, or bigint into the internal {@link IDecimal} representation.
260
+ *
261
+ * Supports standard decimals (`"1.23"`, `-0.5`) and scientific notation (`"1.2e-3"`).
262
+ *
263
+ * @param input Value to parse, e.g. `"3.14"`, `42`, `-1n`, `"1e10"`
264
+ * @returns Parsed {@link IDecimal} (`digits` is always >= 0; sign is carried by `sign`)
265
+ * @throws When the string is not a valid number
266
+ * @example
267
+ * parse('1.23') // { sign: 1, digits: 123n, exp: 2 }
268
+ * parse('-5') // { sign: -1, digits: 5n, exp: 0 }
269
+ */
270
+ declare const parse: (input: string | number | bigint) => IDecimal;
271
+ /**
272
+ * High-precision division `a / b`, result rounded to `precision` decimal places (half-up).
273
+ *
274
+ * @param a Dividend
275
+ * @param b Divisor
276
+ * @param precision Maximum decimal places to retain, defaults to `50`
277
+ * @returns Canonical string of the quotient
278
+ * @throws When the divisor is zero
279
+ * @example
280
+ * div('1', '3') // '0.333...' (up to 50 places)
281
+ * div('1', '3', 4) // '0.3333'
282
+ */
283
+ declare const div$1: (a: string | number | bigint, b: string | number | bigint, precision?: number) => string;
284
+ /**
285
+ * Compares two numbers numerically.
286
+ *
287
+ * @param a Left operand
288
+ * @param b Right operand
289
+ * @returns `1` if `a > b`, `-1` if `a < b`, `0` if equal
290
+ * @example
291
+ * cmp('0.1', '0.2') // -1
292
+ * cmp('2', '2.0') // 0
293
+ */
294
+ declare const cmp: (a: string | number | bigint, b: string | number | bigint) => number;
295
+ /**
296
+ * Returns the negation `-a`.
297
+ *
298
+ * @param a Input value
299
+ * @returns Canonical string of the negation (`0` always returns `'0'`)
300
+ * @example
301
+ * neg('1.5') // '-1.5'
302
+ * neg('-2') // '2'
303
+ */
304
+ declare const neg: (a: string | number | bigint) => string;
305
+ /**
306
+ * Returns the absolute value `|a|`.
307
+ *
308
+ * @param a Input value
309
+ * @returns Canonical string of the absolute value
310
+ * @example
311
+ * abs('-3.14') // '3.14'
312
+ */
313
+ declare const abs: (a: string | number | bigint) => string;
314
+ /**
315
+ * Truncates to N decimal places by discarding excess digits — **no rounding**.
316
+ *
317
+ * @param a Input value
318
+ * @param decimals Number of decimal places to keep
319
+ * @returns Canonical string after truncation
320
+ * @example
321
+ * truncate('1.2349', 2) // '1.23'
322
+ * truncate('1.99', 0) // '1'
323
+ */
324
+ declare const truncate: (a: string | number | bigint, decimals: number) => string;
325
+ /**
326
+ * Rounds to N decimal places using half-up rounding (rounds up when digit `>= 0.5`).
327
+ *
328
+ * @param a Input value
329
+ * @param decimals Number of decimal places to keep
330
+ * @returns Canonical string after rounding
331
+ * @example
332
+ * roundHalfUp('1.235', 2) // '1.24'
333
+ * roundHalfUp('1.234', 2) // '1.23'
334
+ */
335
+ declare const roundHalfUp: (a: string | number | bigint, decimals: number) => string;
336
+ /**
337
+ * Rounds away from zero to N decimal places (rounds up whenever there is any remainder).
338
+ *
339
+ * @param a Input value
340
+ * @param decimals Number of decimal places to keep
341
+ * @returns Canonical string after rounding
342
+ * @example
343
+ * roundCeil('1.231', 2) // '1.24'
344
+ * roundCeil('-1.231', 2) // '-1.24'
345
+ */
346
+ declare const roundCeil: (a: string | number | bigint, decimals: number) => string;
347
+ /**
348
+ * Banker's rounding (round half to even): when the discarded portion is exactly `0.5`,
349
+ * rounds to the nearest even digit.
350
+ *
351
+ * @param a Input value
352
+ * @param decimals Number of decimal places to keep
353
+ * @returns Canonical string after rounding
354
+ * @example
355
+ * roundBanker('0.5', 0) // '0'
356
+ * roundBanker('1.5', 0) // '2'
357
+ * roundBanker('2.5', 0) // '2'
358
+ */
359
+ declare const roundBanker: (a: string | number | bigint, decimals: number) => string;
360
+ //#endregion
361
+ //#region src/utils/standalone.d.ts
362
+ type Val = string | number | bigint;
363
+ /** Division using the precision from the given config (shared by the default {@link div} export and per-call precision entry points). */
364
+
365
+ /**
366
+ * High-precision addition, result converted to `number` (convenient for interop with native numbers).
367
+ *
368
+ * @param args Any number of addends, accumulated left to right
369
+ * @returns Sum (`number`)
370
+ * @example
371
+ * add(0.1, 0.2) // 0.3
372
+ * add(1, 2, 3, 4) // 10
373
+ */
374
+ declare const add: (...args: Val[]) => number;
375
+ /**
376
+ * High-precision subtraction, result as `number`: `args[0] - args[1] - args[2] ...`.
377
+ *
378
+ * @param args Minuend followed by subtrahends
379
+ * @returns Difference (`number`)
380
+ * @example
381
+ * sub(0.3, 0.1) // 0.2
382
+ */
383
+ declare const sub: (...args: Val[]) => number;
384
+ /**
385
+ * High-precision multiplication, result as `number`, factors multiplied left to right.
386
+ *
387
+ * @param args Any number of factors
388
+ * @returns Product (`number`)
389
+ * @example
390
+ * mul(0.1, 0.2) // 0.02
391
+ */
392
+ declare const mul: (...args: Val[]) => number;
393
+ /**
394
+ * High-precision division, result as `number`: `args[0] / args[1] / args[2] ...`.
395
+ *
396
+ * Precision defaults to the global `_precision`; pass `{ _precision }` as the **last** argument
397
+ * to override it for this call only (does not affect the global config).
398
+ *
399
+ * @param args Dividend and divisors, with an optional {@link IPrecisionOption} at the end
400
+ * @returns Quotient (`number`)
401
+ * @example
402
+ * div(1, 3) // 0.333... (global precision)
403
+ * div(100, 3, { _precision: 5 }) // 33.33333
404
+ */
405
+ declare function div(...args: Val[]): number;
406
+ declare function div(...args: [...Val[], IPrecisionOption]): number;
407
+ /**
408
+ * High-precision addition, result returned as `string` (no precision loss; suitable for monetary values).
409
+ *
410
+ * @param args Any number of addends
411
+ * @returns Sum (`string`)
412
+ * @example
413
+ * addStr('0.1', '0.2') // '0.3'
414
+ */
415
+ declare const addStr: (...args: Val[]) => string;
416
+ /**
417
+ * High-precision subtraction, result as `string`: `args[0] - args[1] - ...`.
418
+ *
419
+ * @param args Minuend followed by subtrahends
420
+ * @returns Difference (`string`)
421
+ * @example
422
+ * subStr('0.3', '0.1') // '0.2'
423
+ */
424
+ declare const subStr: (...args: Val[]) => string;
425
+ /**
426
+ * High-precision multiplication, result as `string`, factors multiplied left to right.
427
+ *
428
+ * @param args Any number of factors
429
+ * @returns Product (`string`)
430
+ * @example
431
+ * mulStr('0.1', '0.2') // '0.02'
432
+ */
433
+ declare const mulStr: (...args: Val[]) => string;
434
+ /**
435
+ * High-precision division, result as `string`: `args[0] / args[1] / ...`.
436
+ *
437
+ * Precision defaults to the global `_precision`; pass `{ _precision }` as the **last** argument
438
+ * to override it for this call only (does not affect the global config).
439
+ *
440
+ * @param args Dividend and divisors, with an optional {@link IPrecisionOption} at the end
441
+ * @returns Quotient (`string`)
442
+ * @example
443
+ * divStr('1', '3') // '0.333...' (global precision)
444
+ * divStr('100', '3', { _precision: 5 }) // '33.33333'
445
+ */
446
+ declare function divStr(...args: Val[]): string;
447
+ declare function divStr(...args: [...Val[], IPrecisionOption]): string;
448
+ //#endregion
449
+ export { type ICalcOptions, type IChain, type IDebugInfo, type IDecimal, type IFmtOptions, type IFormat, type IGlobalConfig, type IPrecisionOption, type Rounding, abs, add, addStr, calc, calcAvg, calcMax, calcMin, calcSum, chainAdd, chainDiv, chainMul, chainSub, cmp, div, divStr, fmt, getConfig, mul, mulStr, neg, parse, div$1 as rawDiv, resetConfig, roundBanker, roundCeil, roundHalfUp, setConfig, sub, subStr, truncate };