@stripe/extensibility-sdk 0.24.1 → 0.26.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 (54) hide show
  1. package/README.md +328 -0
  2. package/dist/config-values/generate.cjs +1 -1
  3. package/dist/config-values/generate.d.ts +2 -0
  4. package/dist/config-values/generate.d.ts.map +1 -1
  5. package/dist/config-values/generate.js +1 -1
  6. package/dist/extensibility-sdk-alpha.d.ts +141 -98
  7. package/dist/extensibility-sdk-beta.d.ts +141 -98
  8. package/dist/extensibility-sdk-extensions-alpha.d.ts +155 -25
  9. package/dist/extensibility-sdk-extensions-beta.d.ts +155 -25
  10. package/dist/extensibility-sdk-extensions-internal.d.ts +160 -26
  11. package/dist/extensibility-sdk-extensions-public.d.ts +155 -25
  12. package/dist/extensibility-sdk-internal-alpha.d.ts +5 -0
  13. package/dist/extensibility-sdk-internal-beta.d.ts +5 -0
  14. package/dist/extensibility-sdk-internal-internal.d.ts +5 -0
  15. package/dist/extensibility-sdk-internal-public.d.ts +5 -0
  16. package/dist/extensibility-sdk-internal.d.ts +144 -82
  17. package/dist/extensibility-sdk-public.d.ts +141 -98
  18. package/dist/extensibility-sdk-stdlib-alpha.d.ts +146 -98
  19. package/dist/extensibility-sdk-stdlib-beta.d.ts +146 -98
  20. package/dist/extensibility-sdk-stdlib-internal.d.ts +149 -82
  21. package/dist/extensibility-sdk-stdlib-public.d.ts +146 -98
  22. package/dist/extensions/billing/bill/discount_calculation.d.ts +5 -3
  23. package/dist/extensions/billing/customer_balance_application.d.ts +3 -1
  24. package/dist/extensions/billing/invoice_collection_setting.d.ts +15 -11
  25. package/dist/extensions/billing/prorations.d.ts +30 -21
  26. package/dist/extensions/billing/recurring_billing_item_handling.d.ts +41 -23
  27. package/dist/extensions/billing/types.d.ts +4 -4
  28. package/dist/extensions/core/workflows/custom_action.d.ts +6 -2
  29. package/dist/extensions/extend/workflows/custom_action.d.ts +6 -2
  30. package/dist/index.cjs +398 -163
  31. package/dist/index.js +395 -158
  32. package/dist/internal.d.ts +4 -0
  33. package/dist/internal.d.ts.map +1 -1
  34. package/dist/stdlib/brand.d.ts +16 -10
  35. package/dist/stdlib/brand.d.ts.map +1 -1
  36. package/dist/stdlib/decimal.d.ts +50 -22
  37. package/dist/stdlib/decimal.d.ts.map +1 -1
  38. package/dist/stdlib/index.cjs +398 -163
  39. package/dist/stdlib/index.d.ts +11 -5
  40. package/dist/stdlib/index.d.ts.map +1 -1
  41. package/dist/stdlib/index.js +395 -158
  42. package/dist/stdlib/refs.d.ts +12 -20
  43. package/dist/stdlib/refs.d.ts.map +1 -1
  44. package/dist/stdlib/scalars.d.ts +51 -36
  45. package/dist/stdlib/scalars.d.ts.map +1 -1
  46. package/dist/stdlib/to-const.d.ts +35 -0
  47. package/dist/stdlib/to-const.d.ts.map +1 -0
  48. package/dist/stdlib/transforms.d.ts +1 -1
  49. package/dist/stdlib/type-utils.d.ts +3 -1
  50. package/dist/stdlib/types.d.ts +11 -11
  51. package/dist/stdlib/types.d.ts.map +1 -1
  52. package/dist/tsconfig.build.tsbuildinfo +1 -1
  53. package/package.json +11 -11
  54. 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,20 +856,277 @@ 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
+
1106
+ // src/stdlib/refs.ts
1107
+ var Ref = {
1108
+ create: (step) => {
1109
+ return {
1110
+ type: step.object,
1111
+ id: step.id
1112
+ };
1113
+ }
1114
+ };
1115
+
894
1116
  // src/stdlib/types.ts
895
- var WireReadError = class extends Error {
1117
+ var _WireReadError = class extends Error {
896
1118
  /**
897
1119
  * Error class name for `instanceof`-free identification.
898
1120
  * @internal
899
1121
  */
900
- name = "WireReadError";
1122
+ name = "_WireReadError";
901
1123
  };
902
- var WireWriteError = class extends Error {
1124
+ var _WireWriteError = class extends Error {
903
1125
  /**
904
1126
  * Error class name for `instanceof`-free identification.
905
1127
  * @internal
906
1128
  */
907
- name = "WireWriteError";
1129
+ name = "_WireWriteError";
908
1130
  };
909
1131
  var WireParseError = class extends Error {
910
1132
  name = "WireParseError";
@@ -1111,7 +1333,7 @@ function enumLookup(spec, value, direction) {
1111
1333
  var _ProtoWireToType = {
1112
1334
  _brand: "ProtoWireToType",
1113
1335
  createNotObjectError(loc, received) {
1114
- return new WireReadError(`${loc}: Expected an object but received ${received}`);
1336
+ return new _WireReadError(`${loc}: Expected an object but received ${received}`);
1115
1337
  },
1116
1338
  applyField(typeName, desc, input, strategy) {
1117
1339
  const from = desc.wire ?? desc.type;
@@ -1121,7 +1343,7 @@ var _ProtoWireToType = {
1121
1343
  return [to, (desc.transform ?? _identity)(strategy, raw)];
1122
1344
  } catch (e) {
1123
1345
  if (e instanceof WireParseError)
1124
- throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1346
+ throw new _WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1125
1347
  throw e;
1126
1348
  }
1127
1349
  },
@@ -1176,7 +1398,7 @@ var _ProtoWireToType = {
1176
1398
  }
1177
1399
  }
1178
1400
  const loc = descriptor.typeName || "union";
1179
- throw new WireReadError(`${loc}: No variant set`);
1401
+ throw new _WireReadError(`${loc}: No variant set`);
1180
1402
  },
1181
1403
  applyOneofField(typeName, oneof, input, strategy, result, excludeWireKeys) {
1182
1404
  applyOneofFieldIncoming(typeName, oneof, input, strategy, result, excludeWireKeys);
@@ -1185,7 +1407,7 @@ var _ProtoWireToType = {
1185
1407
  var _TypeToProtoWire = {
1186
1408
  _brand: "TypeToProtoWire",
1187
1409
  createNotObjectError(loc, received) {
1188
- return new WireWriteError(`${loc}: Expected an object but received ${received}`);
1410
+ return new _WireWriteError(`${loc}: Expected an object but received ${received}`);
1189
1411
  },
1190
1412
  applyField(typeName, desc, input, strategy) {
1191
1413
  const from = desc.type;
@@ -1195,7 +1417,7 @@ var _TypeToProtoWire = {
1195
1417
  return [to, (desc.transform ?? _identity)(strategy, raw)];
1196
1418
  } catch (e) {
1197
1419
  if (e instanceof WireParseError)
1198
- throw new WireWriteError(`${typeName}.${desc.type}: ${e.message}`);
1420
+ throw new _WireWriteError(`${typeName}.${desc.type}: ${e.message}`);
1199
1421
  throw e;
1200
1422
  }
1201
1423
  },
@@ -1235,20 +1457,20 @@ var _TypeToProtoWire = {
1235
1457
  const discriminant = sdk[descriptor.discriminantFieldName];
1236
1458
  if (typeof discriminant !== "string") {
1237
1459
  const loc = descriptor.typeName || "union";
1238
- throw new WireWriteError(
1460
+ throw new _WireWriteError(
1239
1461
  `${loc}: Expected a string '${descriptor.discriminantFieldName}' discriminant but received ${discriminant === void 0 ? "undefined" : typeof discriminant}`
1240
1462
  );
1241
1463
  }
1242
1464
  if (discriminant === "other") {
1243
1465
  const loc = descriptor.typeName || "union";
1244
- throw new WireWriteError(
1466
+ throw new _WireWriteError(
1245
1467
  `${loc}: Cannot serialize 'other' variant back to wire format`
1246
1468
  );
1247
1469
  }
1248
1470
  const branch = descriptor.branches.find((b) => b.typeKey === discriminant);
1249
1471
  if (!branch) {
1250
1472
  const loc = descriptor.typeName || "union";
1251
- throw new WireWriteError(`${loc}: Unknown variant '${discriminant}'`);
1473
+ throw new _WireWriteError(`${loc}: Unknown variant '${discriminant}'`);
1252
1474
  }
1253
1475
  const branchData = _apply(
1254
1476
  new _ShapeDescriptor(descriptor.typeName, branch.shape),
@@ -1277,7 +1499,7 @@ function _configAppContextFromContext(ctx) {
1277
1499
  var _JsonWireToType = {
1278
1500
  _brand: "JsonWireToType",
1279
1501
  createNotObjectError(loc, received) {
1280
- return new WireReadError(`${loc}: Expected an object but received ${received}`);
1502
+ return new _WireReadError(`${loc}: Expected an object but received ${received}`);
1281
1503
  },
1282
1504
  applyField(typeName, desc, input, strategy) {
1283
1505
  const key = desc.type;
@@ -1286,7 +1508,7 @@ var _JsonWireToType = {
1286
1508
  return [key, (desc.transform ?? _identity)(strategy, raw)];
1287
1509
  } catch (e) {
1288
1510
  if (e instanceof WireParseError)
1289
- throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1511
+ throw new _WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1290
1512
  throw e;
1291
1513
  }
1292
1514
  },
@@ -1341,7 +1563,7 @@ function applyOneofFieldIncoming(typeName, oneof, input, strategy, result, exclu
1341
1563
  }
1342
1564
  } catch (e) {
1343
1565
  if (e instanceof WireParseError) {
1344
- throw new WireReadError(
1566
+ throw new _WireReadError(
1345
1567
  `${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
1346
1568
  );
1347
1569
  }
@@ -1359,30 +1581,30 @@ function applyOneofFieldIncoming(typeName, oneof, input, strategy, result, exclu
1359
1581
  }
1360
1582
  }
1361
1583
  if (!oneof.optional) {
1362
- throw new WireReadError(`${typeName}.${oneof.discriminant}: no variant set`);
1584
+ throw new _WireReadError(`${typeName}.${oneof.discriminant}: no variant set`);
1363
1585
  }
1364
1586
  }
1365
1587
  function applyOneofFieldOutgoing(typeName, oneof, input, strategy, result) {
1366
1588
  const discriminant = Object.hasOwn(input, oneof.discriminant) ? input[oneof.discriminant] : void 0;
1367
1589
  if (discriminant === void 0 || discriminant === null) {
1368
1590
  if (!oneof.optional) {
1369
- throw new WireWriteError(`${typeName}.${oneof.discriminant}: no variant set`);
1591
+ throw new _WireWriteError(`${typeName}.${oneof.discriminant}: no variant set`);
1370
1592
  }
1371
1593
  return;
1372
1594
  }
1373
1595
  if (typeof discriminant !== "string") {
1374
- throw new WireWriteError(
1596
+ throw new _WireWriteError(
1375
1597
  `${typeName}.${oneof.discriminant}: expected string discriminant but received ${typeof discriminant}`
1376
1598
  );
1377
1599
  }
1378
1600
  if (discriminant === "other") {
1379
- throw new WireWriteError(
1601
+ throw new _WireWriteError(
1380
1602
  `${typeName}.${oneof.discriminant}: cannot serialize 'other' variant back to wire format`
1381
1603
  );
1382
1604
  }
1383
1605
  const branch = oneof.branches.find((b) => b.typeKey === discriminant);
1384
1606
  if (!branch) {
1385
- throw new WireWriteError(
1607
+ throw new _WireWriteError(
1386
1608
  `${typeName}.${oneof.discriminant}: unknown variant '${discriminant}'`
1387
1609
  );
1388
1610
  }
@@ -1392,7 +1614,7 @@ function applyOneofFieldOutgoing(typeName, oneof, input, strategy, result) {
1392
1614
  result[branch.wireKey] = transformed ?? {};
1393
1615
  } catch (e) {
1394
1616
  if (e instanceof WireParseError) {
1395
- throw new WireWriteError(
1617
+ throw new _WireWriteError(
1396
1618
  `${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
1397
1619
  );
1398
1620
  }
@@ -1423,6 +1645,23 @@ function _applyConfig(descriptor, inputObject, appCtx) {
1423
1645
  const strategy = appCtx?.clockTime !== void 0 ? createJsonWireToType(appCtx) : _JsonWireToType;
1424
1646
  return _apply(descriptor, strategy, inputObject);
1425
1647
  }
1648
+
1649
+ // src/stdlib/to-const.ts
1650
+ function toConst(value) {
1651
+ if (value === null || typeof value !== "object") {
1652
+ return value;
1653
+ }
1654
+ if (Array.isArray(value)) {
1655
+ for (const item of value) {
1656
+ toConst(item);
1657
+ }
1658
+ return Object.freeze(value);
1659
+ }
1660
+ for (const key of Object.keys(value)) {
1661
+ toConst(value[key]);
1662
+ }
1663
+ return Object.freeze(value);
1664
+ }
1426
1665
  export {
1427
1666
  DEFAULT_DIV_PRECISION,
1428
1667
  Decimal,
@@ -1430,10 +1669,6 @@ export {
1430
1669
  Integer,
1431
1670
  PositiveInteger,
1432
1671
  Ref,
1433
- StreetAddress,
1434
- Timestamp,
1435
- WireReadError,
1436
- WireWriteError,
1437
1672
  _ConfigEnum,
1438
1673
  _JsonWireToType,
1439
1674
  _ProtoEnum,
@@ -1441,6 +1676,8 @@ export {
1441
1676
  _ShapeDescriptor,
1442
1677
  _TypeToProtoWire,
1443
1678
  _UnionDescriptor,
1679
+ _WireReadError,
1680
+ _WireWriteError,
1444
1681
  _apply,
1445
1682
  _applyConfig,
1446
1683
  _applyIncoming,
@@ -1456,5 +1693,5 @@ export {
1456
1693
  _translateMap,
1457
1694
  _translateShape,
1458
1695
  _translateUnion,
1459
- isDecimal
1696
+ toConst
1460
1697
  };