@stripe/extensibility-sdk 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +355 -0
  2. package/dist/config-values/generate.d.ts +2 -0
  3. package/dist/config-values/generate.d.ts.map +1 -1
  4. package/dist/extensibility-sdk-alpha.d.ts +140 -38
  5. package/dist/extensibility-sdk-beta.d.ts +140 -38
  6. package/dist/extensibility-sdk-extensions-alpha.d.ts +155 -25
  7. package/dist/extensibility-sdk-extensions-beta.d.ts +155 -25
  8. package/dist/extensibility-sdk-extensions-internal.d.ts +159 -25
  9. package/dist/extensibility-sdk-extensions-public.d.ts +155 -25
  10. package/dist/extensibility-sdk-internal-alpha.d.ts +5 -0
  11. package/dist/extensibility-sdk-internal-beta.d.ts +5 -0
  12. package/dist/extensibility-sdk-internal-internal.d.ts +5 -0
  13. package/dist/extensibility-sdk-internal-public.d.ts +5 -0
  14. package/dist/extensibility-sdk-internal.d.ts +139 -40
  15. package/dist/extensibility-sdk-public.d.ts +140 -38
  16. package/dist/extensibility-sdk-stdlib-alpha.d.ts +145 -38
  17. package/dist/extensibility-sdk-stdlib-beta.d.ts +145 -38
  18. package/dist/extensibility-sdk-stdlib-internal.d.ts +144 -40
  19. package/dist/extensibility-sdk-stdlib-public.d.ts +145 -38
  20. package/dist/extensions/billing/bill/discount_calculation.d.ts +5 -3
  21. package/dist/extensions/billing/customer_balance_application.d.ts +3 -1
  22. package/dist/extensions/billing/invoice_collection_setting.d.ts +15 -11
  23. package/dist/extensions/billing/prorations.d.ts +30 -21
  24. package/dist/extensions/billing/recurring_billing_item_handling.d.ts +41 -23
  25. package/dist/extensions/billing/types.d.ts +4 -4
  26. package/dist/extensions/core/workflows/custom_action.d.ts +6 -2
  27. package/dist/extensions/extend/workflows/custom_action.d.ts +6 -2
  28. package/dist/index.cjs +385 -134
  29. package/dist/index.js +383 -133
  30. package/dist/internal.d.ts +4 -0
  31. package/dist/internal.d.ts.map +1 -1
  32. package/dist/stdlib/brand.d.ts +16 -10
  33. package/dist/stdlib/brand.d.ts.map +1 -1
  34. package/dist/stdlib/decimal.d.ts +49 -21
  35. package/dist/stdlib/decimal.d.ts.map +1 -1
  36. package/dist/stdlib/index.cjs +385 -134
  37. package/dist/stdlib/index.d.ts +10 -4
  38. package/dist/stdlib/index.d.ts.map +1 -1
  39. package/dist/stdlib/index.js +383 -133
  40. package/dist/stdlib/refs.d.ts +21 -7
  41. package/dist/stdlib/scalars.d.ts +61 -28
  42. package/dist/stdlib/scalars.d.ts.map +1 -1
  43. package/dist/stdlib/to-const.d.ts +35 -0
  44. package/dist/stdlib/to-const.d.ts.map +1 -0
  45. package/dist/stdlib/type-utils.d.ts +3 -1
  46. package/dist/stdlib/types.d.ts +6 -6
  47. package/dist/tsconfig.build.tsbuildinfo +1 -1
  48. package/package.json +11 -11
  49. package/dist/api-surface.d.ts.map +0 -1
@@ -1,116 +1,5 @@
1
1
  // src/stdlib/scalars.ts
2
2
  import "@formspec/core";
3
- function roundToInteger(value, direction) {
4
- switch (direction) {
5
- case "ceil":
6
- return Math.ceil(value);
7
- case "floor":
8
- return Math.floor(value);
9
- case "round-down":
10
- return Math.trunc(value);
11
- case "round-up":
12
- return value >= 0 ? Math.ceil(value) : Math.floor(value);
13
- case "half-up":
14
- return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
15
- default: {
16
- const _exhaustive = direction;
17
- throw new Error(`Unknown rounding direction: ${String(_exhaustive)}`);
18
- }
19
- }
20
- }
21
- var Integer = {
22
- /**
23
- * Type guard that narrows a `number` to {@link (Integer:type)}.
24
- *
25
- * @example
26
- * ```ts
27
- * const n: number = getCount();
28
- * if (Integer.is(n)) {
29
- * // n is Integer here
30
- * config.retryCount = n;
31
- * }
32
- * ```
33
- * @public
34
- */
35
- is: (value) => Number.isInteger(value),
36
- /**
37
- * Coerces a number to an {@link (Integer:type)} by rounding.
38
- * Throws if the value is not finite.
39
- *
40
- * @example
41
- * ```ts
42
- * const price = 9.99;
43
- * const rounded = Integer.from(price, 'floor'); // 9
44
- * const ceiled = Integer.from(price, 'ceil'); // 10
45
- * ```
46
- * @public
47
- */
48
- from: (value, rounding) => {
49
- if (!Number.isFinite(value)) {
50
- throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
51
- }
52
- return roundToInteger(value, rounding);
53
- }
54
- };
55
- var PositiveInteger = {
56
- /**
57
- * Type guard that narrows a `number` to {@link (PositiveInteger:type)}.
58
- *
59
- * @example
60
- * ```ts
61
- * const n: number = getRetryCount();
62
- * if (PositiveInteger.is(n)) {
63
- * // n is PositiveInteger here
64
- * config.maxRetries = n;
65
- * }
66
- * ```
67
- * @public
68
- */
69
- is: (value) => Number.isInteger(value) && value >= 0,
70
- /**
71
- * Coerces a number to a {@link (PositiveInteger:type)} by rounding.
72
- * Throws if the value is not finite or the rounded result is negative.
73
- *
74
- * @example
75
- * ```ts
76
- * const ratio = 2.7;
77
- * const count = PositiveInteger.from(ratio, 'floor'); // 2
78
- * ```
79
- * @public
80
- */
81
- from: (value, rounding) => {
82
- if (!Number.isFinite(value)) {
83
- throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
84
- }
85
- const rounded = roundToInteger(value, rounding) || 0;
86
- if (rounded < 0) {
87
- throw new Error(
88
- `Value ${String(value)} rounds to ${String(rounded)}, which is negative`
89
- );
90
- }
91
- return rounded;
92
- }
93
- };
94
- var StreetAddress = {
95
- create: (address) => {
96
- return address;
97
- }
98
- };
99
- var Timestamp = {
100
- create: (value) => {
101
- return value;
102
- }
103
- };
104
-
105
- // src/stdlib/refs.ts
106
- var Ref = {
107
- create: (step) => {
108
- return {
109
- type: step.object,
110
- id: step.id
111
- };
112
- }
113
- };
114
3
 
115
4
  // src/stdlib/decimal.ts
116
5
  var PLAIN_NOTATION_DIGIT_LIMIT = 30;
@@ -127,6 +16,9 @@ var DecimalRoundingPresets = Object.freeze({
127
16
  var DEFAULT_DIV_PRECISION = 34;
128
17
  var IMPLICIT_DECIMAL_COERCION_ERROR = "Implicit Decimal coercion is not allowed; use .add(), .sub(), .mul(), .div(), .toString(), or .toNumber() explicitly.";
129
18
  var MAX_EXPONENT = Number.MAX_SAFE_INTEGER;
19
+ function normalizeZero(value) {
20
+ return Object.is(value, -0) ? 0 : value;
21
+ }
130
22
  var DECIMAL_BRAND = /* @__PURE__ */ Symbol.for(
131
23
  "stripe.apps-extensibility-sdk.Decimal"
132
24
  );
@@ -240,13 +132,13 @@ var DecimalImpl = class _DecimalImpl {
240
132
  /**
241
133
  * Return the sum of this value and `other`.
242
134
  *
243
- * @param other - The addend.
135
+ * @param other - The addend. Accepts any {@link DecimalLike} value.
244
136
  * @returns A new {@link Decimal} equal to `this + other`.
245
137
  *
246
138
  * @public
247
139
  */
248
140
  add(other) {
249
- const otherImpl = toImpl(other);
141
+ const otherImpl = coerceToImpl(other);
250
142
  if (this.#exponent === otherImpl.#exponent) {
251
143
  return toDecimal(
252
144
  new _DecimalImpl(this.#coefficient + otherImpl.#coefficient, this.#exponent)
@@ -273,13 +165,13 @@ var DecimalImpl = class _DecimalImpl {
273
165
  /**
274
166
  * Return the difference of this value and `other`.
275
167
  *
276
- * @param other - The subtrahend.
168
+ * @param other - The subtrahend. Accepts any {@link DecimalLike} value.
277
169
  * @returns A new {@link Decimal} equal to `this - other`.
278
170
  *
279
171
  * @public
280
172
  */
281
173
  sub(other) {
282
- const otherImpl = toImpl(other);
174
+ const otherImpl = coerceToImpl(other);
283
175
  if (this.#exponent === otherImpl.#exponent) {
284
176
  return toDecimal(
285
177
  new _DecimalImpl(this.#coefficient - otherImpl.#coefficient, this.#exponent)
@@ -306,13 +198,13 @@ var DecimalImpl = class _DecimalImpl {
306
198
  /**
307
199
  * Return the product of this value and `other`.
308
200
  *
309
- * @param other - The multiplicand.
201
+ * @param other - The multiplicand. Accepts any {@link DecimalLike} value.
310
202
  * @returns A new {@link Decimal} equal to `this × other`.
311
203
  *
312
204
  * @public
313
205
  */
314
206
  mul(other) {
315
- const otherImpl = toImpl(other);
207
+ const otherImpl = coerceToImpl(other);
316
208
  return toDecimal(
317
209
  new _DecimalImpl(
318
210
  this.#coefficient * otherImpl.#coefficient,
@@ -339,7 +231,7 @@ var DecimalImpl = class _DecimalImpl {
339
231
  * Decimal.from('5').div(Decimal.from('2'), 0, 'half-even'); // "2"
340
232
  * ```
341
233
  *
342
- * @param other - The divisor. Must not be zero.
234
+ * @param other - The divisor. Must not be zero. Accepts any {@link DecimalLike} value.
343
235
  * @param precision - Maximum number of decimal digits in the result.
344
236
  * @param direction - How to round when the exact quotient cannot
345
237
  * be represented at the requested precision.
@@ -354,7 +246,7 @@ var DecimalImpl = class _DecimalImpl {
354
246
  if (precision < 0 || !Number.isInteger(precision)) {
355
247
  throw new Error("precision must be a non-negative integer");
356
248
  }
357
- const otherImpl = toImpl(other);
249
+ const otherImpl = coerceToImpl(other);
358
250
  if (otherImpl.#coefficient === 0n) {
359
251
  throw new Error("Division by zero");
360
252
  }
@@ -396,13 +288,13 @@ var DecimalImpl = class _DecimalImpl {
396
288
  * a.cmp(a); // 0
397
289
  * ```
398
290
  *
399
- * @param other - The value to compare against.
291
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
400
292
  * @returns `-1` if `this < other`, `0` if equal, `1` if `this > other`.
401
293
  *
402
294
  * @public
403
295
  */
404
296
  cmp(other) {
405
- const otherImpl = toImpl(other);
297
+ const otherImpl = coerceToImpl(other);
406
298
  if (this.#exponent === otherImpl.#exponent) {
407
299
  if (this.#coefficient < otherImpl.#coefficient) return -1;
408
300
  if (this.#coefficient > otherImpl.#coefficient) return 1;
@@ -425,7 +317,7 @@ var DecimalImpl = class _DecimalImpl {
425
317
  /**
426
318
  * Return `true` if this value is numerically equal to `other`.
427
319
  *
428
- * @param other - The value to compare against.
320
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
429
321
  * @returns `true` if `this === other` in value, `false` otherwise.
430
322
  *
431
323
  * @public
@@ -436,7 +328,7 @@ var DecimalImpl = class _DecimalImpl {
436
328
  /**
437
329
  * Return `true` if this value is strictly less than `other`.
438
330
  *
439
- * @param other - The value to compare against.
331
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
440
332
  * @returns `true` if `this < other`, `false` otherwise.
441
333
  *
442
334
  * @public
@@ -447,7 +339,7 @@ var DecimalImpl = class _DecimalImpl {
447
339
  /**
448
340
  * Return `true` if this value is less than or equal to `other`.
449
341
  *
450
- * @param other - The value to compare against.
342
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
451
343
  * @returns `true` if `this ≤ other`, `false` otherwise.
452
344
  *
453
345
  * @public
@@ -458,7 +350,7 @@ var DecimalImpl = class _DecimalImpl {
458
350
  /**
459
351
  * Return `true` if this value is strictly greater than `other`.
460
352
  *
461
- * @param other - The value to compare against.
353
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
462
354
  * @returns `true` if `this > other`, `false` otherwise.
463
355
  *
464
356
  * @public
@@ -469,7 +361,7 @@ var DecimalImpl = class _DecimalImpl {
469
361
  /**
470
362
  * Return `true` if this value is greater than or equal to `other`.
471
363
  *
472
- * @param other - The value to compare against.
364
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
473
365
  * @returns `true` if `this ≥ other`, `false` otherwise.
474
366
  *
475
367
  * @public
@@ -768,6 +660,38 @@ var DecimalImpl = class _DecimalImpl {
768
660
  return formatFixed(scaled);
769
661
  }
770
662
  }
663
+ /**
664
+ * Convert this value to an {@link (Integer:type)} by rounding.
665
+ *
666
+ * @remarks
667
+ * The rounding direction is always required — no invisible defaults
668
+ * in financial code.
669
+ *
670
+ * @example
671
+ * ```ts
672
+ * Decimal.from('2.7').toInteger('floor'); // 2
673
+ * Decimal.from('2.5').toInteger('half-up'); // 3
674
+ * Decimal.from('2.5').toInteger('half-even'); // 2
675
+ * ```
676
+ *
677
+ * @param direction - How to round when the value is not a whole number.
678
+ * @returns A branded {@link (Integer:type)} value.
679
+ * @throws Error if the rounded value is too large to represent as
680
+ * a JavaScript `number`.
681
+ *
682
+ * @public
683
+ */
684
+ toInteger(direction) {
685
+ const fixed = this.toFixed(0, direction);
686
+ const num = Number(fixed);
687
+ if (!Number.isFinite(num) || !Number.isSafeInteger(num)) {
688
+ throw new Error(
689
+ `Decimal value ${fixed} cannot be exactly represented as a JavaScript integer`
690
+ );
691
+ }
692
+ const normalized = normalizeZero(num);
693
+ return normalized;
694
+ }
771
695
  /**
772
696
  * Reject implicit arithmetic-style coercion while preserving explicit
773
697
  * stringification.
@@ -808,23 +732,59 @@ var DecimalImpl = class _DecimalImpl {
808
732
  function toImpl(d) {
809
733
  return d;
810
734
  }
735
+ function coerceToImpl(value) {
736
+ if (isDecimal(value)) {
737
+ return toImpl(value);
738
+ }
739
+ return toImpl(Decimal.from(value));
740
+ }
811
741
  function toDecimal(impl) {
812
742
  return impl;
813
743
  }
814
744
  function isDecimal(value) {
815
- return typeof value === "object" && value !== null && DECIMAL_BRAND in value;
745
+ return typeof value === "object" && value !== null && DECIMAL_BRAND in value && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- symbol key access requires cast
746
+ value[DECIMAL_BRAND] === true;
747
+ }
748
+ function assertIsDecimal(value) {
749
+ if (!isDecimal(value)) {
750
+ throw new Error(`Expected a Decimal, got ${typeof value}`);
751
+ }
816
752
  }
817
753
  var Decimal = {
818
754
  /**
819
- * Create a `Decimal` from a string, number, or bigint.
755
+ * Type guard that narrows an unknown value to {@link (Decimal:type)}.
756
+ *
757
+ * @example
758
+ * ```ts
759
+ * if (Decimal.is(value)) {
760
+ * value.add(1); // value is Decimal
761
+ * }
762
+ * ```
763
+ * @public
764
+ */
765
+ is: isDecimal,
766
+ /**
767
+ * Assertion guard that throws if the value is not a {@link (Decimal:type)}.
768
+ *
769
+ * @example
770
+ * ```ts
771
+ * Decimal.assert(value);
772
+ * value.add(1); // value is Decimal
773
+ * ```
774
+ * @public
775
+ */
776
+ assert: assertIsDecimal,
777
+ /**
778
+ * Create a `Decimal` from a string, number, bigint, Integer, or Decimal.
820
779
  *
821
780
  * @remarks
781
+ * - **Decimal**: returned as-is (immutable passthrough).
822
782
  * - **string**: Parsed as a decimal literal. Accepts an optional sign,
823
783
  * integer digits, an optional fractional part, and an optional `e`/`E`
824
784
  * exponent. Leading/trailing whitespace is trimmed.
825
- * - **number**: Must be finite. Converted via `Number.prototype.toString()`
826
- * then parsed, so `Decimal.from(0.1)` produces `"0.1"` (not the
827
- * 53-bit binary approximation).
785
+ * - **number** (including Integer): Must be finite. Converted via
786
+ * `Number.prototype.toString()` then parsed, so `Decimal.from(0.1)`
787
+ * produces `"0.1"` (not the 53-bit binary approximation).
828
788
  * - **bigint**: Treated as an integer with exponent 0.
829
789
  *
830
790
  * @example
@@ -833,16 +793,21 @@ var Decimal = {
833
793
  * Decimal.from(42); // number
834
794
  * Decimal.from(100n); // bigint
835
795
  * Decimal.from('1.5e3'); // scientific notation → 1500
796
+ * Decimal.from(d); // Decimal passthrough
836
797
  * ```
837
798
  *
838
799
  * @param value - The value to convert.
839
- * @returns A new frozen `Decimal` instance.
800
+ * @returns A new frozen `Decimal` instance (or the same instance if
801
+ * already a Decimal).
840
802
  * @throws Error if `value` is a non-finite number, an empty
841
803
  * string, or a string that does not match the decimal literal grammar.
842
804
  *
843
805
  * @public
844
806
  */
845
807
  from(value) {
808
+ if (isDecimal(value)) {
809
+ return value;
810
+ }
846
811
  if (typeof value === "bigint") {
847
812
  return toDecimal(new DecimalImpl(value, 0));
848
813
  }
@@ -891,6 +856,273 @@ var Decimal = {
891
856
  zero: toDecimal(new DecimalImpl(0n, 0))
892
857
  };
893
858
 
859
+ // src/stdlib/scalars.ts
860
+ function roundToInteger(value, direction) {
861
+ switch (direction) {
862
+ case "ceil":
863
+ return Math.ceil(value);
864
+ case "floor":
865
+ return Math.floor(value);
866
+ case "round-down":
867
+ return Math.trunc(value);
868
+ case "round-up":
869
+ return value >= 0 ? Math.ceil(value) : Math.floor(value);
870
+ case "half-up":
871
+ return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
872
+ default: {
873
+ const _exhaustive = direction;
874
+ throw new Error(`Unknown rounding direction: ${String(_exhaustive)}`);
875
+ }
876
+ }
877
+ }
878
+ function normalizeZero2(value) {
879
+ return Object.is(value, -0) ? 0 : value;
880
+ }
881
+ function assertIsInteger(value) {
882
+ if (!(typeof value === "number" && Number.isInteger(value))) {
883
+ throw new Error(
884
+ `Expected an integer, got ${typeof value === "number" ? String(value) : typeof value}`
885
+ );
886
+ }
887
+ }
888
+ function assertIsPositiveInteger(value) {
889
+ if (!(typeof value === "number" && Number.isInteger(value) && value >= 0)) {
890
+ throw new Error(
891
+ `Expected a non-negative integer, got ${typeof value === "number" ? String(value) : typeof value}`
892
+ );
893
+ }
894
+ }
895
+ function assertIntegerIsPositive(value) {
896
+ if (value < 0) {
897
+ throw new Error(`Expected a non-negative integer, got ${String(value)}`);
898
+ }
899
+ }
900
+ var Integer = {
901
+ /**
902
+ * The `Integer` value representing zero.
903
+ *
904
+ * @remarks
905
+ * Pre-allocated singleton — prefer `Integer.zero` over
906
+ * `Integer.from(0, 'floor')` to avoid an unnecessary call.
907
+ *
908
+ * @public
909
+ */
910
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-type-assertion -- branded type construction: 0 is trivially an integer
911
+ zero: 0,
912
+ /**
913
+ * Type guard that narrows an unknown value to {@link (Integer:type)}.
914
+ *
915
+ * @example
916
+ * ```ts
917
+ * const n: unknown = getCount();
918
+ * if (Integer.is(n)) {
919
+ * // n is Integer here
920
+ * config.retryCount = n;
921
+ * }
922
+ * ```
923
+ * @public
924
+ */
925
+ is: (value) => typeof value === "number" && Number.isInteger(value),
926
+ /**
927
+ * Assertion guard that throws if the value is not an {@link (Integer:type)}.
928
+ *
929
+ * @example
930
+ * ```ts
931
+ * const n: unknown = getCount();
932
+ * Integer.assert(n);
933
+ * // n is Integer here
934
+ * ```
935
+ * @public
936
+ */
937
+ assert: assertIsInteger,
938
+ /**
939
+ * Coerces a value to an {@link (Integer:type)} by rounding.
940
+ *
941
+ * @remarks
942
+ * Accepts `number`, `string`, `Decimal`, or `Integer`. The rounding
943
+ * direction is always required — no invisible defaults.
944
+ *
945
+ * - **number** (including Integer): must be finite and round to a
946
+ * safe integer (`Number.isSafeInteger`). IEEE 754 negative zero is
947
+ * normalized to positive zero.
948
+ * - **string**: must be a valid numeric literal (not empty/whitespace).
949
+ * Parsed via `Number()`, then rounded. The result must be a safe integer.
950
+ * - **Decimal**: delegated to {@link Decimal.toInteger | Decimal.toInteger()}.
951
+ *
952
+ * @example
953
+ * ```ts
954
+ * Integer.from(9.99, 'floor'); // 9
955
+ * Integer.from('1.5', 'ceil'); // 2
956
+ * Integer.from(Decimal.from('2.7'), 'half-up'); // 3
957
+ * ```
958
+ *
959
+ * @throws Error if the value is non-finite, an empty string, an
960
+ * unparseable string, or rounds to a value outside the safe integer range.
961
+ *
962
+ * @public
963
+ */
964
+ from(value, rounding) {
965
+ if (typeof value === "number") {
966
+ if (!Number.isFinite(value)) {
967
+ throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
968
+ }
969
+ const rounded = normalizeZero2(roundToInteger(value, rounding));
970
+ if (!Number.isSafeInteger(rounded)) {
971
+ throw new Error(
972
+ `Value ${String(value)} rounds to ${String(rounded)}, which is outside the safe integer range`
973
+ );
974
+ }
975
+ return rounded;
976
+ }
977
+ if (typeof value === "string") {
978
+ if (value.trim() === "") {
979
+ throw new Error("Cannot parse empty string as an integer");
980
+ }
981
+ const num = Number(value);
982
+ if (!Number.isFinite(num)) {
983
+ throw new Error(
984
+ `Cannot parse "${value}" as a finite number for integer conversion`
985
+ );
986
+ }
987
+ const rounded = normalizeZero2(roundToInteger(num, rounding));
988
+ if (!Number.isSafeInteger(rounded)) {
989
+ throw new Error(
990
+ `Value "${value}" rounds to ${String(rounded)}, which is outside the safe integer range`
991
+ );
992
+ }
993
+ return rounded;
994
+ }
995
+ if (isDecimal(value)) {
996
+ return value.toInteger(rounding);
997
+ }
998
+ throw new Error(
999
+ `Cannot convert ${typeof value} to Integer; expected string, number, or Decimal`
1000
+ );
1001
+ },
1002
+ /**
1003
+ * Convert an {@link (Integer:type)} to a {@link (Decimal:type)}.
1004
+ *
1005
+ * @remarks
1006
+ * This conversion is lossless — every JavaScript integer is exactly
1007
+ * representable as a Decimal.
1008
+ *
1009
+ * @example
1010
+ * ```ts
1011
+ * const dec = Integer.toDecimal(Integer.from(42, 'floor'));
1012
+ * dec.add(Decimal.from('0.5')); // 42.5
1013
+ * ```
1014
+ * @public
1015
+ */
1016
+ toDecimal(value) {
1017
+ return Decimal.from(value);
1018
+ },
1019
+ /**
1020
+ * Type guard that narrows an {@link (Integer:type)} to {@link (PositiveInteger:type)}.
1021
+ *
1022
+ * @example
1023
+ * ```ts
1024
+ * const n = Integer.from(count, 'floor');
1025
+ * if (Integer.isPositive(n)) {
1026
+ * // n is PositiveInteger here
1027
+ * }
1028
+ * ```
1029
+ * @public
1030
+ */
1031
+ isPositive: (value) => value >= 0,
1032
+ /**
1033
+ * Assertion guard that throws if an {@link (Integer:type)} is not a {@link (PositiveInteger:type)}.
1034
+ *
1035
+ * @example
1036
+ * ```ts
1037
+ * const n = Integer.from(count, 'floor');
1038
+ * Integer.assertIsPositive(n);
1039
+ * // n is PositiveInteger here
1040
+ * ```
1041
+ * @public
1042
+ */
1043
+ assertIsPositive: assertIntegerIsPositive
1044
+ };
1045
+ var PositiveInteger = {
1046
+ /**
1047
+ * Type guard that narrows an unknown value to {@link (PositiveInteger:type)}.
1048
+ *
1049
+ * @example
1050
+ * ```ts
1051
+ * const n: unknown = getRetryCount();
1052
+ * if (PositiveInteger.is(n)) {
1053
+ * // n is PositiveInteger here
1054
+ * config.maxRetries = n;
1055
+ * }
1056
+ * ```
1057
+ * @public
1058
+ */
1059
+ is: (value) => typeof value === "number" && Number.isInteger(value) && value >= 0,
1060
+ /**
1061
+ * Assertion guard that throws if the value is not a {@link (PositiveInteger:type)}.
1062
+ *
1063
+ * @example
1064
+ * ```ts
1065
+ * const n: unknown = getRetryCount();
1066
+ * PositiveInteger.assert(n);
1067
+ * // n is PositiveInteger here
1068
+ * ```
1069
+ * @public
1070
+ */
1071
+ assert: assertIsPositiveInteger,
1072
+ /**
1073
+ * Coerces a value to a {@link (PositiveInteger:type)} by rounding.
1074
+ *
1075
+ * @remarks
1076
+ * Delegates to {@link (Integer:variable).from | Integer.from()} for
1077
+ * rounding, then checks the result is non-negative. All error
1078
+ * conditions from `Integer.from()` apply (non-finite, empty string,
1079
+ * unsafe integer range), plus an additional check that the rounded
1080
+ * result is ≥ 0. IEEE 754 negative zero is normalized to positive zero.
1081
+ *
1082
+ * @example
1083
+ * ```ts
1084
+ * PositiveInteger.from(2.7, 'floor'); // 2
1085
+ * PositiveInteger.from('1.5', 'ceil'); // 2
1086
+ * PositiveInteger.from(Decimal.from('3.2'), 'half-up'); // 3
1087
+ * ```
1088
+ *
1089
+ * @throws Error if the value is non-finite, unparseable, outside the
1090
+ * safe integer range, or rounds to a negative number.
1091
+ *
1092
+ * @public
1093
+ */
1094
+ from(value, rounding) {
1095
+ const rounded = Integer.from(value, rounding);
1096
+ const normalized = normalizeZero2(rounded);
1097
+ if (normalized < 0) {
1098
+ throw new Error(
1099
+ `Value ${String(value)} rounds to ${String(normalized)}, which is negative`
1100
+ );
1101
+ }
1102
+ return normalized;
1103
+ }
1104
+ };
1105
+ var StreetAddress = {
1106
+ create: (address) => {
1107
+ return address;
1108
+ }
1109
+ };
1110
+ var Timestamp = {
1111
+ create: (value) => {
1112
+ return value;
1113
+ }
1114
+ };
1115
+
1116
+ // src/stdlib/refs.ts
1117
+ var Ref = {
1118
+ create: (step) => {
1119
+ return {
1120
+ type: step.object,
1121
+ id: step.id
1122
+ };
1123
+ }
1124
+ };
1125
+
894
1126
  // src/stdlib/types.ts
895
1127
  var WireReadError = class extends Error {
896
1128
  /**
@@ -1423,6 +1655,23 @@ function _applyConfig(descriptor, inputObject, appCtx) {
1423
1655
  const strategy = appCtx?.clockTime !== void 0 ? createJsonWireToType(appCtx) : _JsonWireToType;
1424
1656
  return _apply(descriptor, strategy, inputObject);
1425
1657
  }
1658
+
1659
+ // src/stdlib/to-const.ts
1660
+ function toConst(value) {
1661
+ if (value === null || typeof value !== "object") {
1662
+ return value;
1663
+ }
1664
+ if (Array.isArray(value)) {
1665
+ for (const item of value) {
1666
+ toConst(item);
1667
+ }
1668
+ return Object.freeze(value);
1669
+ }
1670
+ for (const key of Object.keys(value)) {
1671
+ toConst(value[key]);
1672
+ }
1673
+ return Object.freeze(value);
1674
+ }
1426
1675
  export {
1427
1676
  DEFAULT_DIV_PRECISION,
1428
1677
  Decimal,
@@ -1456,5 +1705,6 @@ export {
1456
1705
  _translateMap,
1457
1706
  _translateShape,
1458
1707
  _translateUnion,
1459
- isDecimal
1708
+ isDecimal,
1709
+ toConst
1460
1710
  };