@c9up/atom 0.1.11 → 0.1.12
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 +9 -1
- package/dist/Decimal.d.ts +8 -1
- package/dist/Decimal.d.ts.map +1 -1
- package/dist/Decimal.js +132 -96
- package/dist/Decimal.js.map +1 -1
- package/dist/Money.d.ts +15 -2
- package/dist/Money.d.ts.map +1 -1
- package/dist/Money.js +28 -3
- package/dist/Money.js.map +1 -1
- package/dist/atlas.d.ts +2 -5
- package/dist/atlas.d.ts.map +1 -1
- package/dist/atlas.js +2 -5
- package/dist/atlas.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -33
- package/dist/index.js.map +1 -1
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +3 -2
- package/scripts/build-napi-types.mjs +4 -3
- package/scripts/generate-napi-types.mjs +9 -6
- package/src/Decimal.ts +203 -134
- package/src/Money.ts +44 -5
- package/src/atlas.ts +2 -5
- package/src/index.ts +75 -36
package/src/index.ts
CHANGED
|
@@ -26,7 +26,11 @@ export type {
|
|
|
26
26
|
ToMinorUnitsOptions,
|
|
27
27
|
} from "./Decimal.js";
|
|
28
28
|
export { Decimal } from "./Decimal.js";
|
|
29
|
-
export type {
|
|
29
|
+
export type {
|
|
30
|
+
MoneyFormatOptions,
|
|
31
|
+
MoneyOptions,
|
|
32
|
+
MoneyRoundingOptions,
|
|
33
|
+
} from "./Money.js";
|
|
30
34
|
export { Money, money } from "./Money.js";
|
|
31
35
|
export { isNativeAvailable } from "./native.js";
|
|
32
36
|
|
|
@@ -46,13 +50,36 @@ function isDecimalIterable(value: unknown): value is Iterable<DecimalInput> {
|
|
|
46
50
|
);
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
/**
|
|
54
|
+
* What every aggregate accepts as one value.
|
|
55
|
+
*
|
|
56
|
+
* The variadic form used to be asserted back into shape — a claim about the
|
|
57
|
+
* caller's arguments made in the one place that can check them. Anything else
|
|
58
|
+
* reached `new Decimal(...)`, where an object failed as
|
|
59
|
+
* `input.trim is not a function`, naming neither the argument nor the call.
|
|
60
|
+
*/
|
|
61
|
+
function isDecimalValue(value: unknown): value is DecimalInput {
|
|
62
|
+
return (
|
|
63
|
+
Decimal.isDecimal(value) ||
|
|
64
|
+
typeof value === "string" ||
|
|
65
|
+
typeof value === "number" ||
|
|
66
|
+
typeof value === "bigint"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function toDecimalValue(value: unknown): DecimalInput {
|
|
71
|
+
if (isDecimalValue(value)) return value;
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Atom aggregates take a string, number, bigint or Decimal, got ${
|
|
74
|
+
value === null ? "null" : typeof value
|
|
75
|
+
}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function resolveValues(args: readonly unknown[]): Iterable<DecimalInput> {
|
|
80
|
+
const head = args[0];
|
|
81
|
+
if (args.length === 1 && isDecimalIterable(head)) return head;
|
|
82
|
+
return args.map(toDecimalValue);
|
|
56
83
|
}
|
|
57
84
|
|
|
58
85
|
function sumImpl(values: Iterable<DecimalInput>): Decimal {
|
|
@@ -77,25 +104,25 @@ function avgImpl(values: Iterable<DecimalInput>): Decimal {
|
|
|
77
104
|
}
|
|
78
105
|
|
|
79
106
|
function minImpl(values: Iterable<DecimalInput>): Decimal {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
107
|
+
const [first, ...rest] = [...values].map((value) => new Decimal(value));
|
|
108
|
+
if (first === undefined) {
|
|
82
109
|
throw new Error("Atom.min requires at least one value");
|
|
83
110
|
}
|
|
84
|
-
let best =
|
|
85
|
-
for (
|
|
86
|
-
if (
|
|
111
|
+
let best = first;
|
|
112
|
+
for (const candidate of rest) {
|
|
113
|
+
if (candidate.lt(best)) best = candidate;
|
|
87
114
|
}
|
|
88
115
|
return best;
|
|
89
116
|
}
|
|
90
117
|
|
|
91
118
|
function maxImpl(values: Iterable<DecimalInput>): Decimal {
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
119
|
+
const [first, ...rest] = [...values].map((value) => new Decimal(value));
|
|
120
|
+
if (first === undefined) {
|
|
94
121
|
throw new Error("Atom.max requires at least one value");
|
|
95
122
|
}
|
|
96
|
-
let best =
|
|
97
|
-
for (
|
|
98
|
-
if (
|
|
123
|
+
let best = first;
|
|
124
|
+
for (const candidate of rest) {
|
|
125
|
+
if (candidate.gt(best)) best = candidate;
|
|
99
126
|
}
|
|
100
127
|
return best;
|
|
101
128
|
}
|
|
@@ -110,9 +137,14 @@ function medianImpl(
|
|
|
110
137
|
}
|
|
111
138
|
list.sort((a, b) => a.cmp(b));
|
|
112
139
|
const mid = Math.floor(list.length / 2);
|
|
113
|
-
|
|
140
|
+
// The empty case threw above, so both halves of the middle are present.
|
|
141
|
+
const upper = list[mid];
|
|
142
|
+
if (upper === undefined) throw new Error("Atom.median lost its middle value");
|
|
143
|
+
if (list.length % 2 === 1) return upper;
|
|
144
|
+
const lower = list[mid - 1];
|
|
145
|
+
if (lower === undefined) throw new Error("Atom.median lost its middle value");
|
|
114
146
|
const precision = options.precision ?? defaultPrecision();
|
|
115
|
-
return
|
|
147
|
+
return lower.plus(upper).div("2", { precision });
|
|
116
148
|
}
|
|
117
149
|
|
|
118
150
|
function modeImpl(values: Iterable<DecimalInput>): Decimal[] {
|
|
@@ -162,32 +194,39 @@ function stddevImpl(
|
|
|
162
194
|
return variance.sqrt({ precision, mode });
|
|
163
195
|
}
|
|
164
196
|
|
|
197
|
+
/**
|
|
198
|
+
* The trailing options object of `median(values, options)` / `stddev(values,
|
|
199
|
+
* options)`, or `{}`.
|
|
200
|
+
*
|
|
201
|
+
* A `Decimal` is an object too, so excluding it is what lets the compiler
|
|
202
|
+
* check the narrowing instead of being told the answer.
|
|
203
|
+
*/
|
|
204
|
+
function optionsFrom<T extends MedianOptions | StddevOptions>(
|
|
205
|
+
value: DecimalInput | T | undefined,
|
|
206
|
+
): T | Record<string, never> {
|
|
207
|
+
if (typeof value !== "object" || value === null) return {};
|
|
208
|
+
if (Decimal.isDecimal(value)) return {};
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
|
|
165
212
|
function parseMedianArgs(
|
|
166
213
|
args: [Iterable<DecimalInput>, MedianOptions?] | DecimalInput[],
|
|
167
214
|
): { values: Iterable<DecimalInput>; options: MedianOptions } {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
args.length > 1 && typeof args[1] === "object" && args[1] !== null
|
|
172
|
-
? (args[1] as MedianOptions)
|
|
173
|
-
: {};
|
|
174
|
-
return { values, options };
|
|
215
|
+
const head = args[0];
|
|
216
|
+
if (isDecimalIterable(head)) {
|
|
217
|
+
return { values: head, options: optionsFrom<MedianOptions>(args[1]) };
|
|
175
218
|
}
|
|
176
|
-
return { values: args
|
|
219
|
+
return { values: resolveValues(args), options: {} };
|
|
177
220
|
}
|
|
178
221
|
|
|
179
222
|
function parseStddevArgs(
|
|
180
223
|
args: [Iterable<DecimalInput>, StddevOptions?] | DecimalInput[],
|
|
181
224
|
): { values: Iterable<DecimalInput>; options: StddevOptions } {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
args.length > 1 && typeof args[1] === "object" && args[1] !== null
|
|
186
|
-
? (args[1] as StddevOptions)
|
|
187
|
-
: {};
|
|
188
|
-
return { values, options };
|
|
225
|
+
const head = args[0];
|
|
226
|
+
if (isDecimalIterable(head)) {
|
|
227
|
+
return { values: head, options: optionsFrom<StddevOptions>(args[1]) };
|
|
189
228
|
}
|
|
190
|
-
return { values: args
|
|
229
|
+
return { values: resolveValues(args), options: {} };
|
|
191
230
|
}
|
|
192
231
|
|
|
193
232
|
function sumFn(...args: [Iterable<DecimalInput>] | DecimalInput[]): Decimal {
|