@stripe/extensibility-sdk 0.22.4
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.md +19 -0
- package/dist/config-values/generate.cjs +262 -0
- package/dist/config-values/generate.d.ts +38 -0
- package/dist/config-values/generate.d.ts.map +1 -0
- package/dist/config-values/generate.js +232 -0
- package/dist/config-values/parse.d.ts +87 -0
- package/dist/config-values/parse.d.ts.map +1 -0
- package/dist/extensibility-sdk-alpha.d.ts +542 -0
- package/dist/extensibility-sdk-beta.d.ts +542 -0
- package/dist/extensibility-sdk-config-values-alpha.d.ts +27 -0
- package/dist/extensibility-sdk-config-values-beta.d.ts +27 -0
- package/dist/extensibility-sdk-config-values-internal.d.ts +118 -0
- package/dist/extensibility-sdk-config-values-public.d.ts +27 -0
- package/dist/extensibility-sdk-extensions-alpha.d.ts +1592 -0
- package/dist/extensibility-sdk-extensions-beta.d.ts +1592 -0
- package/dist/extensibility-sdk-extensions-internal.d.ts +1655 -0
- package/dist/extensibility-sdk-extensions-public.d.ts +1592 -0
- package/dist/extensibility-sdk-internal-alpha.d.ts +9 -0
- package/dist/extensibility-sdk-internal-beta.d.ts +9 -0
- package/dist/extensibility-sdk-internal-internal.d.ts +23 -0
- package/dist/extensibility-sdk-internal-public.d.ts +9 -0
- package/dist/extensibility-sdk-internal.d.ts +915 -0
- package/dist/extensibility-sdk-jsonschema-alpha.d.ts +3 -0
- package/dist/extensibility-sdk-jsonschema-beta.d.ts +3 -0
- package/dist/extensibility-sdk-jsonschema-internal.d.ts +15 -0
- package/dist/extensibility-sdk-jsonschema-public.d.ts +3 -0
- package/dist/extensibility-sdk-public.d.ts +542 -0
- package/dist/extensibility-sdk-stdlib-alpha.d.ts +531 -0
- package/dist/extensibility-sdk-stdlib-beta.d.ts +531 -0
- package/dist/extensibility-sdk-stdlib-internal.d.ts +904 -0
- package/dist/extensibility-sdk-stdlib-public.d.ts +531 -0
- package/dist/extensions/billing/bill/discount_calculation.d.ts +226 -0
- package/dist/extensions/billing/bill/discount_calculation.d.ts.map +1 -0
- package/dist/extensions/billing/bill/index.d.ts +2 -0
- package/dist/extensions/billing/bill/index.d.ts.map +1 -0
- package/dist/extensions/billing/customer_balance_application.d.ts +82 -0
- package/dist/extensions/billing/customer_balance_application.d.ts.map +1 -0
- package/dist/extensions/billing/index.d.ts +8 -0
- package/dist/extensions/billing/index.d.ts.map +1 -0
- package/dist/extensions/billing/invoice_collection_setting.d.ts +117 -0
- package/dist/extensions/billing/invoice_collection_setting.d.ts.map +1 -0
- package/dist/extensions/billing/prorations.d.ts +222 -0
- package/dist/extensions/billing/prorations.d.ts.map +1 -0
- package/dist/extensions/billing/recurring_billing_item_handling.d.ts +326 -0
- package/dist/extensions/billing/recurring_billing_item_handling.d.ts.map +1 -0
- package/dist/extensions/billing/types.d.ts +33 -0
- package/dist/extensions/billing/types.d.ts.map +1 -0
- package/dist/extensions/context.d.ts +9 -0
- package/dist/extensions/context.d.ts.map +1 -0
- package/dist/extensions/core/index.d.ts +3 -0
- package/dist/extensions/core/index.d.ts.map +1 -0
- package/dist/extensions/core/workflows/custom_action.d.ts +142 -0
- package/dist/extensions/core/workflows/custom_action.d.ts.map +1 -0
- package/dist/extensions/core/workflows/index.d.ts +2 -0
- package/dist/extensions/core/workflows/index.d.ts.map +1 -0
- package/dist/extensions/extend/index.d.ts +3 -0
- package/dist/extensions/extend/index.d.ts.map +1 -0
- package/dist/extensions/extend/workflows/custom_action.d.ts +142 -0
- package/dist/extensions/extend/workflows/custom_action.d.ts.map +1 -0
- package/dist/extensions/extend/workflows/index.d.ts +2 -0
- package/dist/extensions/extend/workflows/index.d.ts.map +1 -0
- package/dist/extensions/index.cjs +2356 -0
- package/dist/extensions/index.d.ts +9 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +2435 -0
- package/dist/extensions/registry.d.ts +19 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/types.d.ts +10 -0
- package/dist/extensions/types.d.ts.map +1 -0
- package/dist/index.cjs +1519 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1460 -0
- package/dist/internal.cjs +156 -0
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +128 -0
- package/dist/jsonschema.cjs +18 -0
- package/dist/jsonschema.d.ts +2 -0
- package/dist/jsonschema.d.ts.map +1 -0
- package/dist/jsonschema.js +0 -0
- package/dist/stdlib/brand.d.ts +27 -0
- package/dist/stdlib/brand.d.ts.map +1 -0
- package/dist/stdlib/decimal.d.ts +324 -0
- package/dist/stdlib/decimal.d.ts.map +1 -0
- package/dist/stdlib/extension-method.d.ts +27 -0
- package/dist/stdlib/extension-method.d.ts.map +1 -0
- package/dist/stdlib/generated.d.ts +15 -0
- package/dist/stdlib/generated.d.ts.map +1 -0
- package/dist/stdlib/index.cjs +1519 -0
- package/dist/stdlib/index.d.ts +18 -0
- package/dist/stdlib/index.d.ts.map +1 -0
- package/dist/stdlib/index.js +1460 -0
- package/dist/stdlib/refs.d.ts +62 -0
- package/dist/stdlib/refs.d.ts.map +1 -0
- package/dist/stdlib/scalars.d.ts +141 -0
- package/dist/stdlib/scalars.d.ts.map +1 -0
- package/dist/stdlib/transform-strategies.d.ts +74 -0
- package/dist/stdlib/transform-strategies.d.ts.map +1 -0
- package/dist/stdlib/transforms.d.ts +97 -0
- package/dist/stdlib/transforms.d.ts.map +1 -0
- package/dist/stdlib/type-utils.d.ts +9 -0
- package/dist/stdlib/type-utils.d.ts.map +1 -0
- package/dist/stdlib/types.d.ts +281 -0
- package/dist/stdlib/types.d.ts.map +1 -0
- package/dist/stdlib/utils.d.ts +7 -0
- package/dist/stdlib/utils.d.ts.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +111 -0
- package/tslibs/5.9.3/lib.es2022.egress.d.ts +4328 -0
- package/tslibs/5.9.3/lib.es2022.restricted.d.ts +4067 -0
- package/tslibs/lib.egress.globals.d.ts +112 -0
- package/tslibs/lib.restricted.globals.d.ts +1 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1519 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
DEFAULT_DIV_PRECISION: () => DEFAULT_DIV_PRECISION,
|
|
24
|
+
Decimal: () => Decimal,
|
|
25
|
+
DecimalRoundingPresets: () => DecimalRoundingPresets,
|
|
26
|
+
Integer: () => Integer,
|
|
27
|
+
PositiveInteger: () => PositiveInteger,
|
|
28
|
+
Ref: () => Ref,
|
|
29
|
+
StreetAddress: () => StreetAddress,
|
|
30
|
+
Timestamp: () => Timestamp,
|
|
31
|
+
WireReadError: () => WireReadError,
|
|
32
|
+
WireWriteError: () => WireWriteError,
|
|
33
|
+
_ConfigEnum: () => _ConfigEnum,
|
|
34
|
+
_JsonWireToType: () => _JsonWireToType,
|
|
35
|
+
_ProtoEnum: () => _ProtoEnum,
|
|
36
|
+
_ProtoWireToType: () => _ProtoWireToType,
|
|
37
|
+
_ShapeDescriptor: () => _ShapeDescriptor,
|
|
38
|
+
_TypeToProtoWire: () => _TypeToProtoWire,
|
|
39
|
+
_UnionDescriptor: () => _UnionDescriptor,
|
|
40
|
+
_apply: () => _apply,
|
|
41
|
+
_applyConfig: () => _applyConfig,
|
|
42
|
+
_applyIncoming: () => _applyIncoming,
|
|
43
|
+
_applyOutgoing: () => _applyOutgoing,
|
|
44
|
+
_configAppContextFromContext: () => _configAppContextFromContext,
|
|
45
|
+
_identity: () => _identity,
|
|
46
|
+
_isPromiseLike: () => _isPromiseLike,
|
|
47
|
+
_required: () => _required,
|
|
48
|
+
_translateArray: () => _translateArray,
|
|
49
|
+
_translateDateTime: () => _translateDateTime,
|
|
50
|
+
_translateDecimal: () => _translateDecimal,
|
|
51
|
+
_translateEnum: () => _translateEnum,
|
|
52
|
+
_translateMap: () => _translateMap,
|
|
53
|
+
_translateShape: () => _translateShape,
|
|
54
|
+
_translateUnion: () => _translateUnion,
|
|
55
|
+
isDecimal: () => isDecimal
|
|
56
|
+
});
|
|
57
|
+
module.exports = __toCommonJS(src_exports);
|
|
58
|
+
|
|
59
|
+
// src/stdlib/scalars.ts
|
|
60
|
+
var import_core = require("@formspec/core");
|
|
61
|
+
function roundToInteger(value, direction) {
|
|
62
|
+
switch (direction) {
|
|
63
|
+
case "ceil":
|
|
64
|
+
return Math.ceil(value);
|
|
65
|
+
case "floor":
|
|
66
|
+
return Math.floor(value);
|
|
67
|
+
case "round-down":
|
|
68
|
+
return Math.trunc(value);
|
|
69
|
+
case "round-up":
|
|
70
|
+
return value >= 0 ? Math.ceil(value) : Math.floor(value);
|
|
71
|
+
case "half-up":
|
|
72
|
+
return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
|
|
73
|
+
default: {
|
|
74
|
+
const _exhaustive = direction;
|
|
75
|
+
throw new Error(`Unknown rounding direction: ${String(_exhaustive)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
var Integer = {
|
|
80
|
+
/**
|
|
81
|
+
* Type guard that narrows a `number` to {@link (Integer:type)}.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const n: number = getCount();
|
|
86
|
+
* if (Integer.is(n)) {
|
|
87
|
+
* // n is Integer here
|
|
88
|
+
* config.retryCount = n;
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
is: (value) => Number.isInteger(value),
|
|
94
|
+
/**
|
|
95
|
+
* Coerces a number to an {@link (Integer:type)} by rounding.
|
|
96
|
+
* Throws if the value is not finite.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* const price = 9.99;
|
|
101
|
+
* const rounded = Integer.from(price, 'floor'); // 9
|
|
102
|
+
* const ceiled = Integer.from(price, 'ceil'); // 10
|
|
103
|
+
* ```
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
from: (value, rounding) => {
|
|
107
|
+
if (!Number.isFinite(value)) {
|
|
108
|
+
throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
|
|
109
|
+
}
|
|
110
|
+
return roundToInteger(value, rounding);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
var PositiveInteger = {
|
|
114
|
+
/**
|
|
115
|
+
* Type guard that narrows a `number` to {@link (PositiveInteger:type)}.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const n: number = getRetryCount();
|
|
120
|
+
* if (PositiveInteger.is(n)) {
|
|
121
|
+
* // n is PositiveInteger here
|
|
122
|
+
* config.maxRetries = n;
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
is: (value) => Number.isInteger(value) && value >= 0,
|
|
128
|
+
/**
|
|
129
|
+
* Coerces a number to a {@link (PositiveInteger:type)} by rounding.
|
|
130
|
+
* Throws if the value is not finite or the rounded result is negative.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* const ratio = 2.7;
|
|
135
|
+
* const count = PositiveInteger.from(ratio, 'floor'); // 2
|
|
136
|
+
* ```
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
from: (value, rounding) => {
|
|
140
|
+
if (!Number.isFinite(value)) {
|
|
141
|
+
throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
|
|
142
|
+
}
|
|
143
|
+
const rounded = roundToInteger(value, rounding) || 0;
|
|
144
|
+
if (rounded < 0) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`Value ${String(value)} rounds to ${String(rounded)}, which is negative`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return rounded;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
var StreetAddress = {
|
|
153
|
+
create: (address) => {
|
|
154
|
+
return address;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var Timestamp = {
|
|
158
|
+
create: (value) => {
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/stdlib/refs.ts
|
|
164
|
+
var Ref = {
|
|
165
|
+
create: (step) => {
|
|
166
|
+
return {
|
|
167
|
+
type: step.object,
|
|
168
|
+
id: step.id
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/stdlib/decimal.ts
|
|
174
|
+
var PLAIN_NOTATION_DIGIT_LIMIT = 30;
|
|
175
|
+
var DecimalRoundingPresets = Object.freeze({
|
|
176
|
+
"ubb-usage-count": Object.freeze({
|
|
177
|
+
mode: "significant-figures",
|
|
178
|
+
value: 15
|
|
179
|
+
}),
|
|
180
|
+
"v1-api": Object.freeze({
|
|
181
|
+
mode: "decimal-places",
|
|
182
|
+
value: 12
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
var DEFAULT_DIV_PRECISION = 34;
|
|
186
|
+
var IMPLICIT_DECIMAL_COERCION_ERROR = "Implicit Decimal coercion is not allowed; use .add(), .sub(), .mul(), .div(), .toString(), or .toNumber() explicitly.";
|
|
187
|
+
var MAX_EXPONENT = Number.MAX_SAFE_INTEGER;
|
|
188
|
+
var DECIMAL_BRAND = /* @__PURE__ */ Symbol.for(
|
|
189
|
+
"stripe.apps-extensibility-sdk.Decimal"
|
|
190
|
+
);
|
|
191
|
+
var DecimalImpl = class _DecimalImpl {
|
|
192
|
+
/** @internal */
|
|
193
|
+
[DECIMAL_BRAND] = true;
|
|
194
|
+
/** @internal */
|
|
195
|
+
#coefficient;
|
|
196
|
+
/** @internal */
|
|
197
|
+
#exponent;
|
|
198
|
+
/**
|
|
199
|
+
* Construct and normalise a decimal value.
|
|
200
|
+
*
|
|
201
|
+
* @param coefficient - The unscaled integer value.
|
|
202
|
+
* @param exponent - The power-of-ten scale factor.
|
|
203
|
+
*
|
|
204
|
+
* @internal
|
|
205
|
+
*/
|
|
206
|
+
constructor(coefficient, exponent) {
|
|
207
|
+
const [normalizedCoef, normalizedExp] = _DecimalImpl.normalize(coefficient, exponent);
|
|
208
|
+
this.#coefficient = normalizedCoef;
|
|
209
|
+
this.#exponent = normalizedExp;
|
|
210
|
+
Object.freeze(this);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Strip trailing zeros from `coefficient`, incrementing `exponent`
|
|
214
|
+
* for each zero removed. Zero always normalises to `(0n, 0)`.
|
|
215
|
+
*
|
|
216
|
+
* @param coefficient - Raw coefficient before normalisation.
|
|
217
|
+
* @param exponent - Raw exponent before normalisation.
|
|
218
|
+
* @returns A `[coefficient, exponent]` tuple with trailing zeros removed.
|
|
219
|
+
*
|
|
220
|
+
* @internal
|
|
221
|
+
*/
|
|
222
|
+
static normalize(coefficient, exponent) {
|
|
223
|
+
if (coefficient === 0n) {
|
|
224
|
+
return [0n, 0];
|
|
225
|
+
}
|
|
226
|
+
let coef = coefficient;
|
|
227
|
+
let exp = exponent;
|
|
228
|
+
while (coef !== 0n && coef % 10n === 0n) {
|
|
229
|
+
coef = coef / 10n;
|
|
230
|
+
exp++;
|
|
231
|
+
}
|
|
232
|
+
return [coef, exp];
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Apply rounding to the result of an integer division.
|
|
236
|
+
*
|
|
237
|
+
* @remarks
|
|
238
|
+
* BigInt division truncates toward zero. This helper inspects the
|
|
239
|
+
* `remainder` to decide whether to adjust the truncated `quotient`
|
|
240
|
+
* by ±1 according to the chosen {@link RoundDirection}.
|
|
241
|
+
*
|
|
242
|
+
* The rounding direction is derived from the signs of `remainder`
|
|
243
|
+
* and `divisor`: when they agree the exact fractional part is
|
|
244
|
+
* positive (the truncation point is below the true value, so +1
|
|
245
|
+
* rounds to nearest); when they disagree the fractional part is
|
|
246
|
+
* negative (−1 rounds to nearest).
|
|
247
|
+
*
|
|
248
|
+
* @param quotient - Truncated integer quotient (`dividend / divisor`).
|
|
249
|
+
* @param remainder - Division remainder (`dividend % divisor`).
|
|
250
|
+
* @param divisor - The divisor used in the division.
|
|
251
|
+
* @param direction - The rounding strategy to apply.
|
|
252
|
+
* @returns The rounded quotient.
|
|
253
|
+
*
|
|
254
|
+
* @internal
|
|
255
|
+
*/
|
|
256
|
+
static roundDivision(quotient, remainder, divisor, direction) {
|
|
257
|
+
if (remainder === 0n) {
|
|
258
|
+
return quotient;
|
|
259
|
+
}
|
|
260
|
+
if (direction === "round-down") {
|
|
261
|
+
return quotient;
|
|
262
|
+
}
|
|
263
|
+
const roundDir = remainder > 0n === divisor > 0n ? 1n : -1n;
|
|
264
|
+
if (direction === "round-up") {
|
|
265
|
+
return quotient + roundDir;
|
|
266
|
+
}
|
|
267
|
+
if (direction === "ceil") {
|
|
268
|
+
return roundDir === 1n ? quotient + 1n : quotient;
|
|
269
|
+
}
|
|
270
|
+
if (direction === "floor") {
|
|
271
|
+
return roundDir === -1n ? quotient - 1n : quotient;
|
|
272
|
+
}
|
|
273
|
+
const absRemainder = remainder < 0n ? -remainder : remainder;
|
|
274
|
+
const absDivisor = divisor < 0n ? -divisor : divisor;
|
|
275
|
+
const doubled = absRemainder * 2n;
|
|
276
|
+
const cmp = doubled === absDivisor ? 0 : doubled < absDivisor ? -1 : 1;
|
|
277
|
+
if (cmp < 0) {
|
|
278
|
+
return quotient;
|
|
279
|
+
}
|
|
280
|
+
if (cmp > 0) {
|
|
281
|
+
return quotient + roundDir;
|
|
282
|
+
}
|
|
283
|
+
if (direction === "half-up") {
|
|
284
|
+
return quotient + roundDir;
|
|
285
|
+
}
|
|
286
|
+
if (direction === "half-down") {
|
|
287
|
+
return quotient;
|
|
288
|
+
}
|
|
289
|
+
if (quotient % 2n === 0n) {
|
|
290
|
+
return quotient;
|
|
291
|
+
} else {
|
|
292
|
+
return quotient + roundDir;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// -------------------------------------------------------------------
|
|
296
|
+
// Arithmetic
|
|
297
|
+
// -------------------------------------------------------------------
|
|
298
|
+
/**
|
|
299
|
+
* Return the sum of this value and `other`.
|
|
300
|
+
*
|
|
301
|
+
* @param other - The addend.
|
|
302
|
+
* @returns A new {@link Decimal} equal to `this + other`.
|
|
303
|
+
*
|
|
304
|
+
* @public
|
|
305
|
+
*/
|
|
306
|
+
add(other) {
|
|
307
|
+
const otherImpl = toImpl(other);
|
|
308
|
+
if (this.#exponent === otherImpl.#exponent) {
|
|
309
|
+
return toDecimal(
|
|
310
|
+
new _DecimalImpl(this.#coefficient + otherImpl.#coefficient, this.#exponent)
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
if (this.#exponent < otherImpl.#exponent) {
|
|
314
|
+
const scale = 10n ** BigInt(otherImpl.#exponent - this.#exponent);
|
|
315
|
+
return toDecimal(
|
|
316
|
+
new _DecimalImpl(
|
|
317
|
+
this.#coefficient + otherImpl.#coefficient * scale,
|
|
318
|
+
this.#exponent
|
|
319
|
+
)
|
|
320
|
+
);
|
|
321
|
+
} else {
|
|
322
|
+
const scale = 10n ** BigInt(this.#exponent - otherImpl.#exponent);
|
|
323
|
+
return toDecimal(
|
|
324
|
+
new _DecimalImpl(
|
|
325
|
+
this.#coefficient * scale + otherImpl.#coefficient,
|
|
326
|
+
otherImpl.#exponent
|
|
327
|
+
)
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Return the difference of this value and `other`.
|
|
333
|
+
*
|
|
334
|
+
* @param other - The subtrahend.
|
|
335
|
+
* @returns A new {@link Decimal} equal to `this - other`.
|
|
336
|
+
*
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
sub(other) {
|
|
340
|
+
const otherImpl = toImpl(other);
|
|
341
|
+
if (this.#exponent === otherImpl.#exponent) {
|
|
342
|
+
return toDecimal(
|
|
343
|
+
new _DecimalImpl(this.#coefficient - otherImpl.#coefficient, this.#exponent)
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
if (this.#exponent < otherImpl.#exponent) {
|
|
347
|
+
const scale = 10n ** BigInt(otherImpl.#exponent - this.#exponent);
|
|
348
|
+
return toDecimal(
|
|
349
|
+
new _DecimalImpl(
|
|
350
|
+
this.#coefficient - otherImpl.#coefficient * scale,
|
|
351
|
+
this.#exponent
|
|
352
|
+
)
|
|
353
|
+
);
|
|
354
|
+
} else {
|
|
355
|
+
const scale = 10n ** BigInt(this.#exponent - otherImpl.#exponent);
|
|
356
|
+
return toDecimal(
|
|
357
|
+
new _DecimalImpl(
|
|
358
|
+
this.#coefficient * scale - otherImpl.#coefficient,
|
|
359
|
+
otherImpl.#exponent
|
|
360
|
+
)
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Return the product of this value and `other`.
|
|
366
|
+
*
|
|
367
|
+
* @param other - The multiplicand.
|
|
368
|
+
* @returns A new {@link Decimal} equal to `this × other`.
|
|
369
|
+
*
|
|
370
|
+
* @public
|
|
371
|
+
*/
|
|
372
|
+
mul(other) {
|
|
373
|
+
const otherImpl = toImpl(other);
|
|
374
|
+
return toDecimal(
|
|
375
|
+
new _DecimalImpl(
|
|
376
|
+
this.#coefficient * otherImpl.#coefficient,
|
|
377
|
+
this.#exponent + otherImpl.#exponent
|
|
378
|
+
)
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Return the quotient of this value divided by `other`.
|
|
383
|
+
*
|
|
384
|
+
* @remarks
|
|
385
|
+
* Division scales the dividend to produce `precision` decimal digits
|
|
386
|
+
* in the result, then applies integer division and rounds the
|
|
387
|
+
* remainder according to `direction`.
|
|
388
|
+
*
|
|
389
|
+
* Division requires explicit rounding control — no invisible defaults
|
|
390
|
+
* in financial code. For full precision use {@link DEFAULT_DIV_PRECISION}
|
|
391
|
+
* (34, matching the IEEE 754 decimal128 coefficient size).
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* ```ts
|
|
395
|
+
* Decimal.from('1').div(Decimal.from('3'), 5, 'half-up'); // "0.33333"
|
|
396
|
+
* Decimal.from('5').div(Decimal.from('2'), 0, 'half-up'); // "3"
|
|
397
|
+
* Decimal.from('5').div(Decimal.from('2'), 0, 'half-even'); // "2"
|
|
398
|
+
* ```
|
|
399
|
+
*
|
|
400
|
+
* @param other - The divisor. Must not be zero.
|
|
401
|
+
* @param precision - Maximum number of decimal digits in the result.
|
|
402
|
+
* @param direction - How to round when the exact quotient cannot
|
|
403
|
+
* be represented at the requested precision.
|
|
404
|
+
* @returns A new {@link Decimal} equal to `this ÷ other`, rounded to
|
|
405
|
+
* `precision` decimal places.
|
|
406
|
+
* @throws Error if `other` is zero.
|
|
407
|
+
* @throws Error if `precision` is negative or non-integer.
|
|
408
|
+
*
|
|
409
|
+
* @public
|
|
410
|
+
*/
|
|
411
|
+
div(other, precision, direction) {
|
|
412
|
+
if (precision < 0 || !Number.isInteger(precision)) {
|
|
413
|
+
throw new Error("precision must be a non-negative integer");
|
|
414
|
+
}
|
|
415
|
+
const otherImpl = toImpl(other);
|
|
416
|
+
if (otherImpl.#coefficient === 0n) {
|
|
417
|
+
throw new Error("Division by zero");
|
|
418
|
+
}
|
|
419
|
+
const scale = this.#exponent - otherImpl.#exponent + precision;
|
|
420
|
+
let quotient;
|
|
421
|
+
let remainder;
|
|
422
|
+
let roundingDivisor;
|
|
423
|
+
if (scale >= 0) {
|
|
424
|
+
const scaledDividend = this.#coefficient * 10n ** BigInt(scale);
|
|
425
|
+
quotient = scaledDividend / otherImpl.#coefficient;
|
|
426
|
+
remainder = scaledDividend % otherImpl.#coefficient;
|
|
427
|
+
roundingDivisor = otherImpl.#coefficient;
|
|
428
|
+
} else {
|
|
429
|
+
const scaledDivisor = otherImpl.#coefficient * 10n ** BigInt(-scale);
|
|
430
|
+
quotient = this.#coefficient / scaledDivisor;
|
|
431
|
+
remainder = this.#coefficient % scaledDivisor;
|
|
432
|
+
roundingDivisor = scaledDivisor;
|
|
433
|
+
}
|
|
434
|
+
const roundedQuotient = _DecimalImpl.roundDivision(
|
|
435
|
+
quotient,
|
|
436
|
+
remainder,
|
|
437
|
+
roundingDivisor,
|
|
438
|
+
direction
|
|
439
|
+
);
|
|
440
|
+
return toDecimal(new _DecimalImpl(roundedQuotient, -precision));
|
|
441
|
+
}
|
|
442
|
+
// -------------------------------------------------------------------
|
|
443
|
+
// Comparison
|
|
444
|
+
// -------------------------------------------------------------------
|
|
445
|
+
/**
|
|
446
|
+
* Three-way comparison of this value with `other`.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* const a = Decimal.from('1.5');
|
|
451
|
+
* const b = Decimal.from('2');
|
|
452
|
+
* a.cmp(b); // -1
|
|
453
|
+
* b.cmp(a); // 1
|
|
454
|
+
* a.cmp(a); // 0
|
|
455
|
+
* ```
|
|
456
|
+
*
|
|
457
|
+
* @param other - The value to compare against.
|
|
458
|
+
* @returns `-1` if `this < other`, `0` if equal, `1` if `this > other`.
|
|
459
|
+
*
|
|
460
|
+
* @public
|
|
461
|
+
*/
|
|
462
|
+
cmp(other) {
|
|
463
|
+
const otherImpl = toImpl(other);
|
|
464
|
+
if (this.#exponent === otherImpl.#exponent) {
|
|
465
|
+
if (this.#coefficient < otherImpl.#coefficient) return -1;
|
|
466
|
+
if (this.#coefficient > otherImpl.#coefficient) return 1;
|
|
467
|
+
return 0;
|
|
468
|
+
}
|
|
469
|
+
if (this.#exponent < otherImpl.#exponent) {
|
|
470
|
+
const scale = 10n ** BigInt(otherImpl.#exponent - this.#exponent);
|
|
471
|
+
const scaledOther = otherImpl.#coefficient * scale;
|
|
472
|
+
if (this.#coefficient < scaledOther) return -1;
|
|
473
|
+
if (this.#coefficient > scaledOther) return 1;
|
|
474
|
+
return 0;
|
|
475
|
+
} else {
|
|
476
|
+
const scale = 10n ** BigInt(this.#exponent - otherImpl.#exponent);
|
|
477
|
+
const scaledThis = this.#coefficient * scale;
|
|
478
|
+
if (scaledThis < otherImpl.#coefficient) return -1;
|
|
479
|
+
if (scaledThis > otherImpl.#coefficient) return 1;
|
|
480
|
+
return 0;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Return `true` if this value is numerically equal to `other`.
|
|
485
|
+
*
|
|
486
|
+
* @param other - The value to compare against.
|
|
487
|
+
* @returns `true` if `this === other` in value, `false` otherwise.
|
|
488
|
+
*
|
|
489
|
+
* @public
|
|
490
|
+
*/
|
|
491
|
+
eq(other) {
|
|
492
|
+
return this.cmp(other) === 0;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Return `true` if this value is strictly less than `other`.
|
|
496
|
+
*
|
|
497
|
+
* @param other - The value to compare against.
|
|
498
|
+
* @returns `true` if `this < other`, `false` otherwise.
|
|
499
|
+
*
|
|
500
|
+
* @public
|
|
501
|
+
*/
|
|
502
|
+
lt(other) {
|
|
503
|
+
return this.cmp(other) === -1;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Return `true` if this value is less than or equal to `other`.
|
|
507
|
+
*
|
|
508
|
+
* @param other - The value to compare against.
|
|
509
|
+
* @returns `true` if `this ≤ other`, `false` otherwise.
|
|
510
|
+
*
|
|
511
|
+
* @public
|
|
512
|
+
*/
|
|
513
|
+
lte(other) {
|
|
514
|
+
return this.cmp(other) <= 0;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Return `true` if this value is strictly greater than `other`.
|
|
518
|
+
*
|
|
519
|
+
* @param other - The value to compare against.
|
|
520
|
+
* @returns `true` if `this > other`, `false` otherwise.
|
|
521
|
+
*
|
|
522
|
+
* @public
|
|
523
|
+
*/
|
|
524
|
+
gt(other) {
|
|
525
|
+
return this.cmp(other) === 1;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Return `true` if this value is greater than or equal to `other`.
|
|
529
|
+
*
|
|
530
|
+
* @param other - The value to compare against.
|
|
531
|
+
* @returns `true` if `this ≥ other`, `false` otherwise.
|
|
532
|
+
*
|
|
533
|
+
* @public
|
|
534
|
+
*/
|
|
535
|
+
gte(other) {
|
|
536
|
+
return this.cmp(other) >= 0;
|
|
537
|
+
}
|
|
538
|
+
// -------------------------------------------------------------------
|
|
539
|
+
// Predicates
|
|
540
|
+
// -------------------------------------------------------------------
|
|
541
|
+
/**
|
|
542
|
+
* Return `true` if this value is exactly zero.
|
|
543
|
+
*
|
|
544
|
+
* @returns `true` if the value is zero, `false` otherwise.
|
|
545
|
+
*
|
|
546
|
+
* @public
|
|
547
|
+
*/
|
|
548
|
+
isZero() {
|
|
549
|
+
return this.#coefficient === 0n;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Return `true` if this value is strictly less than zero.
|
|
553
|
+
*
|
|
554
|
+
* @returns `true` if negative, `false` if zero or positive.
|
|
555
|
+
*
|
|
556
|
+
* @public
|
|
557
|
+
*/
|
|
558
|
+
isNegative() {
|
|
559
|
+
return this.#coefficient < 0n;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Return `true` if this value is strictly greater than zero.
|
|
563
|
+
*
|
|
564
|
+
* @returns `true` if positive, `false` if zero or negative.
|
|
565
|
+
*
|
|
566
|
+
* @public
|
|
567
|
+
*/
|
|
568
|
+
isPositive() {
|
|
569
|
+
return this.#coefficient > 0n;
|
|
570
|
+
}
|
|
571
|
+
// -------------------------------------------------------------------
|
|
572
|
+
// Unary operations
|
|
573
|
+
// -------------------------------------------------------------------
|
|
574
|
+
/**
|
|
575
|
+
* Return the additive inverse of this value.
|
|
576
|
+
*
|
|
577
|
+
* @returns A new {@link Decimal} equal to `-this`.
|
|
578
|
+
*
|
|
579
|
+
* @public
|
|
580
|
+
*/
|
|
581
|
+
neg() {
|
|
582
|
+
return toDecimal(new _DecimalImpl(-this.#coefficient, this.#exponent));
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Return the absolute value.
|
|
586
|
+
*
|
|
587
|
+
* @returns A new {@link Decimal} equal to `|this|`. If this value is
|
|
588
|
+
* already non-negative, returns `this` (no allocation).
|
|
589
|
+
*
|
|
590
|
+
* @public
|
|
591
|
+
*/
|
|
592
|
+
abs() {
|
|
593
|
+
if (this.#coefficient < 0n) {
|
|
594
|
+
return toDecimal(new _DecimalImpl(-this.#coefficient, this.#exponent));
|
|
595
|
+
}
|
|
596
|
+
return toDecimal(this);
|
|
597
|
+
}
|
|
598
|
+
// -------------------------------------------------------------------
|
|
599
|
+
// Rounding
|
|
600
|
+
// -------------------------------------------------------------------
|
|
601
|
+
/**
|
|
602
|
+
* Round this value to a specified precision.
|
|
603
|
+
*
|
|
604
|
+
* @remarks
|
|
605
|
+
* **Rounding directions** (IEEE 754-2019 §4.3):
|
|
606
|
+
*
|
|
607
|
+
* | Direction | Behavior |
|
|
608
|
+
* | -------------- | ---------------------------------------------- |
|
|
609
|
+
* | `'ceil'` | 1.1→2, -1.1→-1, 1.0→1 (toward +∞) |
|
|
610
|
+
* | `'floor'` | 1.9→1, -1.1→-2, 1.0→1 (toward -∞) |
|
|
611
|
+
* | `'round-down'` | 1.9→1, -1.9→-1 (toward zero / truncate) |
|
|
612
|
+
* | `'round-up'` | 1.1→2, -1.1→-2 (away from zero) |
|
|
613
|
+
* | `'half-up'` | 0.5→1, 1.5→2, -0.5→-1 (ties away from zero) |
|
|
614
|
+
* | `'half-down'` | 0.5→0, 1.5→1, -0.5→0 (ties toward zero) |
|
|
615
|
+
* | `'half-even'` | 0.5→0, 1.5→2, 2.5→2, 3.5→4 (ties to even) |
|
|
616
|
+
*
|
|
617
|
+
* **Precision** is specified as a {@link DecimalRoundingOptions} object
|
|
618
|
+
* or a built-in preset name from {@link DecimalRoundingPresets}:
|
|
619
|
+
*
|
|
620
|
+
* @example
|
|
621
|
+
* ```ts
|
|
622
|
+
* // Using a preset
|
|
623
|
+
* amount.round('half-even', 'v1-api');
|
|
624
|
+
*
|
|
625
|
+
* // Using explicit options
|
|
626
|
+
* amount.round('half-even', { mode: 'decimal-places', value: 2 });
|
|
627
|
+
* amount.round('half-up', { mode: 'significant-figures', value: 4 });
|
|
628
|
+
* ```
|
|
629
|
+
*
|
|
630
|
+
* @param direction - How to round.
|
|
631
|
+
* @param options - A {@link DecimalRoundingOptions} object or key of `typeof DecimalRoundingPresets`.
|
|
632
|
+
* @returns A new {@link Decimal} rounded to the specified precision.
|
|
633
|
+
* @throws Error if `options.value` is negative or non-integer.
|
|
634
|
+
* @throws Error if the preset name is not recognized.
|
|
635
|
+
*
|
|
636
|
+
* @public
|
|
637
|
+
*/
|
|
638
|
+
round(direction, options) {
|
|
639
|
+
if (typeof options === "string") {
|
|
640
|
+
if (!Object.hasOwn(DecimalRoundingPresets, options)) {
|
|
641
|
+
throw new Error(`Unknown rounding preset: "${options}"`);
|
|
642
|
+
}
|
|
643
|
+
return this.#roundWithOptions(direction, DecimalRoundingPresets[options]);
|
|
644
|
+
}
|
|
645
|
+
return this.#roundWithOptions(direction, options);
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Apply resolved {@link DecimalRoundingOptions} to this value.
|
|
649
|
+
*
|
|
650
|
+
* @param direction - How to round.
|
|
651
|
+
* @param resolved - Already-resolved options (never a preset name).
|
|
652
|
+
* @returns A new {@link Decimal} rounded to the specified precision.
|
|
653
|
+
*
|
|
654
|
+
* @internal
|
|
655
|
+
*/
|
|
656
|
+
#roundWithOptions(direction, resolved) {
|
|
657
|
+
if (resolved.value < 0 || !Number.isInteger(resolved.value)) {
|
|
658
|
+
throw new Error("DecimalRoundingOptions.value must be a non-negative integer");
|
|
659
|
+
}
|
|
660
|
+
if (resolved.mode === "decimal-places") {
|
|
661
|
+
const fixed = this.toFixed(resolved.value, direction);
|
|
662
|
+
return Decimal.from(fixed);
|
|
663
|
+
}
|
|
664
|
+
if (this.#coefficient === 0n) {
|
|
665
|
+
return toDecimal(this);
|
|
666
|
+
}
|
|
667
|
+
const coeffStr = this.#coefficient < 0n ? (-this.#coefficient).toString() : this.#coefficient.toString();
|
|
668
|
+
const currentSigFigs = coeffStr.length;
|
|
669
|
+
if (resolved.value === 0) {
|
|
670
|
+
return Decimal.zero;
|
|
671
|
+
}
|
|
672
|
+
if (currentSigFigs <= resolved.value) {
|
|
673
|
+
return toDecimal(this);
|
|
674
|
+
}
|
|
675
|
+
const digitsToTrim = currentSigFigs - resolved.value;
|
|
676
|
+
const divisor = 10n ** BigInt(digitsToTrim);
|
|
677
|
+
const quotient = this.#coefficient / divisor;
|
|
678
|
+
const remainder = this.#coefficient % divisor;
|
|
679
|
+
const rounded = _DecimalImpl.roundDivision(quotient, remainder, divisor, direction);
|
|
680
|
+
return toDecimal(new _DecimalImpl(rounded, this.#exponent + digitsToTrim));
|
|
681
|
+
}
|
|
682
|
+
// -------------------------------------------------------------------
|
|
683
|
+
// Conversion / serialisation
|
|
684
|
+
// -------------------------------------------------------------------
|
|
685
|
+
/**
|
|
686
|
+
* Return a human-readable string representation.
|
|
687
|
+
*
|
|
688
|
+
* @remarks
|
|
689
|
+
* Plain notation for values whose digit count is at most 30, and
|
|
690
|
+
* scientific notation (`1.23E+40`) for larger values. Trailing zeros
|
|
691
|
+
* are never present because the internal representation is normalised.
|
|
692
|
+
*
|
|
693
|
+
* @public
|
|
694
|
+
*/
|
|
695
|
+
toString() {
|
|
696
|
+
if (this.#coefficient === 0n) {
|
|
697
|
+
return "0";
|
|
698
|
+
}
|
|
699
|
+
const coeffStr = this.#coefficient.toString();
|
|
700
|
+
const isNeg = coeffStr.startsWith("-");
|
|
701
|
+
const absCoeffStr = isNeg ? coeffStr.slice(1) : coeffStr;
|
|
702
|
+
if (this.#exponent < 0) {
|
|
703
|
+
const decimalPlaces = -this.#exponent;
|
|
704
|
+
const leadingZeroCount = decimalPlaces >= absCoeffStr.length ? decimalPlaces - absCoeffStr.length : 0;
|
|
705
|
+
if (leadingZeroCount > PLAIN_NOTATION_DIGIT_LIMIT) {
|
|
706
|
+
if (absCoeffStr.length === 1) {
|
|
707
|
+
return `${coeffStr}E${String(this.#exponent)}`;
|
|
708
|
+
}
|
|
709
|
+
const intPart = absCoeffStr[0] ?? "";
|
|
710
|
+
const fracPart = absCoeffStr.slice(1);
|
|
711
|
+
const adjustedExp = this.#exponent + absCoeffStr.length - 1;
|
|
712
|
+
return `${isNeg ? "-" : ""}${intPart}.${fracPart}E${String(adjustedExp)}`;
|
|
713
|
+
}
|
|
714
|
+
if (decimalPlaces >= absCoeffStr.length) {
|
|
715
|
+
const leadingZeros = "0".repeat(decimalPlaces - absCoeffStr.length);
|
|
716
|
+
return `${isNeg ? "-" : ""}0.${leadingZeros}${absCoeffStr}`;
|
|
717
|
+
} else {
|
|
718
|
+
const integerPart = absCoeffStr.slice(0, absCoeffStr.length - decimalPlaces);
|
|
719
|
+
const fractionalPart = absCoeffStr.slice(absCoeffStr.length - decimalPlaces);
|
|
720
|
+
return `${isNeg ? "-" : ""}${integerPart}.${fractionalPart}`;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
const plainLength = absCoeffStr.length + this.#exponent;
|
|
724
|
+
if (plainLength <= PLAIN_NOTATION_DIGIT_LIMIT) {
|
|
725
|
+
if (this.#exponent === 0) {
|
|
726
|
+
return coeffStr;
|
|
727
|
+
}
|
|
728
|
+
const trailingZeros = "0".repeat(this.#exponent);
|
|
729
|
+
return `${isNeg ? "-" : ""}${absCoeffStr}${trailingZeros}`;
|
|
730
|
+
} else {
|
|
731
|
+
if (absCoeffStr.length === 1) {
|
|
732
|
+
return `${coeffStr}E+${String(this.#exponent)}`;
|
|
733
|
+
}
|
|
734
|
+
const integerPart = absCoeffStr[0] ?? "";
|
|
735
|
+
const fractionalPart = absCoeffStr.slice(1);
|
|
736
|
+
const adjustedExponent = this.#exponent + absCoeffStr.length - 1;
|
|
737
|
+
return `${isNeg ? "-" : ""}${integerPart}.${fractionalPart}E+${String(adjustedExponent)}`;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Return the JSON-serialisable representation.
|
|
742
|
+
*
|
|
743
|
+
* @remarks
|
|
744
|
+
* Returns a plain string matching the Stripe API convention where
|
|
745
|
+
* decimal values are serialised as strings in JSON. Called
|
|
746
|
+
* automatically by `JSON.stringify`.
|
|
747
|
+
*
|
|
748
|
+
* @public
|
|
749
|
+
*/
|
|
750
|
+
toJSON() {
|
|
751
|
+
return this.toString();
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Convert to a JavaScript `number`.
|
|
755
|
+
*
|
|
756
|
+
* @remarks
|
|
757
|
+
* This is an explicit, intentionally lossy conversion. Use it only
|
|
758
|
+
* when you need a numeric value for display or interop with APIs
|
|
759
|
+
* that require `number`. Prefer {@link Decimal.toString | toString}
|
|
760
|
+
* or {@link Decimal.toFixed | toFixed} for lossless output.
|
|
761
|
+
*
|
|
762
|
+
* @public
|
|
763
|
+
*/
|
|
764
|
+
toNumber() {
|
|
765
|
+
return Number(this.toString());
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Format this value as a fixed-point string with exactly
|
|
769
|
+
* `decimalPlaces` digits after the decimal point.
|
|
770
|
+
*
|
|
771
|
+
* @remarks
|
|
772
|
+
* Values are rounded according to `direction` when the internal
|
|
773
|
+
* precision exceeds the requested number of decimal places.
|
|
774
|
+
* The rounding direction is always required — no invisible defaults
|
|
775
|
+
* in financial code.
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* ```ts
|
|
779
|
+
* Decimal.from('1.235').toFixed(2, 'half-up'); // "1.24"
|
|
780
|
+
* Decimal.from('1.225').toFixed(2, 'half-even'); // "1.22"
|
|
781
|
+
* Decimal.from('42').toFixed(3, 'half-up'); // "42.000"
|
|
782
|
+
* ```
|
|
783
|
+
*
|
|
784
|
+
* @param decimalPlaces - Number of digits after the decimal point.
|
|
785
|
+
* Must be a non-negative integer.
|
|
786
|
+
* @param direction - How to round when truncating excess digits.
|
|
787
|
+
* @returns A string with exactly `decimalPlaces` fractional digits.
|
|
788
|
+
* @throws Error if `decimalPlaces` is negative or non-integer.
|
|
789
|
+
*
|
|
790
|
+
* @public
|
|
791
|
+
*/
|
|
792
|
+
toFixed(decimalPlaces, direction) {
|
|
793
|
+
if (decimalPlaces < 0 || !Number.isInteger(decimalPlaces)) {
|
|
794
|
+
throw new Error("decimalPlaces must be a non-negative integer");
|
|
795
|
+
}
|
|
796
|
+
const formatFixed = (coef) => {
|
|
797
|
+
const coeffStr = coef.toString();
|
|
798
|
+
const isNeg = coeffStr.startsWith("-");
|
|
799
|
+
const absCoeffStr = isNeg ? coeffStr.slice(1) : coeffStr;
|
|
800
|
+
if (decimalPlaces === 0) {
|
|
801
|
+
return coeffStr;
|
|
802
|
+
}
|
|
803
|
+
if (decimalPlaces >= absCoeffStr.length) {
|
|
804
|
+
const leadingZeros = "0".repeat(decimalPlaces - absCoeffStr.length);
|
|
805
|
+
return `${isNeg ? "-" : ""}0.${leadingZeros}${absCoeffStr}`;
|
|
806
|
+
} else {
|
|
807
|
+
const integerPart = absCoeffStr.slice(0, absCoeffStr.length - decimalPlaces);
|
|
808
|
+
const fractionalPart = absCoeffStr.slice(absCoeffStr.length - decimalPlaces);
|
|
809
|
+
return `${isNeg ? "-" : ""}${integerPart}.${fractionalPart}`;
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const targetExponent = -decimalPlaces;
|
|
813
|
+
if (this.#exponent === targetExponent) {
|
|
814
|
+
return formatFixed(this.#coefficient);
|
|
815
|
+
}
|
|
816
|
+
if (this.#exponent < targetExponent) {
|
|
817
|
+
const scaleDiff = targetExponent - this.#exponent;
|
|
818
|
+
const divisor = 10n ** BigInt(scaleDiff);
|
|
819
|
+
const quotient = this.#coefficient / divisor;
|
|
820
|
+
const remainder = this.#coefficient % divisor;
|
|
821
|
+
const rounded = _DecimalImpl.roundDivision(quotient, remainder, divisor, direction);
|
|
822
|
+
return formatFixed(rounded);
|
|
823
|
+
} else {
|
|
824
|
+
const scaleDiff = this.#exponent - targetExponent;
|
|
825
|
+
const scaled = this.#coefficient * 10n ** BigInt(scaleDiff);
|
|
826
|
+
return formatFixed(scaled);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Reject implicit arithmetic-style coercion while preserving explicit
|
|
831
|
+
* stringification.
|
|
832
|
+
*
|
|
833
|
+
* @remarks
|
|
834
|
+
* JavaScript cannot overload `+` to perform exact decimal arithmetic.
|
|
835
|
+
* The runtime only allows coercion hooks to return primitive values,
|
|
836
|
+
* which would either concatenate strings or lose precision by forcing
|
|
837
|
+
* the Decimal through IEEE 754 `number`. In financial code, that is
|
|
838
|
+
* less safe than rejecting the operation outright.
|
|
839
|
+
*
|
|
840
|
+
* `String(decimal)` and template-string interpolation still work
|
|
841
|
+
* because the string hint returns the canonical decimal string.
|
|
842
|
+
*
|
|
843
|
+
* @public
|
|
844
|
+
*/
|
|
845
|
+
[Symbol.toPrimitive](hint) {
|
|
846
|
+
if (hint === "string") {
|
|
847
|
+
return this.toString();
|
|
848
|
+
}
|
|
849
|
+
throw new Error(IMPLICIT_DECIMAL_COERCION_ERROR);
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Return the canonical string representation when called directly.
|
|
853
|
+
*
|
|
854
|
+
* @remarks
|
|
855
|
+
* JavaScript implicit coercion uses
|
|
856
|
+
* {@link Decimal.[Symbol.toPrimitive] | [Symbol.toPrimitive]} first, so
|
|
857
|
+
* this method is only reached via explicit direct calls such as
|
|
858
|
+
* `decimal.valueOf()`.
|
|
859
|
+
*
|
|
860
|
+
* @public
|
|
861
|
+
*/
|
|
862
|
+
valueOf() {
|
|
863
|
+
return this.toString();
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
function toImpl(d) {
|
|
867
|
+
return d;
|
|
868
|
+
}
|
|
869
|
+
function toDecimal(impl) {
|
|
870
|
+
return impl;
|
|
871
|
+
}
|
|
872
|
+
function isDecimal(value) {
|
|
873
|
+
return typeof value === "object" && value !== null && DECIMAL_BRAND in value;
|
|
874
|
+
}
|
|
875
|
+
var Decimal = {
|
|
876
|
+
/**
|
|
877
|
+
* Create a `Decimal` from a string, number, or bigint.
|
|
878
|
+
*
|
|
879
|
+
* @remarks
|
|
880
|
+
* - **string**: Parsed as a decimal literal. Accepts an optional sign,
|
|
881
|
+
* integer digits, an optional fractional part, and an optional `e`/`E`
|
|
882
|
+
* exponent. Leading/trailing whitespace is trimmed.
|
|
883
|
+
* - **number**: Must be finite. Converted via `Number.prototype.toString()`
|
|
884
|
+
* then parsed, so `Decimal.from(0.1)` produces `"0.1"` (not the
|
|
885
|
+
* 53-bit binary approximation).
|
|
886
|
+
* - **bigint**: Treated as an integer with exponent 0.
|
|
887
|
+
*
|
|
888
|
+
* @example
|
|
889
|
+
* ```ts
|
|
890
|
+
* Decimal.from('1.23'); // string
|
|
891
|
+
* Decimal.from(42); // number
|
|
892
|
+
* Decimal.from(100n); // bigint
|
|
893
|
+
* Decimal.from('1.5e3'); // scientific notation → 1500
|
|
894
|
+
* ```
|
|
895
|
+
*
|
|
896
|
+
* @param value - The value to convert.
|
|
897
|
+
* @returns A new frozen `Decimal` instance.
|
|
898
|
+
* @throws Error if `value` is a non-finite number, an empty
|
|
899
|
+
* string, or a string that does not match the decimal literal grammar.
|
|
900
|
+
*
|
|
901
|
+
* @public
|
|
902
|
+
*/
|
|
903
|
+
from(value) {
|
|
904
|
+
if (typeof value === "bigint") {
|
|
905
|
+
return toDecimal(new DecimalImpl(value, 0));
|
|
906
|
+
}
|
|
907
|
+
if (typeof value === "number") {
|
|
908
|
+
if (!Number.isFinite(value)) {
|
|
909
|
+
throw new Error("Number must be finite");
|
|
910
|
+
}
|
|
911
|
+
return Decimal.from(value.toString());
|
|
912
|
+
}
|
|
913
|
+
const trimmed = value.trim();
|
|
914
|
+
if (trimmed === "") {
|
|
915
|
+
throw new Error("Cannot parse empty string as Decimal");
|
|
916
|
+
}
|
|
917
|
+
const match = /^([+-]?)(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/.exec(trimmed);
|
|
918
|
+
if (!match) {
|
|
919
|
+
throw new Error(`Invalid decimal string: ${value}`);
|
|
920
|
+
}
|
|
921
|
+
const sign = match[1] === "-" ? -1n : 1n;
|
|
922
|
+
const integerPart = match[2] ?? "";
|
|
923
|
+
const fractionalPart = match[3] ?? "";
|
|
924
|
+
const exponentPart = match[4] ? Number(match[4]) : 0;
|
|
925
|
+
if (!Number.isSafeInteger(exponentPart) || exponentPart > MAX_EXPONENT || exponentPart < -MAX_EXPONENT) {
|
|
926
|
+
throw new Error(
|
|
927
|
+
`Exponent out of range: ${String(match[4])} exceeds safe integer bounds`
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
const coefficientStr = integerPart + fractionalPart;
|
|
931
|
+
const coefficient = sign * BigInt(coefficientStr);
|
|
932
|
+
const exponent = exponentPart - fractionalPart.length;
|
|
933
|
+
if (!Number.isSafeInteger(exponent) || exponent > MAX_EXPONENT || exponent < -MAX_EXPONENT) {
|
|
934
|
+
throw new Error(
|
|
935
|
+
`Computed exponent out of range: ${String(exponent)} exceeds safe integer bounds`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
return toDecimal(new DecimalImpl(coefficient, exponent));
|
|
939
|
+
},
|
|
940
|
+
/**
|
|
941
|
+
* The `Decimal` value representing zero.
|
|
942
|
+
*
|
|
943
|
+
* @remarks
|
|
944
|
+
* Pre-allocated singleton — prefer `Decimal.zero` over
|
|
945
|
+
* `Decimal.from(0)` to avoid an unnecessary allocation.
|
|
946
|
+
*
|
|
947
|
+
* @public
|
|
948
|
+
*/
|
|
949
|
+
zero: toDecimal(new DecimalImpl(0n, 0))
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
// src/stdlib/types.ts
|
|
953
|
+
var WireReadError = class extends Error {
|
|
954
|
+
/**
|
|
955
|
+
* Error class name for `instanceof`-free identification.
|
|
956
|
+
* @internal
|
|
957
|
+
*/
|
|
958
|
+
name = "WireReadError";
|
|
959
|
+
};
|
|
960
|
+
var WireWriteError = class extends Error {
|
|
961
|
+
/**
|
|
962
|
+
* Error class name for `instanceof`-free identification.
|
|
963
|
+
* @internal
|
|
964
|
+
*/
|
|
965
|
+
name = "WireWriteError";
|
|
966
|
+
};
|
|
967
|
+
var WireParseError = class extends Error {
|
|
968
|
+
name = "WireParseError";
|
|
969
|
+
};
|
|
970
|
+
var _ProtoEnum = class {
|
|
971
|
+
_from;
|
|
972
|
+
_to;
|
|
973
|
+
constructor(fromProto) {
|
|
974
|
+
this._from = new Map(Object.entries(fromProto));
|
|
975
|
+
const to = /* @__PURE__ */ new Map();
|
|
976
|
+
for (const [wire, sdk] of this._from) {
|
|
977
|
+
if (to.has(sdk)) {
|
|
978
|
+
throw new Error(`_ProtoEnum: duplicate SDK value '${sdk}' in fromProto map`);
|
|
979
|
+
}
|
|
980
|
+
to.set(sdk, wire);
|
|
981
|
+
}
|
|
982
|
+
this._to = to;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Convert a proto wire value to an SDK value, or `null` if unknown.
|
|
986
|
+
* @internal
|
|
987
|
+
*/
|
|
988
|
+
fromWire(value) {
|
|
989
|
+
return this._from.get(value) ?? null;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Convert an SDK value to a proto wire value, or `null` if unknown.
|
|
993
|
+
* @internal
|
|
994
|
+
*/
|
|
995
|
+
toWire(value) {
|
|
996
|
+
return this._to.get(value) ?? null;
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
var _ConfigEnum = class {
|
|
1000
|
+
_values;
|
|
1001
|
+
constructor(values) {
|
|
1002
|
+
this._values = new Set(values);
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Validate and return the wire value unchanged, or `null` if unknown.
|
|
1006
|
+
* @internal
|
|
1007
|
+
*/
|
|
1008
|
+
fromWire(value) {
|
|
1009
|
+
return this._values.has(value) ? value : null;
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Validate and return the SDK value unchanged, or `null` if unknown.
|
|
1013
|
+
* @internal
|
|
1014
|
+
*/
|
|
1015
|
+
toWire(value) {
|
|
1016
|
+
return this._values.has(value) ? value : null;
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
var _ShapeDescriptor = class {
|
|
1020
|
+
/** The type name, used in error messages. */
|
|
1021
|
+
typeName;
|
|
1022
|
+
/** The field descriptors for this shape. */
|
|
1023
|
+
fields;
|
|
1024
|
+
/** Optional oneof field descriptors (mixed messages with regular + oneof fields). */
|
|
1025
|
+
oneofFields;
|
|
1026
|
+
constructor(typeName, fields, oneofFields) {
|
|
1027
|
+
this.typeName = typeName;
|
|
1028
|
+
this.fields = fields;
|
|
1029
|
+
if (oneofFields) {
|
|
1030
|
+
this.oneofFields = oneofFields;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
var _UnionDescriptor = class {
|
|
1035
|
+
/** The type name, used in error messages. */
|
|
1036
|
+
typeName;
|
|
1037
|
+
/** The SDK-side discriminant field name (e.g. `'value'`, `'kind'`). */
|
|
1038
|
+
discriminantFieldName;
|
|
1039
|
+
/** The branch descriptors for this union. */
|
|
1040
|
+
branches;
|
|
1041
|
+
constructor(typeName, discriminantFieldName, branches) {
|
|
1042
|
+
this.typeName = typeName;
|
|
1043
|
+
this.discriminantFieldName = discriminantFieldName;
|
|
1044
|
+
this.branches = branches;
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
function otherFieldNameFor(discriminantFieldName) {
|
|
1048
|
+
return "other" + discriminantFieldName.charAt(0).toUpperCase() + discriminantFieldName.slice(1);
|
|
1049
|
+
}
|
|
1050
|
+
function _isPromiseLike(value) {
|
|
1051
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
1052
|
+
if ("then" in value) {
|
|
1053
|
+
return typeof value.then === "function";
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
return false;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// src/stdlib/transforms.ts
|
|
1060
|
+
function _apply(descriptor, strategy, inputObject, typeName = descriptor.typeName) {
|
|
1061
|
+
if (inputObject === null || inputObject === void 0) {
|
|
1062
|
+
const loc = typeName || "object";
|
|
1063
|
+
const received = inputObject === null ? "null" : "undefined";
|
|
1064
|
+
throw strategy.createNotObjectError(loc, received);
|
|
1065
|
+
}
|
|
1066
|
+
if (typeof inputObject !== "object") {
|
|
1067
|
+
const loc = typeName || "object";
|
|
1068
|
+
throw strategy.createNotObjectError(loc, typeof inputObject);
|
|
1069
|
+
}
|
|
1070
|
+
const input = inputObject;
|
|
1071
|
+
const result = {};
|
|
1072
|
+
for (const desc of descriptor.fields) {
|
|
1073
|
+
const [key, value] = strategy.applyField(typeName, desc, input, strategy);
|
|
1074
|
+
if (value !== void 0) result[key] = value;
|
|
1075
|
+
}
|
|
1076
|
+
if (descriptor.oneofFields) {
|
|
1077
|
+
const regularWireKeys = descriptor.fields.map((f) => f.wire ?? f.type);
|
|
1078
|
+
const allOneofBranchKeys = descriptor.oneofFields.flatMap(
|
|
1079
|
+
(o) => o.branches.map((b) => b.wireKey)
|
|
1080
|
+
);
|
|
1081
|
+
const excludeKeys = /* @__PURE__ */ new Set([...regularWireKeys, ...allOneofBranchKeys]);
|
|
1082
|
+
for (const oneof of descriptor.oneofFields) {
|
|
1083
|
+
strategy.applyOneofField(typeName, oneof, input, strategy, result, excludeKeys);
|
|
1084
|
+
const otherField = otherFieldNameFor(oneof.discriminant);
|
|
1085
|
+
if (result[oneof.discriminant] === "other" && typeof result[otherField] === "string") {
|
|
1086
|
+
excludeKeys.add(result[otherField]);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
return result;
|
|
1091
|
+
}
|
|
1092
|
+
var _identity = (_strategy, value) => value;
|
|
1093
|
+
function _required(fn = _identity) {
|
|
1094
|
+
return (strategy, value) => {
|
|
1095
|
+
const result = fn(strategy, value);
|
|
1096
|
+
if (result === null || result === void 0) {
|
|
1097
|
+
throw new WireParseError("Required field is missing");
|
|
1098
|
+
}
|
|
1099
|
+
return result;
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
var _translateDecimal = (strategy, value) => strategy.translateDecimal(value);
|
|
1103
|
+
var _translateDateTime = (strategy, value) => strategy.translateDateTime(value);
|
|
1104
|
+
function _translateEnum(spec) {
|
|
1105
|
+
return (strategy, value) => strategy.translateEnum(spec, value);
|
|
1106
|
+
}
|
|
1107
|
+
function _translateShape(getDesc) {
|
|
1108
|
+
return (strategy, value) => {
|
|
1109
|
+
if (value === null || value === void 0) return void 0;
|
|
1110
|
+
return _apply(getDesc(), strategy, value);
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
function _translateUnion(getDesc) {
|
|
1114
|
+
return (strategy, value) => {
|
|
1115
|
+
if (value === null || value === void 0) return void 0;
|
|
1116
|
+
return strategy.applyUnion(getDesc(), value);
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
function _translateArray(elementFn) {
|
|
1120
|
+
return (strategy, value) => {
|
|
1121
|
+
if (value === null || value === void 0) return void 0;
|
|
1122
|
+
if (!Array.isArray(value)) {
|
|
1123
|
+
throw new WireParseError(`Expected array but received: ${typeof value}`);
|
|
1124
|
+
}
|
|
1125
|
+
return value.map((v) => elementFn(strategy, v));
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
function _translateMap(keyFn, valueFn) {
|
|
1129
|
+
return (strategy, value) => {
|
|
1130
|
+
if (value === null || value === void 0) return void 0;
|
|
1131
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
1132
|
+
throw new WireParseError(
|
|
1133
|
+
`Expected object for translateMap but received: ${typeof value}`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
const entries = Object.entries(value);
|
|
1137
|
+
return Object.fromEntries(
|
|
1138
|
+
entries.map(([k, v]) => {
|
|
1139
|
+
const mappedKey = keyFn(strategy, k);
|
|
1140
|
+
if (typeof mappedKey !== "string") {
|
|
1141
|
+
throw new WireParseError(
|
|
1142
|
+
`translateMap: key transform returned ${typeof mappedKey} instead of string`
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
return [mappedKey, valueFn(strategy, v)];
|
|
1146
|
+
})
|
|
1147
|
+
);
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// src/stdlib/transform-strategies.ts
|
|
1152
|
+
function parseDateString(value) {
|
|
1153
|
+
const date = new Date(value);
|
|
1154
|
+
if (isNaN(date.getTime())) {
|
|
1155
|
+
throw new WireParseError(`Cannot parse '${value}' as Date`);
|
|
1156
|
+
}
|
|
1157
|
+
return date;
|
|
1158
|
+
}
|
|
1159
|
+
function enumLookup(spec, value, direction) {
|
|
1160
|
+
if (typeof value !== "string") {
|
|
1161
|
+
throw new WireParseError(`Expected string enum value but received ${typeof value}`);
|
|
1162
|
+
}
|
|
1163
|
+
const result = spec[direction](value);
|
|
1164
|
+
if (result === null) {
|
|
1165
|
+
throw new WireParseError(`Unknown enum value '${value}'`);
|
|
1166
|
+
}
|
|
1167
|
+
return result;
|
|
1168
|
+
}
|
|
1169
|
+
var _ProtoWireToType = {
|
|
1170
|
+
_brand: "ProtoWireToType",
|
|
1171
|
+
createNotObjectError(loc, received) {
|
|
1172
|
+
return new WireReadError(`${loc}: Expected an object but received ${received}`);
|
|
1173
|
+
},
|
|
1174
|
+
applyField(typeName, desc, input, strategy) {
|
|
1175
|
+
const from = desc.wire ?? desc.type;
|
|
1176
|
+
const to = desc.type;
|
|
1177
|
+
const raw = Object.hasOwn(input, from) ? input[from] : void 0;
|
|
1178
|
+
try {
|
|
1179
|
+
return [to, (desc.transform ?? _identity)(strategy, raw)];
|
|
1180
|
+
} catch (e) {
|
|
1181
|
+
if (e instanceof WireParseError)
|
|
1182
|
+
throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
|
|
1183
|
+
throw e;
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
translateDecimal(value) {
|
|
1187
|
+
if (value === null || value === void 0) return void 0;
|
|
1188
|
+
if (typeof value !== "object" || !("value" in value)) {
|
|
1189
|
+
throw new WireParseError(
|
|
1190
|
+
`Cannot parse ${typeof value} as Decimal \u2014 expected {value: string}`
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
const raw = String(value.value);
|
|
1194
|
+
try {
|
|
1195
|
+
return Decimal.from(raw);
|
|
1196
|
+
} catch {
|
|
1197
|
+
throw new WireParseError(`Cannot parse '${raw}' as Decimal`);
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
translateDateTime(value) {
|
|
1201
|
+
if (value === null || value === void 0) return void 0;
|
|
1202
|
+
if (typeof value !== "string") {
|
|
1203
|
+
throw new WireParseError(`Cannot parse ${typeof value} as Date \u2014 expected string`);
|
|
1204
|
+
}
|
|
1205
|
+
return parseDateString(value);
|
|
1206
|
+
},
|
|
1207
|
+
translateEnum(spec, value) {
|
|
1208
|
+
if (value === null || value === void 0) return void 0;
|
|
1209
|
+
return enumLookup(spec, value, "fromWire");
|
|
1210
|
+
},
|
|
1211
|
+
applyUnion(descriptor, input) {
|
|
1212
|
+
if (input === null || input === void 0) {
|
|
1213
|
+
throw this.createNotObjectError(descriptor.typeName || "union", String(input));
|
|
1214
|
+
}
|
|
1215
|
+
if (typeof input !== "object") {
|
|
1216
|
+
throw this.createNotObjectError(descriptor.typeName || "union", typeof input);
|
|
1217
|
+
}
|
|
1218
|
+
const wire = input;
|
|
1219
|
+
for (const branch of descriptor.branches) {
|
|
1220
|
+
if (Object.hasOwn(wire, branch.wireKey) && wire[branch.wireKey] !== null && wire[branch.wireKey] !== void 0) {
|
|
1221
|
+
const branchData = _apply(
|
|
1222
|
+
new _ShapeDescriptor(descriptor.typeName, branch.shape),
|
|
1223
|
+
this,
|
|
1224
|
+
wire[branch.wireKey]
|
|
1225
|
+
);
|
|
1226
|
+
return { [descriptor.discriminantFieldName]: branch.typeKey, ...branchData };
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
const knownWireKeys = new Set(descriptor.branches.map((b) => b.wireKey));
|
|
1230
|
+
for (const key of Object.keys(wire)) {
|
|
1231
|
+
if (!knownWireKeys.has(key) && wire[key] !== null && wire[key] !== void 0) {
|
|
1232
|
+
const otherFieldName = otherFieldNameFor(descriptor.discriminantFieldName);
|
|
1233
|
+
return { [descriptor.discriminantFieldName]: "other", [otherFieldName]: key };
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
const loc = descriptor.typeName || "union";
|
|
1237
|
+
throw new WireReadError(`${loc}: No variant set`);
|
|
1238
|
+
},
|
|
1239
|
+
applyOneofField(typeName, oneof, input, strategy, result, excludeWireKeys) {
|
|
1240
|
+
applyOneofFieldIncoming(typeName, oneof, input, strategy, result, excludeWireKeys);
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
var _TypeToProtoWire = {
|
|
1244
|
+
_brand: "TypeToProtoWire",
|
|
1245
|
+
createNotObjectError(loc, received) {
|
|
1246
|
+
return new WireWriteError(`${loc}: Expected an object but received ${received}`);
|
|
1247
|
+
},
|
|
1248
|
+
applyField(typeName, desc, input, strategy) {
|
|
1249
|
+
const from = desc.type;
|
|
1250
|
+
const to = desc.wire ?? desc.type;
|
|
1251
|
+
const raw = Object.hasOwn(input, from) ? input[from] : void 0;
|
|
1252
|
+
try {
|
|
1253
|
+
return [to, (desc.transform ?? _identity)(strategy, raw)];
|
|
1254
|
+
} catch (e) {
|
|
1255
|
+
if (e instanceof WireParseError)
|
|
1256
|
+
throw new WireWriteError(`${typeName}.${desc.type}: ${e.message}`);
|
|
1257
|
+
throw e;
|
|
1258
|
+
}
|
|
1259
|
+
},
|
|
1260
|
+
translateDecimal(value) {
|
|
1261
|
+
if (value === null || value === void 0) return void 0;
|
|
1262
|
+
if (!isDecimal(value)) {
|
|
1263
|
+
throw new WireParseError(
|
|
1264
|
+
`Cannot serialize ${typeof value} as Decimal \u2014 expected Decimal instance`
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
return { value: value.toString() };
|
|
1268
|
+
},
|
|
1269
|
+
translateDateTime(value) {
|
|
1270
|
+
if (value === null || value === void 0) return void 0;
|
|
1271
|
+
if (!(value instanceof Date)) {
|
|
1272
|
+
throw new WireParseError(
|
|
1273
|
+
`Cannot serialize ${typeof value} as Date \u2014 expected Date instance`
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
if (isNaN(value.getTime())) {
|
|
1277
|
+
throw new WireParseError(`Cannot serialize invalid Date (NaN time value)`);
|
|
1278
|
+
}
|
|
1279
|
+
return value.toISOString();
|
|
1280
|
+
},
|
|
1281
|
+
translateEnum(spec, value) {
|
|
1282
|
+
if (value === null || value === void 0) return void 0;
|
|
1283
|
+
return enumLookup(spec, value, "toWire");
|
|
1284
|
+
},
|
|
1285
|
+
applyUnion(descriptor, input) {
|
|
1286
|
+
if (input === null || input === void 0) {
|
|
1287
|
+
throw this.createNotObjectError(descriptor.typeName || "union", String(input));
|
|
1288
|
+
}
|
|
1289
|
+
if (typeof input !== "object") {
|
|
1290
|
+
throw this.createNotObjectError(descriptor.typeName || "union", typeof input);
|
|
1291
|
+
}
|
|
1292
|
+
const sdk = input;
|
|
1293
|
+
const discriminant = sdk[descriptor.discriminantFieldName];
|
|
1294
|
+
if (typeof discriminant !== "string") {
|
|
1295
|
+
const loc = descriptor.typeName || "union";
|
|
1296
|
+
throw new WireWriteError(
|
|
1297
|
+
`${loc}: Expected a string '${descriptor.discriminantFieldName}' discriminant but received ${discriminant === void 0 ? "undefined" : typeof discriminant}`
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
if (discriminant === "other") {
|
|
1301
|
+
const loc = descriptor.typeName || "union";
|
|
1302
|
+
throw new WireWriteError(
|
|
1303
|
+
`${loc}: Cannot serialize 'other' variant back to wire format`
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1306
|
+
const branch = descriptor.branches.find((b) => b.typeKey === discriminant);
|
|
1307
|
+
if (!branch) {
|
|
1308
|
+
const loc = descriptor.typeName || "union";
|
|
1309
|
+
throw new WireWriteError(`${loc}: Unknown variant '${discriminant}'`);
|
|
1310
|
+
}
|
|
1311
|
+
const branchData = _apply(
|
|
1312
|
+
new _ShapeDescriptor(descriptor.typeName, branch.shape),
|
|
1313
|
+
this,
|
|
1314
|
+
sdk
|
|
1315
|
+
);
|
|
1316
|
+
return { [branch.wireKey]: branchData };
|
|
1317
|
+
},
|
|
1318
|
+
applyOneofField(typeName, oneof, input, strategy, result, _excludeWireKeys) {
|
|
1319
|
+
applyOneofFieldOutgoing(typeName, oneof, input, strategy, result);
|
|
1320
|
+
}
|
|
1321
|
+
};
|
|
1322
|
+
function _configAppContextFromContext(ctx) {
|
|
1323
|
+
if (typeof ctx !== "object" || ctx === null || !("clockTime" in ctx)) {
|
|
1324
|
+
return {};
|
|
1325
|
+
}
|
|
1326
|
+
const raw = ctx.clockTime;
|
|
1327
|
+
if (raw === void 0 || raw === null) return {};
|
|
1328
|
+
if (typeof raw !== "string") {
|
|
1329
|
+
throw new WireParseError(
|
|
1330
|
+
`Expected clockTime to be a string but received ${typeof raw}`
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
return { clockTime: raw };
|
|
1334
|
+
}
|
|
1335
|
+
var _JsonWireToType = {
|
|
1336
|
+
_brand: "JsonWireToType",
|
|
1337
|
+
createNotObjectError(loc, received) {
|
|
1338
|
+
return new WireReadError(`${loc}: Expected an object but received ${received}`);
|
|
1339
|
+
},
|
|
1340
|
+
applyField(typeName, desc, input, strategy) {
|
|
1341
|
+
const key = desc.type;
|
|
1342
|
+
const raw = Object.hasOwn(input, key) ? input[key] : void 0;
|
|
1343
|
+
try {
|
|
1344
|
+
return [key, (desc.transform ?? _identity)(strategy, raw)];
|
|
1345
|
+
} catch (e) {
|
|
1346
|
+
if (e instanceof WireParseError)
|
|
1347
|
+
throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
|
|
1348
|
+
throw e;
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
translateDecimal(value) {
|
|
1352
|
+
if (value === null || value === void 0) return void 0;
|
|
1353
|
+
if (typeof value === "string") {
|
|
1354
|
+
try {
|
|
1355
|
+
return Decimal.from(value);
|
|
1356
|
+
} catch {
|
|
1357
|
+
throw new WireParseError(`Cannot parse '${value}' as Decimal`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
if (typeof value === "number") {
|
|
1361
|
+
if (!isFinite(value)) {
|
|
1362
|
+
throw new WireParseError(
|
|
1363
|
+
`Expected a string or finite number but received ${typeof value}`
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
return Decimal.from(value);
|
|
1367
|
+
}
|
|
1368
|
+
throw new WireParseError(
|
|
1369
|
+
`Expected a string or finite number but received ${typeof value}`
|
|
1370
|
+
);
|
|
1371
|
+
},
|
|
1372
|
+
translateDateTime(value) {
|
|
1373
|
+
if (value === null || value === void 0) return void 0;
|
|
1374
|
+
if (typeof value !== "string") {
|
|
1375
|
+
throw new WireParseError(`Cannot parse ${typeof value} as Date \u2014 expected string`);
|
|
1376
|
+
}
|
|
1377
|
+
return parseDateString(value);
|
|
1378
|
+
},
|
|
1379
|
+
translateEnum(spec, value) {
|
|
1380
|
+
if (value === null || value === void 0) return void 0;
|
|
1381
|
+
return enumLookup(spec, value, "fromWire");
|
|
1382
|
+
},
|
|
1383
|
+
applyUnion() {
|
|
1384
|
+
throw new Error("applyUnion is not supported for JsonWireToType");
|
|
1385
|
+
},
|
|
1386
|
+
applyOneofField() {
|
|
1387
|
+
throw new Error("applyOneofField is not supported for JsonWireToType");
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
function applyOneofFieldIncoming(typeName, oneof, input, strategy, result, excludeWireKeys) {
|
|
1391
|
+
for (const branch of oneof.branches) {
|
|
1392
|
+
const raw = Object.hasOwn(input, branch.wireKey) ? input[branch.wireKey] : void 0;
|
|
1393
|
+
if (raw !== null && raw !== void 0) {
|
|
1394
|
+
result[oneof.discriminant] = branch.typeKey;
|
|
1395
|
+
try {
|
|
1396
|
+
const transformed = branch.transform ? branch.transform(strategy, raw) : raw;
|
|
1397
|
+
if (transformed !== void 0) {
|
|
1398
|
+
result[branch.typeKey] = transformed;
|
|
1399
|
+
}
|
|
1400
|
+
} catch (e) {
|
|
1401
|
+
if (e instanceof WireParseError) {
|
|
1402
|
+
throw new WireReadError(
|
|
1403
|
+
`${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
throw e;
|
|
1407
|
+
}
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
const knownWireKeys = new Set(oneof.branches.map((b) => b.wireKey));
|
|
1412
|
+
for (const key of Object.keys(input)) {
|
|
1413
|
+
if (!knownWireKeys.has(key) && !excludeWireKeys.has(key) && input[key] !== null && input[key] !== void 0) {
|
|
1414
|
+
result[oneof.discriminant] = "other";
|
|
1415
|
+
result[otherFieldNameFor(oneof.discriminant)] = key;
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
if (!oneof.optional) {
|
|
1420
|
+
throw new WireReadError(`${typeName}.${oneof.discriminant}: no variant set`);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
function applyOneofFieldOutgoing(typeName, oneof, input, strategy, result) {
|
|
1424
|
+
const discriminant = Object.hasOwn(input, oneof.discriminant) ? input[oneof.discriminant] : void 0;
|
|
1425
|
+
if (discriminant === void 0 || discriminant === null) {
|
|
1426
|
+
if (!oneof.optional) {
|
|
1427
|
+
throw new WireWriteError(`${typeName}.${oneof.discriminant}: no variant set`);
|
|
1428
|
+
}
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
if (typeof discriminant !== "string") {
|
|
1432
|
+
throw new WireWriteError(
|
|
1433
|
+
`${typeName}.${oneof.discriminant}: expected string discriminant but received ${typeof discriminant}`
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
if (discriminant === "other") {
|
|
1437
|
+
throw new WireWriteError(
|
|
1438
|
+
`${typeName}.${oneof.discriminant}: cannot serialize 'other' variant back to wire format`
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
const branch = oneof.branches.find((b) => b.typeKey === discriminant);
|
|
1442
|
+
if (!branch) {
|
|
1443
|
+
throw new WireWriteError(
|
|
1444
|
+
`${typeName}.${oneof.discriminant}: unknown variant '${discriminant}'`
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
const raw = Object.hasOwn(input, branch.typeKey) ? input[branch.typeKey] : void 0;
|
|
1448
|
+
try {
|
|
1449
|
+
const transformed = branch.transform ? branch.transform(strategy, raw) : raw;
|
|
1450
|
+
result[branch.wireKey] = transformed ?? {};
|
|
1451
|
+
} catch (e) {
|
|
1452
|
+
if (e instanceof WireParseError) {
|
|
1453
|
+
throw new WireWriteError(
|
|
1454
|
+
`${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
throw e;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
function createJsonWireToType(appCtx) {
|
|
1461
|
+
return {
|
|
1462
|
+
..._JsonWireToType,
|
|
1463
|
+
translateDateTime(value) {
|
|
1464
|
+
if (value === null || value === void 0) {
|
|
1465
|
+
if (appCtx.clockTime !== void 0) {
|
|
1466
|
+
return parseDateString(appCtx.clockTime);
|
|
1467
|
+
}
|
|
1468
|
+
return void 0;
|
|
1469
|
+
}
|
|
1470
|
+
return _JsonWireToType.translateDateTime(value);
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
function _applyIncoming(descriptor, inputObject) {
|
|
1475
|
+
return _apply(descriptor, _ProtoWireToType, inputObject);
|
|
1476
|
+
}
|
|
1477
|
+
function _applyOutgoing(descriptor, inputObject) {
|
|
1478
|
+
return _apply(descriptor, _TypeToProtoWire, inputObject);
|
|
1479
|
+
}
|
|
1480
|
+
function _applyConfig(descriptor, inputObject, appCtx) {
|
|
1481
|
+
const strategy = appCtx?.clockTime !== void 0 ? createJsonWireToType(appCtx) : _JsonWireToType;
|
|
1482
|
+
return _apply(descriptor, strategy, inputObject);
|
|
1483
|
+
}
|
|
1484
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1485
|
+
0 && (module.exports = {
|
|
1486
|
+
DEFAULT_DIV_PRECISION,
|
|
1487
|
+
Decimal,
|
|
1488
|
+
DecimalRoundingPresets,
|
|
1489
|
+
Integer,
|
|
1490
|
+
PositiveInteger,
|
|
1491
|
+
Ref,
|
|
1492
|
+
StreetAddress,
|
|
1493
|
+
Timestamp,
|
|
1494
|
+
WireReadError,
|
|
1495
|
+
WireWriteError,
|
|
1496
|
+
_ConfigEnum,
|
|
1497
|
+
_JsonWireToType,
|
|
1498
|
+
_ProtoEnum,
|
|
1499
|
+
_ProtoWireToType,
|
|
1500
|
+
_ShapeDescriptor,
|
|
1501
|
+
_TypeToProtoWire,
|
|
1502
|
+
_UnionDescriptor,
|
|
1503
|
+
_apply,
|
|
1504
|
+
_applyConfig,
|
|
1505
|
+
_applyIncoming,
|
|
1506
|
+
_applyOutgoing,
|
|
1507
|
+
_configAppContextFromContext,
|
|
1508
|
+
_identity,
|
|
1509
|
+
_isPromiseLike,
|
|
1510
|
+
_required,
|
|
1511
|
+
_translateArray,
|
|
1512
|
+
_translateDateTime,
|
|
1513
|
+
_translateDecimal,
|
|
1514
|
+
_translateEnum,
|
|
1515
|
+
_translateMap,
|
|
1516
|
+
_translateShape,
|
|
1517
|
+
_translateUnion,
|
|
1518
|
+
isDecimal
|
|
1519
|
+
});
|