@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
package/dist/index.js CHANGED
@@ -6,117 +6,6 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/stdlib/scalars.ts
8
8
  import "@formspec/core";
9
- function roundToInteger(value, direction) {
10
- switch (direction) {
11
- case "ceil":
12
- return Math.ceil(value);
13
- case "floor":
14
- return Math.floor(value);
15
- case "round-down":
16
- return Math.trunc(value);
17
- case "round-up":
18
- return value >= 0 ? Math.ceil(value) : Math.floor(value);
19
- case "half-up":
20
- return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
21
- default: {
22
- const _exhaustive = direction;
23
- throw new Error(`Unknown rounding direction: ${String(_exhaustive)}`);
24
- }
25
- }
26
- }
27
- var Integer = {
28
- /**
29
- * Type guard that narrows a `number` to {@link (Integer:type)}.
30
- *
31
- * @example
32
- * ```ts
33
- * const n: number = getCount();
34
- * if (Integer.is(n)) {
35
- * // n is Integer here
36
- * config.retryCount = n;
37
- * }
38
- * ```
39
- * @public
40
- */
41
- is: (value) => Number.isInteger(value),
42
- /**
43
- * Coerces a number to an {@link (Integer:type)} by rounding.
44
- * Throws if the value is not finite.
45
- *
46
- * @example
47
- * ```ts
48
- * const price = 9.99;
49
- * const rounded = Integer.from(price, 'floor'); // 9
50
- * const ceiled = Integer.from(price, 'ceil'); // 10
51
- * ```
52
- * @public
53
- */
54
- from: (value, rounding) => {
55
- if (!Number.isFinite(value)) {
56
- throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
57
- }
58
- return roundToInteger(value, rounding);
59
- }
60
- };
61
- var PositiveInteger = {
62
- /**
63
- * Type guard that narrows a `number` to {@link (PositiveInteger:type)}.
64
- *
65
- * @example
66
- * ```ts
67
- * const n: number = getRetryCount();
68
- * if (PositiveInteger.is(n)) {
69
- * // n is PositiveInteger here
70
- * config.maxRetries = n;
71
- * }
72
- * ```
73
- * @public
74
- */
75
- is: (value) => Number.isInteger(value) && value >= 0,
76
- /**
77
- * Coerces a number to a {@link (PositiveInteger:type)} by rounding.
78
- * Throws if the value is not finite or the rounded result is negative.
79
- *
80
- * @example
81
- * ```ts
82
- * const ratio = 2.7;
83
- * const count = PositiveInteger.from(ratio, 'floor'); // 2
84
- * ```
85
- * @public
86
- */
87
- from: (value, rounding) => {
88
- if (!Number.isFinite(value)) {
89
- throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
90
- }
91
- const rounded = roundToInteger(value, rounding) || 0;
92
- if (rounded < 0) {
93
- throw new Error(
94
- `Value ${String(value)} rounds to ${String(rounded)}, which is negative`
95
- );
96
- }
97
- return rounded;
98
- }
99
- };
100
- var StreetAddress = {
101
- create: (address) => {
102
- return address;
103
- }
104
- };
105
- var Timestamp = {
106
- create: (value) => {
107
- return value;
108
- }
109
- };
110
-
111
- // src/stdlib/refs.ts
112
- var Ref = {
113
- create: (step) => {
114
- return {
115
- type: step.object,
116
- id: step.id
117
- };
118
- }
119
- };
120
9
 
121
10
  // src/stdlib/decimal.ts
122
11
  var PLAIN_NOTATION_DIGIT_LIMIT = 30;
@@ -133,6 +22,9 @@ var DecimalRoundingPresets = Object.freeze({
133
22
  var DEFAULT_DIV_PRECISION = 34;
134
23
  var IMPLICIT_DECIMAL_COERCION_ERROR = "Implicit Decimal coercion is not allowed; use .add(), .sub(), .mul(), .div(), .toString(), or .toNumber() explicitly.";
135
24
  var MAX_EXPONENT = Number.MAX_SAFE_INTEGER;
25
+ function normalizeZero(value) {
26
+ return Object.is(value, -0) ? 0 : value;
27
+ }
136
28
  var DECIMAL_BRAND = /* @__PURE__ */ Symbol.for(
137
29
  "stripe.apps-extensibility-sdk.Decimal"
138
30
  );
@@ -246,13 +138,13 @@ var DecimalImpl = class _DecimalImpl {
246
138
  /**
247
139
  * Return the sum of this value and `other`.
248
140
  *
249
- * @param other - The addend.
141
+ * @param other - The addend. Accepts any {@link DecimalLike} value.
250
142
  * @returns A new {@link Decimal} equal to `this + other`.
251
143
  *
252
144
  * @public
253
145
  */
254
146
  add(other) {
255
- const otherImpl = toImpl(other);
147
+ const otherImpl = coerceToImpl(other);
256
148
  if (this.#exponent === otherImpl.#exponent) {
257
149
  return toDecimal(
258
150
  new _DecimalImpl(this.#coefficient + otherImpl.#coefficient, this.#exponent)
@@ -279,13 +171,13 @@ var DecimalImpl = class _DecimalImpl {
279
171
  /**
280
172
  * Return the difference of this value and `other`.
281
173
  *
282
- * @param other - The subtrahend.
174
+ * @param other - The subtrahend. Accepts any {@link DecimalLike} value.
283
175
  * @returns A new {@link Decimal} equal to `this - other`.
284
176
  *
285
177
  * @public
286
178
  */
287
179
  sub(other) {
288
- const otherImpl = toImpl(other);
180
+ const otherImpl = coerceToImpl(other);
289
181
  if (this.#exponent === otherImpl.#exponent) {
290
182
  return toDecimal(
291
183
  new _DecimalImpl(this.#coefficient - otherImpl.#coefficient, this.#exponent)
@@ -312,13 +204,13 @@ var DecimalImpl = class _DecimalImpl {
312
204
  /**
313
205
  * Return the product of this value and `other`.
314
206
  *
315
- * @param other - The multiplicand.
207
+ * @param other - The multiplicand. Accepts any {@link DecimalLike} value.
316
208
  * @returns A new {@link Decimal} equal to `this × other`.
317
209
  *
318
210
  * @public
319
211
  */
320
212
  mul(other) {
321
- const otherImpl = toImpl(other);
213
+ const otherImpl = coerceToImpl(other);
322
214
  return toDecimal(
323
215
  new _DecimalImpl(
324
216
  this.#coefficient * otherImpl.#coefficient,
@@ -345,7 +237,7 @@ var DecimalImpl = class _DecimalImpl {
345
237
  * Decimal.from('5').div(Decimal.from('2'), 0, 'half-even'); // "2"
346
238
  * ```
347
239
  *
348
- * @param other - The divisor. Must not be zero.
240
+ * @param other - The divisor. Must not be zero. Accepts any {@link DecimalLike} value.
349
241
  * @param precision - Maximum number of decimal digits in the result.
350
242
  * @param direction - How to round when the exact quotient cannot
351
243
  * be represented at the requested precision.
@@ -360,7 +252,7 @@ var DecimalImpl = class _DecimalImpl {
360
252
  if (precision < 0 || !Number.isInteger(precision)) {
361
253
  throw new Error("precision must be a non-negative integer");
362
254
  }
363
- const otherImpl = toImpl(other);
255
+ const otherImpl = coerceToImpl(other);
364
256
  if (otherImpl.#coefficient === 0n) {
365
257
  throw new Error("Division by zero");
366
258
  }
@@ -402,13 +294,13 @@ var DecimalImpl = class _DecimalImpl {
402
294
  * a.cmp(a); // 0
403
295
  * ```
404
296
  *
405
- * @param other - The value to compare against.
297
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
406
298
  * @returns `-1` if `this < other`, `0` if equal, `1` if `this > other`.
407
299
  *
408
300
  * @public
409
301
  */
410
302
  cmp(other) {
411
- const otherImpl = toImpl(other);
303
+ const otherImpl = coerceToImpl(other);
412
304
  if (this.#exponent === otherImpl.#exponent) {
413
305
  if (this.#coefficient < otherImpl.#coefficient) return -1;
414
306
  if (this.#coefficient > otherImpl.#coefficient) return 1;
@@ -431,7 +323,7 @@ var DecimalImpl = class _DecimalImpl {
431
323
  /**
432
324
  * Return `true` if this value is numerically equal to `other`.
433
325
  *
434
- * @param other - The value to compare against.
326
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
435
327
  * @returns `true` if `this === other` in value, `false` otherwise.
436
328
  *
437
329
  * @public
@@ -442,7 +334,7 @@ var DecimalImpl = class _DecimalImpl {
442
334
  /**
443
335
  * Return `true` if this value is strictly less than `other`.
444
336
  *
445
- * @param other - The value to compare against.
337
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
446
338
  * @returns `true` if `this < other`, `false` otherwise.
447
339
  *
448
340
  * @public
@@ -453,7 +345,7 @@ var DecimalImpl = class _DecimalImpl {
453
345
  /**
454
346
  * Return `true` if this value is less than or equal to `other`.
455
347
  *
456
- * @param other - The value to compare against.
348
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
457
349
  * @returns `true` if `this ≤ other`, `false` otherwise.
458
350
  *
459
351
  * @public
@@ -464,7 +356,7 @@ var DecimalImpl = class _DecimalImpl {
464
356
  /**
465
357
  * Return `true` if this value is strictly greater than `other`.
466
358
  *
467
- * @param other - The value to compare against.
359
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
468
360
  * @returns `true` if `this > other`, `false` otherwise.
469
361
  *
470
362
  * @public
@@ -475,7 +367,7 @@ var DecimalImpl = class _DecimalImpl {
475
367
  /**
476
368
  * Return `true` if this value is greater than or equal to `other`.
477
369
  *
478
- * @param other - The value to compare against.
370
+ * @param other - The value to compare against. Accepts any {@link DecimalLike} value.
479
371
  * @returns `true` if `this ≥ other`, `false` otherwise.
480
372
  *
481
373
  * @public
@@ -774,6 +666,38 @@ var DecimalImpl = class _DecimalImpl {
774
666
  return formatFixed(scaled);
775
667
  }
776
668
  }
669
+ /**
670
+ * Convert this value to an {@link (Integer:type)} by rounding.
671
+ *
672
+ * @remarks
673
+ * The rounding direction is always required — no invisible defaults
674
+ * in financial code.
675
+ *
676
+ * @example
677
+ * ```ts
678
+ * Decimal.from('2.7').toInteger('floor'); // 2
679
+ * Decimal.from('2.5').toInteger('half-up'); // 3
680
+ * Decimal.from('2.5').toInteger('half-even'); // 2
681
+ * ```
682
+ *
683
+ * @param direction - How to round when the value is not a whole number.
684
+ * @returns A branded {@link (Integer:type)} value.
685
+ * @throws Error if the rounded value is too large to represent as
686
+ * a JavaScript `number`.
687
+ *
688
+ * @public
689
+ */
690
+ toInteger(direction) {
691
+ const fixed = this.toFixed(0, direction);
692
+ const num = Number(fixed);
693
+ if (!Number.isFinite(num) || !Number.isSafeInteger(num)) {
694
+ throw new Error(
695
+ `Decimal value ${fixed} cannot be exactly represented as a JavaScript integer`
696
+ );
697
+ }
698
+ const normalized = normalizeZero(num);
699
+ return normalized;
700
+ }
777
701
  /**
778
702
  * Reject implicit arithmetic-style coercion while preserving explicit
779
703
  * stringification.
@@ -814,23 +738,59 @@ var DecimalImpl = class _DecimalImpl {
814
738
  function toImpl(d) {
815
739
  return d;
816
740
  }
741
+ function coerceToImpl(value) {
742
+ if (isDecimal(value)) {
743
+ return toImpl(value);
744
+ }
745
+ return toImpl(Decimal.from(value));
746
+ }
817
747
  function toDecimal(impl) {
818
748
  return impl;
819
749
  }
820
750
  function isDecimal(value) {
821
- return typeof value === "object" && value !== null && DECIMAL_BRAND in value;
751
+ return typeof value === "object" && value !== null && DECIMAL_BRAND in value && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- symbol key access requires cast
752
+ value[DECIMAL_BRAND] === true;
753
+ }
754
+ function assertIsDecimal(value) {
755
+ if (!isDecimal(value)) {
756
+ throw new Error(`Expected a Decimal, got ${typeof value}`);
757
+ }
822
758
  }
823
759
  var Decimal = {
824
760
  /**
825
- * Create a `Decimal` from a string, number, or bigint.
761
+ * Type guard that narrows an unknown value to {@link (Decimal:type)}.
762
+ *
763
+ * @example
764
+ * ```ts
765
+ * if (Decimal.is(value)) {
766
+ * value.add(1); // value is Decimal
767
+ * }
768
+ * ```
769
+ * @public
770
+ */
771
+ is: isDecimal,
772
+ /**
773
+ * Assertion guard that throws if the value is not a {@link (Decimal:type)}.
774
+ *
775
+ * @example
776
+ * ```ts
777
+ * Decimal.assert(value);
778
+ * value.add(1); // value is Decimal
779
+ * ```
780
+ * @public
781
+ */
782
+ assert: assertIsDecimal,
783
+ /**
784
+ * Create a `Decimal` from a string, number, bigint, Integer, or Decimal.
826
785
  *
827
786
  * @remarks
787
+ * - **Decimal**: returned as-is (immutable passthrough).
828
788
  * - **string**: Parsed as a decimal literal. Accepts an optional sign,
829
789
  * integer digits, an optional fractional part, and an optional `e`/`E`
830
790
  * exponent. Leading/trailing whitespace is trimmed.
831
- * - **number**: Must be finite. Converted via `Number.prototype.toString()`
832
- * then parsed, so `Decimal.from(0.1)` produces `"0.1"` (not the
833
- * 53-bit binary approximation).
791
+ * - **number** (including Integer): Must be finite. Converted via
792
+ * `Number.prototype.toString()` then parsed, so `Decimal.from(0.1)`
793
+ * produces `"0.1"` (not the 53-bit binary approximation).
834
794
  * - **bigint**: Treated as an integer with exponent 0.
835
795
  *
836
796
  * @example
@@ -839,16 +799,21 @@ var Decimal = {
839
799
  * Decimal.from(42); // number
840
800
  * Decimal.from(100n); // bigint
841
801
  * Decimal.from('1.5e3'); // scientific notation → 1500
802
+ * Decimal.from(d); // Decimal passthrough
842
803
  * ```
843
804
  *
844
805
  * @param value - The value to convert.
845
- * @returns A new frozen `Decimal` instance.
806
+ * @returns A new frozen `Decimal` instance (or the same instance if
807
+ * already a Decimal).
846
808
  * @throws Error if `value` is a non-finite number, an empty
847
809
  * string, or a string that does not match the decimal literal grammar.
848
810
  *
849
811
  * @public
850
812
  */
851
813
  from(value) {
814
+ if (isDecimal(value)) {
815
+ return value;
816
+ }
852
817
  if (typeof value === "bigint") {
853
818
  return toDecimal(new DecimalImpl(value, 0));
854
819
  }
@@ -897,20 +862,277 @@ var Decimal = {
897
862
  zero: toDecimal(new DecimalImpl(0n, 0))
898
863
  };
899
864
 
865
+ // src/stdlib/scalars.ts
866
+ function roundToInteger(value, direction) {
867
+ switch (direction) {
868
+ case "ceil":
869
+ return Math.ceil(value);
870
+ case "floor":
871
+ return Math.floor(value);
872
+ case "round-down":
873
+ return Math.trunc(value);
874
+ case "round-up":
875
+ return value >= 0 ? Math.ceil(value) : Math.floor(value);
876
+ case "half-up":
877
+ return value >= 0 ? Math.floor(value + 0.5) : Math.ceil(value - 0.5);
878
+ default: {
879
+ const _exhaustive = direction;
880
+ throw new Error(`Unknown rounding direction: ${String(_exhaustive)}`);
881
+ }
882
+ }
883
+ }
884
+ function normalizeZero2(value) {
885
+ return Object.is(value, -0) ? 0 : value;
886
+ }
887
+ function assertIsInteger(value) {
888
+ if (!(typeof value === "number" && Number.isInteger(value))) {
889
+ throw new Error(
890
+ `Expected an integer, got ${typeof value === "number" ? String(value) : typeof value}`
891
+ );
892
+ }
893
+ }
894
+ function assertIsPositiveInteger(value) {
895
+ if (!(typeof value === "number" && Number.isInteger(value) && value >= 0)) {
896
+ throw new Error(
897
+ `Expected a non-negative integer, got ${typeof value === "number" ? String(value) : typeof value}`
898
+ );
899
+ }
900
+ }
901
+ function assertIntegerIsPositive(value) {
902
+ if (value < 0) {
903
+ throw new Error(`Expected a non-negative integer, got ${String(value)}`);
904
+ }
905
+ }
906
+ var Integer = {
907
+ /**
908
+ * The `Integer` value representing zero.
909
+ *
910
+ * @remarks
911
+ * Pre-allocated singleton — prefer `Integer.zero` over
912
+ * `Integer.from(0, 'floor')` to avoid an unnecessary call.
913
+ *
914
+ * @public
915
+ */
916
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-type-assertion -- branded type construction: 0 is trivially an integer
917
+ zero: 0,
918
+ /**
919
+ * Type guard that narrows an unknown value to {@link (Integer:type)}.
920
+ *
921
+ * @example
922
+ * ```ts
923
+ * const n: unknown = getCount();
924
+ * if (Integer.is(n)) {
925
+ * // n is Integer here
926
+ * config.retryCount = n;
927
+ * }
928
+ * ```
929
+ * @public
930
+ */
931
+ is: (value) => typeof value === "number" && Number.isInteger(value),
932
+ /**
933
+ * Assertion guard that throws if the value is not an {@link (Integer:type)}.
934
+ *
935
+ * @example
936
+ * ```ts
937
+ * const n: unknown = getCount();
938
+ * Integer.assert(n);
939
+ * // n is Integer here
940
+ * ```
941
+ * @public
942
+ */
943
+ assert: assertIsInteger,
944
+ /**
945
+ * Coerces a value to an {@link (Integer:type)} by rounding.
946
+ *
947
+ * @remarks
948
+ * Accepts `number`, `string`, `Decimal`, or `Integer`. The rounding
949
+ * direction is always required — no invisible defaults.
950
+ *
951
+ * - **number** (including Integer): must be finite and round to a
952
+ * safe integer (`Number.isSafeInteger`). IEEE 754 negative zero is
953
+ * normalized to positive zero.
954
+ * - **string**: must be a valid numeric literal (not empty/whitespace).
955
+ * Parsed via `Number()`, then rounded. The result must be a safe integer.
956
+ * - **Decimal**: delegated to {@link Decimal.toInteger | Decimal.toInteger()}.
957
+ *
958
+ * @example
959
+ * ```ts
960
+ * Integer.from(9.99, 'floor'); // 9
961
+ * Integer.from('1.5', 'ceil'); // 2
962
+ * Integer.from(Decimal.from('2.7'), 'half-up'); // 3
963
+ * ```
964
+ *
965
+ * @throws Error if the value is non-finite, an empty string, an
966
+ * unparseable string, or rounds to a value outside the safe integer range.
967
+ *
968
+ * @public
969
+ */
970
+ from(value, rounding) {
971
+ if (typeof value === "number") {
972
+ if (!Number.isFinite(value)) {
973
+ throw new Error(`Cannot round non-finite value ${String(value)} to an integer`);
974
+ }
975
+ const rounded = normalizeZero2(roundToInteger(value, rounding));
976
+ if (!Number.isSafeInteger(rounded)) {
977
+ throw new Error(
978
+ `Value ${String(value)} rounds to ${String(rounded)}, which is outside the safe integer range`
979
+ );
980
+ }
981
+ return rounded;
982
+ }
983
+ if (typeof value === "string") {
984
+ if (value.trim() === "") {
985
+ throw new Error("Cannot parse empty string as an integer");
986
+ }
987
+ const num = Number(value);
988
+ if (!Number.isFinite(num)) {
989
+ throw new Error(
990
+ `Cannot parse "${value}" as a finite number for integer conversion`
991
+ );
992
+ }
993
+ const rounded = normalizeZero2(roundToInteger(num, rounding));
994
+ if (!Number.isSafeInteger(rounded)) {
995
+ throw new Error(
996
+ `Value "${value}" rounds to ${String(rounded)}, which is outside the safe integer range`
997
+ );
998
+ }
999
+ return rounded;
1000
+ }
1001
+ if (isDecimal(value)) {
1002
+ return value.toInteger(rounding);
1003
+ }
1004
+ throw new Error(
1005
+ `Cannot convert ${typeof value} to Integer; expected string, number, or Decimal`
1006
+ );
1007
+ },
1008
+ /**
1009
+ * Convert an {@link (Integer:type)} to a {@link (Decimal:type)}.
1010
+ *
1011
+ * @remarks
1012
+ * This conversion is lossless — every JavaScript integer is exactly
1013
+ * representable as a Decimal.
1014
+ *
1015
+ * @example
1016
+ * ```ts
1017
+ * const dec = Integer.toDecimal(Integer.from(42, 'floor'));
1018
+ * dec.add(Decimal.from('0.5')); // 42.5
1019
+ * ```
1020
+ * @public
1021
+ */
1022
+ toDecimal(value) {
1023
+ return Decimal.from(value);
1024
+ },
1025
+ /**
1026
+ * Type guard that narrows an {@link (Integer:type)} to {@link (PositiveInteger:type)}.
1027
+ *
1028
+ * @example
1029
+ * ```ts
1030
+ * const n = Integer.from(count, 'floor');
1031
+ * if (Integer.isPositive(n)) {
1032
+ * // n is PositiveInteger here
1033
+ * }
1034
+ * ```
1035
+ * @public
1036
+ */
1037
+ isPositive: (value) => value >= 0,
1038
+ /**
1039
+ * Assertion guard that throws if an {@link (Integer:type)} is not a {@link (PositiveInteger:type)}.
1040
+ *
1041
+ * @example
1042
+ * ```ts
1043
+ * const n = Integer.from(count, 'floor');
1044
+ * Integer.assertIsPositive(n);
1045
+ * // n is PositiveInteger here
1046
+ * ```
1047
+ * @public
1048
+ */
1049
+ assertIsPositive: assertIntegerIsPositive
1050
+ };
1051
+ var PositiveInteger = {
1052
+ /**
1053
+ * Type guard that narrows an unknown value to {@link (PositiveInteger:type)}.
1054
+ *
1055
+ * @example
1056
+ * ```ts
1057
+ * const n: unknown = getRetryCount();
1058
+ * if (PositiveInteger.is(n)) {
1059
+ * // n is PositiveInteger here
1060
+ * config.maxRetries = n;
1061
+ * }
1062
+ * ```
1063
+ * @public
1064
+ */
1065
+ is: (value) => typeof value === "number" && Number.isInteger(value) && value >= 0,
1066
+ /**
1067
+ * Assertion guard that throws if the value is not a {@link (PositiveInteger:type)}.
1068
+ *
1069
+ * @example
1070
+ * ```ts
1071
+ * const n: unknown = getRetryCount();
1072
+ * PositiveInteger.assert(n);
1073
+ * // n is PositiveInteger here
1074
+ * ```
1075
+ * @public
1076
+ */
1077
+ assert: assertIsPositiveInteger,
1078
+ /**
1079
+ * Coerces a value to a {@link (PositiveInteger:type)} by rounding.
1080
+ *
1081
+ * @remarks
1082
+ * Delegates to {@link (Integer:variable).from | Integer.from()} for
1083
+ * rounding, then checks the result is non-negative. All error
1084
+ * conditions from `Integer.from()` apply (non-finite, empty string,
1085
+ * unsafe integer range), plus an additional check that the rounded
1086
+ * result is ≥ 0. IEEE 754 negative zero is normalized to positive zero.
1087
+ *
1088
+ * @example
1089
+ * ```ts
1090
+ * PositiveInteger.from(2.7, 'floor'); // 2
1091
+ * PositiveInteger.from('1.5', 'ceil'); // 2
1092
+ * PositiveInteger.from(Decimal.from('3.2'), 'half-up'); // 3
1093
+ * ```
1094
+ *
1095
+ * @throws Error if the value is non-finite, unparseable, outside the
1096
+ * safe integer range, or rounds to a negative number.
1097
+ *
1098
+ * @public
1099
+ */
1100
+ from(value, rounding) {
1101
+ const rounded = Integer.from(value, rounding);
1102
+ const normalized = normalizeZero2(rounded);
1103
+ if (normalized < 0) {
1104
+ throw new Error(
1105
+ `Value ${String(value)} rounds to ${String(normalized)}, which is negative`
1106
+ );
1107
+ }
1108
+ return normalized;
1109
+ }
1110
+ };
1111
+
1112
+ // src/stdlib/refs.ts
1113
+ var Ref = {
1114
+ create: (step) => {
1115
+ return {
1116
+ type: step.object,
1117
+ id: step.id
1118
+ };
1119
+ }
1120
+ };
1121
+
900
1122
  // src/stdlib/types.ts
901
- var WireReadError = class extends Error {
1123
+ var _WireReadError = class extends Error {
902
1124
  /**
903
1125
  * Error class name for `instanceof`-free identification.
904
1126
  * @internal
905
1127
  */
906
- name = "WireReadError";
1128
+ name = "_WireReadError";
907
1129
  };
908
- var WireWriteError = class extends Error {
1130
+ var _WireWriteError = class extends Error {
909
1131
  /**
910
1132
  * Error class name for `instanceof`-free identification.
911
1133
  * @internal
912
1134
  */
913
- name = "WireWriteError";
1135
+ name = "_WireWriteError";
914
1136
  };
915
1137
  var WireParseError = class extends Error {
916
1138
  name = "WireParseError";
@@ -1117,7 +1339,7 @@ function enumLookup(spec, value, direction) {
1117
1339
  var _ProtoWireToType = {
1118
1340
  _brand: "ProtoWireToType",
1119
1341
  createNotObjectError(loc, received) {
1120
- return new WireReadError(`${loc}: Expected an object but received ${received}`);
1342
+ return new _WireReadError(`${loc}: Expected an object but received ${received}`);
1121
1343
  },
1122
1344
  applyField(typeName, desc, input, strategy) {
1123
1345
  const from = desc.wire ?? desc.type;
@@ -1127,7 +1349,7 @@ var _ProtoWireToType = {
1127
1349
  return [to, (desc.transform ?? _identity)(strategy, raw)];
1128
1350
  } catch (e) {
1129
1351
  if (e instanceof WireParseError)
1130
- throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1352
+ throw new _WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1131
1353
  throw e;
1132
1354
  }
1133
1355
  },
@@ -1182,7 +1404,7 @@ var _ProtoWireToType = {
1182
1404
  }
1183
1405
  }
1184
1406
  const loc = descriptor.typeName || "union";
1185
- throw new WireReadError(`${loc}: No variant set`);
1407
+ throw new _WireReadError(`${loc}: No variant set`);
1186
1408
  },
1187
1409
  applyOneofField(typeName, oneof, input, strategy, result, excludeWireKeys) {
1188
1410
  applyOneofFieldIncoming(typeName, oneof, input, strategy, result, excludeWireKeys);
@@ -1191,7 +1413,7 @@ var _ProtoWireToType = {
1191
1413
  var _TypeToProtoWire = {
1192
1414
  _brand: "TypeToProtoWire",
1193
1415
  createNotObjectError(loc, received) {
1194
- return new WireWriteError(`${loc}: Expected an object but received ${received}`);
1416
+ return new _WireWriteError(`${loc}: Expected an object but received ${received}`);
1195
1417
  },
1196
1418
  applyField(typeName, desc, input, strategy) {
1197
1419
  const from = desc.type;
@@ -1201,7 +1423,7 @@ var _TypeToProtoWire = {
1201
1423
  return [to, (desc.transform ?? _identity)(strategy, raw)];
1202
1424
  } catch (e) {
1203
1425
  if (e instanceof WireParseError)
1204
- throw new WireWriteError(`${typeName}.${desc.type}: ${e.message}`);
1426
+ throw new _WireWriteError(`${typeName}.${desc.type}: ${e.message}`);
1205
1427
  throw e;
1206
1428
  }
1207
1429
  },
@@ -1241,20 +1463,20 @@ var _TypeToProtoWire = {
1241
1463
  const discriminant = sdk[descriptor.discriminantFieldName];
1242
1464
  if (typeof discriminant !== "string") {
1243
1465
  const loc = descriptor.typeName || "union";
1244
- throw new WireWriteError(
1466
+ throw new _WireWriteError(
1245
1467
  `${loc}: Expected a string '${descriptor.discriminantFieldName}' discriminant but received ${discriminant === void 0 ? "undefined" : typeof discriminant}`
1246
1468
  );
1247
1469
  }
1248
1470
  if (discriminant === "other") {
1249
1471
  const loc = descriptor.typeName || "union";
1250
- throw new WireWriteError(
1472
+ throw new _WireWriteError(
1251
1473
  `${loc}: Cannot serialize 'other' variant back to wire format`
1252
1474
  );
1253
1475
  }
1254
1476
  const branch = descriptor.branches.find((b) => b.typeKey === discriminant);
1255
1477
  if (!branch) {
1256
1478
  const loc = descriptor.typeName || "union";
1257
- throw new WireWriteError(`${loc}: Unknown variant '${discriminant}'`);
1479
+ throw new _WireWriteError(`${loc}: Unknown variant '${discriminant}'`);
1258
1480
  }
1259
1481
  const branchData = _apply(
1260
1482
  new _ShapeDescriptor(descriptor.typeName, branch.shape),
@@ -1283,7 +1505,7 @@ function _configAppContextFromContext(ctx) {
1283
1505
  var _JsonWireToType = {
1284
1506
  _brand: "JsonWireToType",
1285
1507
  createNotObjectError(loc, received) {
1286
- return new WireReadError(`${loc}: Expected an object but received ${received}`);
1508
+ return new _WireReadError(`${loc}: Expected an object but received ${received}`);
1287
1509
  },
1288
1510
  applyField(typeName, desc, input, strategy) {
1289
1511
  const key = desc.type;
@@ -1292,7 +1514,7 @@ var _JsonWireToType = {
1292
1514
  return [key, (desc.transform ?? _identity)(strategy, raw)];
1293
1515
  } catch (e) {
1294
1516
  if (e instanceof WireParseError)
1295
- throw new WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1517
+ throw new _WireReadError(`${typeName}.${desc.type}: ${e.message}`);
1296
1518
  throw e;
1297
1519
  }
1298
1520
  },
@@ -1347,7 +1569,7 @@ function applyOneofFieldIncoming(typeName, oneof, input, strategy, result, exclu
1347
1569
  }
1348
1570
  } catch (e) {
1349
1571
  if (e instanceof WireParseError) {
1350
- throw new WireReadError(
1572
+ throw new _WireReadError(
1351
1573
  `${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
1352
1574
  );
1353
1575
  }
@@ -1365,30 +1587,30 @@ function applyOneofFieldIncoming(typeName, oneof, input, strategy, result, exclu
1365
1587
  }
1366
1588
  }
1367
1589
  if (!oneof.optional) {
1368
- throw new WireReadError(`${typeName}.${oneof.discriminant}: no variant set`);
1590
+ throw new _WireReadError(`${typeName}.${oneof.discriminant}: no variant set`);
1369
1591
  }
1370
1592
  }
1371
1593
  function applyOneofFieldOutgoing(typeName, oneof, input, strategy, result) {
1372
1594
  const discriminant = Object.hasOwn(input, oneof.discriminant) ? input[oneof.discriminant] : void 0;
1373
1595
  if (discriminant === void 0 || discriminant === null) {
1374
1596
  if (!oneof.optional) {
1375
- throw new WireWriteError(`${typeName}.${oneof.discriminant}: no variant set`);
1597
+ throw new _WireWriteError(`${typeName}.${oneof.discriminant}: no variant set`);
1376
1598
  }
1377
1599
  return;
1378
1600
  }
1379
1601
  if (typeof discriminant !== "string") {
1380
- throw new WireWriteError(
1602
+ throw new _WireWriteError(
1381
1603
  `${typeName}.${oneof.discriminant}: expected string discriminant but received ${typeof discriminant}`
1382
1604
  );
1383
1605
  }
1384
1606
  if (discriminant === "other") {
1385
- throw new WireWriteError(
1607
+ throw new _WireWriteError(
1386
1608
  `${typeName}.${oneof.discriminant}: cannot serialize 'other' variant back to wire format`
1387
1609
  );
1388
1610
  }
1389
1611
  const branch = oneof.branches.find((b) => b.typeKey === discriminant);
1390
1612
  if (!branch) {
1391
- throw new WireWriteError(
1613
+ throw new _WireWriteError(
1392
1614
  `${typeName}.${oneof.discriminant}: unknown variant '${discriminant}'`
1393
1615
  );
1394
1616
  }
@@ -1398,7 +1620,7 @@ function applyOneofFieldOutgoing(typeName, oneof, input, strategy, result) {
1398
1620
  result[branch.wireKey] = transformed ?? {};
1399
1621
  } catch (e) {
1400
1622
  if (e instanceof WireParseError) {
1401
- throw new WireWriteError(
1623
+ throw new _WireWriteError(
1402
1624
  `${typeName}.${oneof.discriminant}(${branch.typeKey}): ${e.message}`
1403
1625
  );
1404
1626
  }
@@ -1430,6 +1652,23 @@ function _applyConfig(descriptor, inputObject, appCtx) {
1430
1652
  return _apply(descriptor, strategy, inputObject);
1431
1653
  }
1432
1654
 
1655
+ // src/stdlib/to-const.ts
1656
+ function toConst(value) {
1657
+ if (value === null || typeof value !== "object") {
1658
+ return value;
1659
+ }
1660
+ if (Array.isArray(value)) {
1661
+ for (const item of value) {
1662
+ toConst(item);
1663
+ }
1664
+ return Object.freeze(value);
1665
+ }
1666
+ for (const key of Object.keys(value)) {
1667
+ toConst(value[key]);
1668
+ }
1669
+ return Object.freeze(value);
1670
+ }
1671
+
1433
1672
  // src/extensions/billing/index.ts
1434
1673
  var billing_exports = {};
1435
1674
  __export(billing_exports, {
@@ -3750,10 +3989,6 @@ export {
3750
3989
  Integer,
3751
3990
  PositiveInteger,
3752
3991
  Ref,
3753
- StreetAddress,
3754
- Timestamp,
3755
- WireReadError,
3756
- WireWriteError,
3757
3992
  _ConfigEnum,
3758
3993
  _JsonWireToType,
3759
3994
  _ProtoEnum,
@@ -3761,6 +3996,8 @@ export {
3761
3996
  _ShapeDescriptor,
3762
3997
  _TypeToProtoWire,
3763
3998
  _UnionDescriptor,
3999
+ _WireReadError,
4000
+ _WireWriteError,
3764
4001
  _apply,
3765
4002
  _applyConfig,
3766
4003
  _applyIncoming,
@@ -3776,5 +4013,5 @@ export {
3776
4013
  _translateMap,
3777
4014
  _translateShape,
3778
4015
  _translateUnion,
3779
- isDecimal
4016
+ toConst
3780
4017
  };