@hexclave/shared 1.0.45 → 1.0.47

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 (125) hide show
  1. package/dist/{admin-interface-B-UjGQ0i.d.ts → admin-interface-DH4uLcZ3.d.ts} +11 -11
  2. package/dist/{admin-interface-B-UjGQ0i.d.ts.map → admin-interface-DH4uLcZ3.d.ts.map} +1 -1
  3. package/dist/{admin-metrics-1yiWGq9z.d.ts → admin-metrics-pphx-0AE.d.ts} +11 -11
  4. package/dist/{admin-metrics-1yiWGq9z.d.ts.map → admin-metrics-pphx-0AE.d.ts.map} +1 -1
  5. package/dist/ai/unified-prompts/reminders.js +2 -1
  6. package/dist/ai/unified-prompts/reminders.js.map +1 -1
  7. package/dist/{client-interface-DjVtlQix.d.ts → client-interface-BmHWUJhv.d.ts} +10 -10
  8. package/dist/{client-interface-DjVtlQix.d.ts.map → client-interface-BmHWUJhv.d.ts.map} +1 -1
  9. package/dist/config/schema.d.ts +1 -1
  10. package/dist/config-authoring.d.ts +1 -1
  11. package/dist/{current-user-BCkMYzHx.d.ts → current-user-Dvf8Ttjo.d.ts} +15 -15
  12. package/dist/{current-user-BCkMYzHx.d.ts.map → current-user-Dvf8Ttjo.d.ts.map} +1 -1
  13. package/dist/dates-BRAvSk6L.d.ts +40 -0
  14. package/dist/{dates-B6ne9iOR.d.ts.map → dates-BRAvSk6L.d.ts.map} +1 -1
  15. package/dist/{email-outbox-BRZiK0ZG.d.ts → email-outbox-DoxRUJop.d.ts} +179 -179
  16. package/dist/{email-outbox-BRZiK0ZG.d.ts.map → email-outbox-DoxRUJop.d.ts.map} +1 -1
  17. package/dist/esm/ai/unified-prompts/reminders.js +1 -1
  18. package/dist/esm/config/schema.d.ts +92 -92
  19. package/dist/esm/interface/admin-interface.js +1 -1
  20. package/dist/esm/interface/admin-metrics.d.ts +10 -10
  21. package/dist/esm/interface/client-interface.js +1 -1
  22. package/dist/esm/interface/conversations.d.ts +7 -7
  23. package/dist/esm/interface/crud/current-user.d.ts +14 -14
  24. package/dist/esm/interface/crud/email-outbox.d.ts +178 -178
  25. package/dist/esm/interface/crud/invoices.d.ts +1 -1
  26. package/dist/esm/interface/crud/products.d.ts +21 -21
  27. package/dist/esm/interface/crud/project-api-keys.d.ts +4 -4
  28. package/dist/esm/interface/crud/projects.d.ts +16 -16
  29. package/dist/esm/interface/crud/team-member-profiles.d.ts +22 -22
  30. package/dist/esm/interface/crud/transactions.d.ts +17 -17
  31. package/dist/esm/interface/crud/transactions.d.ts.map +1 -1
  32. package/dist/esm/interface/crud/users.d.ts +12 -12
  33. package/dist/esm/interface/plan-usage.d.ts +3 -1
  34. package/dist/esm/interface/plan-usage.d.ts.map +1 -1
  35. package/dist/esm/interface/plan-usage.js +1 -0
  36. package/dist/esm/interface/plan-usage.js.map +1 -1
  37. package/dist/esm/interface/server-interface.js +1 -1
  38. package/dist/esm/interface/webhooks.d.ts +2 -2
  39. package/dist/esm/known-errors.d.ts +3 -3
  40. package/dist/esm/schema-fields.d.ts +12 -12
  41. package/dist/esm/schema-fields.d.ts.map +1 -1
  42. package/dist/esm/schema-fields.js +2 -2
  43. package/dist/esm/schema-fields.js.map +1 -1
  44. package/dist/esm/sessions.d.ts +9 -9
  45. package/dist/esm/utils/currencies.d.ts +16 -1
  46. package/dist/esm/utils/currencies.d.ts.map +1 -1
  47. package/dist/esm/utils/currencies.js +24 -1
  48. package/dist/esm/utils/currencies.js.map +1 -1
  49. package/dist/esm/utils/dates.d.ts +18 -1
  50. package/dist/esm/utils/dates.d.ts.map +1 -1
  51. package/dist/esm/utils/dates.js +36 -15
  52. package/dist/esm/utils/dates.js.map +1 -1
  53. package/dist/helpers/password.d.ts +1 -1
  54. package/dist/helpers/production-mode.d.ts +1 -1
  55. package/dist/index.d.ts +4 -4
  56. package/dist/interface/admin-interface.d.ts +2 -2
  57. package/dist/interface/admin-interface.js +1 -1
  58. package/dist/interface/admin-metrics.d.ts +1 -1
  59. package/dist/interface/client-interface.d.ts +1 -1
  60. package/dist/interface/client-interface.js +1 -1
  61. package/dist/interface/conversations.d.ts +7 -7
  62. package/dist/interface/crud/current-user.d.ts +1 -1
  63. package/dist/interface/crud/email-outbox.d.ts +1 -1
  64. package/dist/interface/crud/invoices.d.ts +1 -1
  65. package/dist/interface/crud/products.d.ts +1 -1
  66. package/dist/interface/crud/project-api-keys.d.ts +1 -1
  67. package/dist/interface/crud/projects.d.ts +1 -1
  68. package/dist/interface/crud/team-member-profiles.d.ts +1 -1
  69. package/dist/interface/crud/transactions.d.ts +1 -1
  70. package/dist/interface/crud/users.d.ts +1 -1
  71. package/dist/interface/plan-usage.d.ts +1 -1
  72. package/dist/interface/plan-usage.js +1 -0
  73. package/dist/interface/plan-usage.js.map +1 -1
  74. package/dist/interface/server-interface.d.ts +1 -1
  75. package/dist/interface/server-interface.js +1 -1
  76. package/dist/interface/webhooks.d.ts +1 -1
  77. package/dist/{invoices-BGLLnTlR.d.ts → invoices-U65KzAZX.d.ts} +2 -2
  78. package/dist/{invoices-BGLLnTlR.d.ts.map → invoices-U65KzAZX.d.ts.map} +1 -1
  79. package/dist/{known-errors-g7JC8z58.d.ts → known-errors-Bm4a61wL.d.ts} +4 -4
  80. package/dist/{known-errors-g7JC8z58.d.ts.map → known-errors-Bm4a61wL.d.ts.map} +1 -1
  81. package/dist/known-errors.d.ts +1 -1
  82. package/dist/{plan-usage-BigvGIcT.d.ts → plan-usage-BaDxcLZ1.d.ts} +4 -2
  83. package/dist/plan-usage-BaDxcLZ1.d.ts.map +1 -0
  84. package/dist/{products-D_fcxfR0.d.ts → products-D4o8A2W0.d.ts} +23 -23
  85. package/dist/{products-D_fcxfR0.d.ts.map → products-D4o8A2W0.d.ts.map} +1 -1
  86. package/dist/{project-api-keys-OQqmKtMS.d.ts → project-api-keys--7V5X_UW.d.ts} +5 -5
  87. package/dist/{project-api-keys-OQqmKtMS.d.ts.map → project-api-keys--7V5X_UW.d.ts.map} +1 -1
  88. package/dist/{projects-C42SVFvm.d.ts → projects-dH9I0bcX.d.ts} +17 -17
  89. package/dist/{projects-C42SVFvm.d.ts.map → projects-dH9I0bcX.d.ts.map} +1 -1
  90. package/dist/{schema-Bgy-GC70.d.ts → schema-BSb4tzx3.d.ts} +94 -94
  91. package/dist/{schema-Bgy-GC70.d.ts.map → schema-BSb4tzx3.d.ts.map} +1 -1
  92. package/dist/{schema-fields-BljhsWsa.d.ts → schema-fields-DZtDQEEO.d.ts} +14 -14
  93. package/dist/schema-fields-DZtDQEEO.d.ts.map +1 -0
  94. package/dist/schema-fields.d.ts +1 -1
  95. package/dist/schema-fields.js +2 -2
  96. package/dist/schema-fields.js.map +1 -1
  97. package/dist/{server-interface-C1W1tZ_y.d.ts → server-interface-CxorzgTW.d.ts} +8 -8
  98. package/dist/{server-interface-C1W1tZ_y.d.ts.map → server-interface-CxorzgTW.d.ts.map} +1 -1
  99. package/dist/{sessions-C0nM8bE_.d.ts → sessions-CI-0TBQb.d.ts} +11 -11
  100. package/dist/{sessions-C0nM8bE_.d.ts.map → sessions-CI-0TBQb.d.ts.map} +1 -1
  101. package/dist/sessions.d.ts +1 -1
  102. package/dist/{team-member-profiles-CgYXR-Rx.d.ts → team-member-profiles-uTluO8XI.d.ts} +23 -23
  103. package/dist/{team-member-profiles-CgYXR-Rx.d.ts.map → team-member-profiles-uTluO8XI.d.ts.map} +1 -1
  104. package/dist/{transactions-BomBBiph.d.ts → transactions-CHNUJ42J.d.ts} +19 -19
  105. package/dist/transactions-CHNUJ42J.d.ts.map +1 -0
  106. package/dist/{users-7MKfEyyq.d.ts → users-CmBBuF00.d.ts} +14 -14
  107. package/dist/{users-7MKfEyyq.d.ts.map → users-CmBBuF00.d.ts.map} +1 -1
  108. package/dist/utils/currencies.d.ts +16 -1
  109. package/dist/utils/currencies.d.ts.map +1 -1
  110. package/dist/utils/currencies.js +24 -0
  111. package/dist/utils/currencies.js.map +1 -1
  112. package/dist/utils/dates.d.ts +2 -2
  113. package/dist/utils/dates.js +36 -14
  114. package/dist/utils/dates.js.map +1 -1
  115. package/dist/{webhooks-C5gG85Ce.d.ts → webhooks-ByXrdSOx.d.ts} +3 -3
  116. package/dist/{webhooks-C5gG85Ce.d.ts.map → webhooks-ByXrdSOx.d.ts.map} +1 -1
  117. package/package.json +1 -1
  118. package/src/interface/plan-usage.ts +1 -0
  119. package/src/schema-fields.ts +13 -2
  120. package/src/utils/currencies.tsx +69 -0
  121. package/src/utils/dates.tsx +104 -15
  122. package/dist/dates-B6ne9iOR.d.ts +0 -23
  123. package/dist/plan-usage-BigvGIcT.d.ts.map +0 -1
  124. package/dist/schema-fields-BljhsWsa.d.ts.map +0 -1
  125. package/dist/transactions-BomBBiph.d.ts.map +0 -1
@@ -19,35 +19,36 @@ declare const teamMemberProfilesCrudServerReadSchema: import("yup").ObjectSchema
19
19
  profile_image_url: string | null;
20
20
  } & {
21
21
  user: {
22
- id: string;
22
+ restricted_reason: {
23
+ type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
24
+ } | null;
25
+ primary_email: string | null;
26
+ display_name: string | null;
23
27
  client_metadata: {} | null;
24
28
  client_read_only_metadata: {} | null;
25
29
  server_metadata: {} | null;
26
- primary_email: string | null;
30
+ id: string;
31
+ selected_team_id: string | null;
32
+ is_anonymous: boolean;
33
+ is_restricted: boolean;
34
+ requires_totp_mfa: boolean;
27
35
  primary_email_verified: boolean;
28
36
  primary_email_auth_enabled: boolean;
29
- display_name: string | null;
30
37
  profile_image_url: string | null;
31
38
  selected_team: {
32
39
  client_metadata?: {} | null | undefined;
33
40
  client_read_only_metadata?: {} | null | undefined;
34
41
  server_metadata?: {} | null | undefined;
35
- id: string;
36
42
  display_name: string;
43
+ id: string;
37
44
  profile_image_url: string | null;
38
45
  created_at_millis: number;
39
46
  } | null;
40
- selected_team_id: string | null;
41
47
  signed_up_at_millis: number;
42
48
  has_password: boolean;
43
49
  otp_auth_enabled: boolean;
44
50
  passkey_auth_enabled: boolean;
45
51
  last_active_at_millis: number;
46
- is_anonymous: boolean;
47
- is_restricted: boolean;
48
- restricted_reason: {
49
- type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
50
- } | null;
51
52
  restricted_by_admin: boolean;
52
53
  restricted_by_admin_reason: string | null;
53
54
  restricted_by_admin_private_details: string | null;
@@ -64,7 +65,6 @@ declare const teamMemberProfilesCrudServerReadSchema: import("yup").ObjectSchema
64
65
  account_id: string;
65
66
  }[];
66
67
  auth_with_email: boolean;
67
- requires_totp_mfa: boolean;
68
68
  };
69
69
  }, import("yup").AnyObject, {
70
70
  team_id: undefined;
@@ -142,35 +142,36 @@ declare const teamMemberProfilesCrud: CrudSchemaFromOptions<{
142
142
  profile_image_url: string | null;
143
143
  } & {
144
144
  user: {
145
- id: string;
145
+ restricted_reason: {
146
+ type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
147
+ } | null;
148
+ primary_email: string | null;
149
+ display_name: string | null;
146
150
  client_metadata: {} | null;
147
151
  client_read_only_metadata: {} | null;
148
152
  server_metadata: {} | null;
149
- primary_email: string | null;
153
+ id: string;
154
+ selected_team_id: string | null;
155
+ is_anonymous: boolean;
156
+ is_restricted: boolean;
157
+ requires_totp_mfa: boolean;
150
158
  primary_email_verified: boolean;
151
159
  primary_email_auth_enabled: boolean;
152
- display_name: string | null;
153
160
  profile_image_url: string | null;
154
161
  selected_team: {
155
162
  client_metadata?: {} | null | undefined;
156
163
  client_read_only_metadata?: {} | null | undefined;
157
164
  server_metadata?: {} | null | undefined;
158
- id: string;
159
165
  display_name: string;
166
+ id: string;
160
167
  profile_image_url: string | null;
161
168
  created_at_millis: number;
162
169
  } | null;
163
- selected_team_id: string | null;
164
170
  signed_up_at_millis: number;
165
171
  has_password: boolean;
166
172
  otp_auth_enabled: boolean;
167
173
  passkey_auth_enabled: boolean;
168
174
  last_active_at_millis: number;
169
- is_anonymous: boolean;
170
- is_restricted: boolean;
171
- restricted_reason: {
172
- type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
173
- } | null;
174
175
  restricted_by_admin: boolean;
175
176
  restricted_by_admin_reason: string | null;
176
177
  restricted_by_admin_private_details: string | null;
@@ -187,7 +188,6 @@ declare const teamMemberProfilesCrud: CrudSchemaFromOptions<{
187
188
  account_id: string;
188
189
  }[];
189
190
  auth_with_email: boolean;
190
- requires_totp_mfa: boolean;
191
191
  };
192
192
  }, import("yup").AnyObject, {
193
193
  team_id: undefined;
@@ -282,4 +282,4 @@ declare const teamMemberProfilesCrud: CrudSchemaFromOptions<{
282
282
  type TeamMemberProfilesCrud = CrudTypeOf<typeof teamMemberProfilesCrud>;
283
283
  //#endregion
284
284
  export { teamMemberProfilesCrudServerReadSchema as a, teamMemberProfilesCrudClientUpdateSchema as i, teamMemberProfilesCrud as n, teamMemberProfilesCrudClientReadSchema as r, TeamMemberProfilesCrud as t };
285
- //# sourceMappingURL=team-member-profiles-CgYXR-Rx.d.ts.map
285
+ //# sourceMappingURL=team-member-profiles-uTluO8XI.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"team-member-profiles-CgYXR-Rx.d.ts","names":[],"sources":["../src/interface/crud/team-member-profiles.ts"],"mappings":";;;cAMa,sCAAA,gBAAsC,YAAA;;;;;;;;;;;cAOtC,sCAAA,gBAAsC,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAItC,wCAAA,gBAAwC,YAAA;;;;;;;cAKxC,sBAAA,EAoCX,qBApCiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCvB,sBAAA,GAAyB,UAAU,QAAQ,sBAAA"}
1
+ {"version":3,"file":"team-member-profiles-uTluO8XI.d.ts","names":[],"sources":["../src/interface/crud/team-member-profiles.ts"],"mappings":";;;cAMa,sCAAA,gBAAsC,YAAA;;;;;;;;;;;cAOtC,sCAAA,gBAAsC,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAItC,wCAAA,gBAAwC,YAAA;;;;;;;cAKxC,sBAAA,EAoCX,qBApCiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCvB,sBAAA,GAAyB,UAAU,QAAQ,sBAAA"}
@@ -1,11 +1,11 @@
1
- import { t as DayInterval } from "./dates-B6ne9iOR.js";
1
+ import { t as DayInterval } from "./dates-BRAvSk6L.js";
2
2
  import { InferType } from "yup";
3
3
 
4
4
  //#region src/interface/crud/transactions.d.ts
5
5
  declare const transactionEntrySchema: import("yup").MixedSchema<{
6
6
  type: "money_transfer";
7
7
  customer_id: string;
8
- customer_type: "user" | "team" | "custom";
8
+ customer_type: "team" | "user" | "custom";
9
9
  charged_amount: {
10
10
  USD?: string | undefined;
11
11
  EUR?: string | undefined;
@@ -25,7 +25,7 @@ declare const transactionEntrySchema: import("yup").MixedSchema<{
25
25
  item_id: string;
26
26
  customer_id: string;
27
27
  quantity: number;
28
- customer_type: "user" | "team" | "custom";
28
+ customer_type: "team" | "user" | "custom";
29
29
  adjusted_transaction_id: string | null;
30
30
  adjusted_entry_index: number | null;
31
31
  } | {
@@ -35,18 +35,16 @@ declare const transactionEntrySchema: import("yup").MixedSchema<{
35
35
  customer_id: string;
36
36
  product_id: string | null;
37
37
  quantity: number;
38
- customer_type: "user" | "team" | "custom";
38
+ customer_type: "team" | "user" | "custom";
39
39
  product: {
40
+ free_trial?: DayInterval | undefined;
40
41
  client_metadata?: {} | null | undefined;
41
42
  client_read_only_metadata?: {} | null | undefined;
42
43
  server_metadata?: {} | null | undefined;
43
- free_trial?: DayInterval | undefined;
44
- display_name: string;
45
44
  server_only: boolean;
46
- customer_type: "user" | "team" | "custom";
45
+ customer_type: "team" | "user" | "custom";
47
46
  stackable: boolean;
48
47
  prices: Record<string, {
49
- free_trial?: DayInterval | undefined;
50
48
  USD?: string | undefined;
51
49
  EUR?: string | undefined;
52
50
  GBP?: string | undefined;
@@ -55,10 +53,12 @@ declare const transactionEntrySchema: import("yup").MixedSchema<{
55
53
  AUD?: string | undefined;
56
54
  CAD?: string | undefined;
57
55
  interval?: DayInterval | undefined;
56
+ free_trial?: DayInterval | undefined;
58
57
  }>;
58
+ display_name: string;
59
59
  included_items: Record<string, {
60
- repeat?: "never" | DayInterval | undefined;
61
60
  quantity?: number | undefined;
61
+ repeat?: "never" | DayInterval | undefined;
62
62
  expires?: "never" | "when-purchase-expires" | "when-repeated" | undefined;
63
63
  }>;
64
64
  };
@@ -84,12 +84,12 @@ declare const transactionSchema: import("yup").ObjectSchema<{
84
84
  created_at_millis: number;
85
85
  effective_at_millis: number;
86
86
  type: "purchase" | "subscription-cancellation" | "subscription-renewal" | "manual-item-quantity-change" | "refund" | "chargeback" | "product-change" | null;
87
- customer_type: "user" | "team" | "custom";
87
+ customer_type: "team" | "user" | "custom";
88
88
  customer_id: string;
89
89
  entries: ({
90
90
  type: "money_transfer";
91
91
  customer_id: string;
92
- customer_type: "user" | "team" | "custom";
92
+ customer_type: "team" | "user" | "custom";
93
93
  charged_amount: {
94
94
  USD?: string | undefined;
95
95
  EUR?: string | undefined;
@@ -109,7 +109,7 @@ declare const transactionSchema: import("yup").ObjectSchema<{
109
109
  item_id: string;
110
110
  customer_id: string;
111
111
  quantity: number;
112
- customer_type: "user" | "team" | "custom";
112
+ customer_type: "team" | "user" | "custom";
113
113
  adjusted_transaction_id: string | null;
114
114
  adjusted_entry_index: number | null;
115
115
  } | {
@@ -119,18 +119,16 @@ declare const transactionSchema: import("yup").ObjectSchema<{
119
119
  customer_id: string;
120
120
  product_id: string | null;
121
121
  quantity: number;
122
- customer_type: "user" | "team" | "custom";
122
+ customer_type: "team" | "user" | "custom";
123
123
  product: {
124
+ free_trial?: DayInterval | undefined;
124
125
  client_metadata?: {} | null | undefined;
125
126
  client_read_only_metadata?: {} | null | undefined;
126
127
  server_metadata?: {} | null | undefined;
127
- free_trial?: DayInterval | undefined;
128
- display_name: string;
129
128
  server_only: boolean;
130
- customer_type: "user" | "team" | "custom";
129
+ customer_type: "team" | "user" | "custom";
131
130
  stackable: boolean;
132
131
  prices: Record<string, {
133
- free_trial?: DayInterval | undefined;
134
132
  USD?: string | undefined;
135
133
  EUR?: string | undefined;
136
134
  GBP?: string | undefined;
@@ -139,10 +137,12 @@ declare const transactionSchema: import("yup").ObjectSchema<{
139
137
  AUD?: string | undefined;
140
138
  CAD?: string | undefined;
141
139
  interval?: DayInterval | undefined;
140
+ free_trial?: DayInterval | undefined;
142
141
  }>;
142
+ display_name: string;
143
143
  included_items: Record<string, {
144
- repeat?: "never" | DayInterval | undefined;
145
144
  quantity?: number | undefined;
145
+ repeat?: "never" | DayInterval | undefined;
146
146
  expires?: "never" | "when-purchase-expires" | "when-repeated" | undefined;
147
147
  }>;
148
148
  };
@@ -179,4 +179,4 @@ declare const transactionSchema: import("yup").ObjectSchema<{
179
179
  type Transaction = InferType<typeof transactionSchema>;
180
180
  //#endregion
181
181
  export { transactionEntrySchema as a, TransactionType as i, Transaction as n, transactionSchema as o, TransactionEntry as r, TRANSACTION_TYPES as t };
182
- //# sourceMappingURL=transactions-BomBBiph.d.ts.map
182
+ //# sourceMappingURL=transactions-CHNUJ42J.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions-CHNUJ42J.d.ts","names":[],"sources":["../src/interface/crud/transactions.ts"],"mappings":";;;;cAwFa,sBAAA,gBAAsB,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMxB,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEC,gBAAA,GAAmB,SAAS,QAAQ,sBAAA;AAAA,cAEnC,iBAAA;AAAA,KAUD,eAAA,WAA0B,iBAAiB;AAAA,cAE1C,iBAAA,gBAAiB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAkBlB,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEA,WAAA,GAAc,SAAS,QAAQ,iBAAA"}
@@ -1,5 +1,5 @@
1
1
  import { c as CrudTypeOf, s as CrudSchemaFromOptions } from "./crud-CqmEW9s6.js";
2
- import { t as WebhookEvent } from "./webhooks-C5gG85Ce.js";
2
+ import { t as WebhookEvent } from "./webhooks-ByXrdSOx.js";
3
3
  import * as yup$1 from "yup";
4
4
  import { InferType } from "yup";
5
5
 
@@ -80,8 +80,8 @@ declare const usersCrudServerReadSchema: yup$1.ObjectSchema<{
80
80
  client_metadata?: {} | null | undefined;
81
81
  client_read_only_metadata?: {} | null | undefined;
82
82
  server_metadata?: {} | null | undefined;
83
- id: string;
84
83
  display_name: string;
84
+ id: string;
85
85
  profile_image_url: string | null;
86
86
  created_at_millis: number;
87
87
  } | null;
@@ -162,17 +162,17 @@ declare const usersCrudServerReadSchema: yup$1.ObjectSchema<{
162
162
  requires_totp_mfa: undefined;
163
163
  }, "">;
164
164
  declare const usersCrudServerCreateSchema: yup$1.ObjectSchema<{
165
+ primary_email: string | null | undefined;
166
+ display_name: string | null | undefined;
165
167
  client_metadata: {} | null | undefined;
166
168
  client_read_only_metadata: {} | null | undefined;
167
169
  server_metadata: {} | null | undefined;
168
- primary_email: string | null | undefined;
170
+ is_anonymous: boolean | undefined;
169
171
  primary_email_verified: boolean | undefined;
170
172
  primary_email_auth_enabled: boolean | undefined;
171
- display_name: string | null | undefined;
172
173
  profile_image_url: string | null | undefined;
173
174
  otp_auth_enabled: boolean | undefined;
174
175
  passkey_auth_enabled: boolean | undefined;
175
- is_anonymous: boolean | undefined;
176
176
  restricted_by_admin: boolean | undefined;
177
177
  restricted_by_admin_reason: string | null | undefined;
178
178
  restricted_by_admin_private_details: string | null | undefined;
@@ -188,8 +188,8 @@ declare const usersCrudServerCreateSchema: yup$1.ObjectSchema<{
188
188
  totp_secret_base64: string | null | undefined;
189
189
  } & {
190
190
  oauth_providers: {
191
- id: string;
192
191
  email: string | null;
192
+ id: string;
193
193
  account_id: string;
194
194
  }[] | undefined;
195
195
  is_anonymous: boolean | undefined;
@@ -233,8 +233,8 @@ declare const usersCrud: CrudSchemaFromOptions<{
233
233
  client_metadata?: {} | null | undefined;
234
234
  client_read_only_metadata?: {} | null | undefined;
235
235
  server_metadata?: {} | null | undefined;
236
- id: string;
237
236
  display_name: string;
237
+ id: string;
238
238
  profile_image_url: string | null;
239
239
  created_at_millis: number;
240
240
  } | null;
@@ -368,17 +368,17 @@ declare const usersCrud: CrudSchemaFromOptions<{
368
368
  };
369
369
  }, "">;
370
370
  serverCreateSchema: yup$1.ObjectSchema<{
371
+ primary_email: string | null | undefined;
372
+ display_name: string | null | undefined;
371
373
  client_metadata: {} | null | undefined;
372
374
  client_read_only_metadata: {} | null | undefined;
373
375
  server_metadata: {} | null | undefined;
374
- primary_email: string | null | undefined;
376
+ is_anonymous: boolean | undefined;
375
377
  primary_email_verified: boolean | undefined;
376
378
  primary_email_auth_enabled: boolean | undefined;
377
- display_name: string | null | undefined;
378
379
  profile_image_url: string | null | undefined;
379
380
  otp_auth_enabled: boolean | undefined;
380
381
  passkey_auth_enabled: boolean | undefined;
381
- is_anonymous: boolean | undefined;
382
382
  restricted_by_admin: boolean | undefined;
383
383
  restricted_by_admin_reason: string | null | undefined;
384
384
  restricted_by_admin_private_details: string | null | undefined;
@@ -394,8 +394,8 @@ declare const usersCrud: CrudSchemaFromOptions<{
394
394
  totp_secret_base64: string | null | undefined;
395
395
  } & {
396
396
  oauth_providers: {
397
- id: string;
398
397
  email: string | null;
398
+ id: string;
399
399
  account_id: string;
400
400
  }[] | undefined;
401
401
  is_anonymous: boolean | undefined;
@@ -467,8 +467,8 @@ declare const userCreatedWebhookEvent: WebhookEvent<yup$1.ObjectSchema<{
467
467
  client_metadata?: {} | null | undefined;
468
468
  client_read_only_metadata?: {} | null | undefined;
469
469
  server_metadata?: {} | null | undefined;
470
- id: string;
471
470
  display_name: string;
471
+ id: string;
472
472
  profile_image_url: string | null;
473
473
  created_at_millis: number;
474
474
  } | null;
@@ -558,8 +558,8 @@ declare const userUpdatedWebhookEvent: WebhookEvent<yup$1.ObjectSchema<{
558
558
  client_metadata?: {} | null | undefined;
559
559
  client_read_only_metadata?: {} | null | undefined;
560
560
  server_metadata?: {} | null | undefined;
561
- id: string;
562
561
  display_name: string;
562
+ id: string;
563
563
  profile_image_url: string | null;
564
564
  created_at_millis: number;
565
565
  } | null;
@@ -650,4 +650,4 @@ declare const userDeletedWebhookEvent: WebhookEvent<yup$1.ObjectSchema<{
650
650
  }, "">>;
651
651
  //#endregion
652
652
  export { userCreatedWebhookEvent as a, usersCrud as c, usersCrudServerReadSchema as d, usersCrudServerUpdateSchema as f, signUpRiskScoresSchema as i, usersCrudServerCreateSchema as l, UsersCrud as n, userDeletedWebhookEvent as o, riskScoreFieldSchema as r, userUpdatedWebhookEvent as s, SignUpRiskScoresCrud as t, usersCrudServerDeleteSchema as u };
653
- //# sourceMappingURL=users-7MKfEyyq.d.ts.map
653
+ //# sourceMappingURL=users-CmBBuF00.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"users-7MKfEyyq.d.ts","names":[],"sources":["../src/interface/crud/users.ts"],"mappings":";;;;;;cAea,oBAAA,EAAoB,KAAA,CAAA,YAAA,SAAA,KAAA,CAAA,SAAA;AAAA,cACpB,sBAAA,EAAsB,KAAA,CAAA,YAAA;;;;;GAKjC,KAAA,CAAA,SAAA;;;;;;KACU,oBAAA,GAAuB,SAAS,QAAQ,sBAAA;AAAA,cAqBvC,2BAAA,EAA2B,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GAyBvC,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEY,yBAAA,EAAyB,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CrC,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEY,2BAAA,EAA2B,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAM3B,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEA,2BAAA,EAA2B,KAAA,CAAA,WAAA,iBAAA,KAAA,CAAA,SAAA;AAAA,cAE3B,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiCD,SAAA,GAAY,UAAU,QAAQ,SAAA;AAAA,cAc7B,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cACvB,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAQvB,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA"}
1
+ {"version":3,"file":"users-CmBBuF00.d.ts","names":[],"sources":["../src/interface/crud/users.ts"],"mappings":";;;;;;cAea,oBAAA,EAAoB,KAAA,CAAA,YAAA,SAAA,KAAA,CAAA,SAAA;AAAA,cACpB,sBAAA,EAAsB,KAAA,CAAA,YAAA;;;;;GAKjC,KAAA,CAAA,SAAA;;;;;;KACU,oBAAA,GAAuB,SAAS,QAAQ,sBAAA;AAAA,cAqBvC,2BAAA,EAA2B,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GAyBvC,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEY,yBAAA,EAAyB,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CrC,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEY,2BAAA,EAA2B,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAM3B,KAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEA,2BAAA,EAA2B,KAAA,CAAA,WAAA,iBAAA,KAAA,CAAA,SAAA;AAAA,cAE3B,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiCD,SAAA,GAAY,UAAU,QAAQ,SAAA;AAAA,cAc7B,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cACvB,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAQvB,uBAAA,EAAuB,YAAA,CAAA,KAAA,CAAA,YAAA"}
@@ -3,6 +3,21 @@ import { n as MoneyAmount, r as SUPPORTED_CURRENCIES, t as Currency } from "../c
3
3
  //#region src/utils/currencies.d.ts
4
4
  type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];
5
5
  declare function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number;
6
+ /**
7
+ * Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount
8
+ * (e.g. cents) back into the canonical decimal money string for the currency.
9
+ * E.g. for USD (2 decimals): 5000 → "50.00", 1 → "0.01"; for JPY (0 decimals):
10
+ * 500 → "500".
11
+ *
12
+ * Prefer this over `String(number)` whenever an amount is scaled: money math
13
+ * must happen in integer minor units, because float multiplication like
14
+ * `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects
15
+ * for having more than the currency's allowed decimals.
16
+ *
17
+ * Money amounts are non-negative (see `MoneyAmount`), so a negative input is a
18
+ * programming error and throws rather than silently dropping the sign.
19
+ */
20
+ declare function stripeUnitsToMoneyAmount(stripeUnits: number, currency: Currency): MoneyAmount;
6
21
  //#endregion
7
- export { SupportedCurrency, moneyAmountToStripeUnits };
22
+ export { SupportedCurrency, moneyAmountToStripeUnits, stripeUnitsToMoneyAmount };
8
23
  //# sourceMappingURL=currencies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"currencies.d.ts","names":[],"sources":["../../src/utils/currencies.tsx"],"mappings":";;;KAIY,iBAAA,WAA4B,oBAAoB;AAAA,iBAE5C,wBAAA,CAAyB,MAAA,EAAQ,WAAA,EAAa,QAAA,EAAU,QAAQ"}
1
+ {"version":3,"file":"currencies.d.ts","names":[],"sources":["../../src/utils/currencies.tsx"],"mappings":";;;KAIY,iBAAA,WAA4B,oBAAoB;AAAA,iBAE5C,wBAAA,CAAyB,MAAA,EAAQ,WAAA,EAAa,QAAA,EAAU,QAAQ;AAFhF;;;;AAA4D;AAE5D;;;;;;;;;AAFA,iBA8BgB,wBAAA,CAAyB,WAAA,UAAqB,QAAA,EAAU,QAAA,GAAW,WAAW"}
@@ -10,7 +10,31 @@ function moneyAmountToStripeUnits(amount, currency) {
10
10
  const paddedFractional = fractional.padEnd(currency.decimals, "0");
11
11
  return Number.parseInt(whole + paddedFractional, 10);
12
12
  }
13
+ /**
14
+ * Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount
15
+ * (e.g. cents) back into the canonical decimal money string for the currency.
16
+ * E.g. for USD (2 decimals): 5000 → "50.00", 1 → "0.01"; for JPY (0 decimals):
17
+ * 500 → "500".
18
+ *
19
+ * Prefer this over `String(number)` whenever an amount is scaled: money math
20
+ * must happen in integer minor units, because float multiplication like
21
+ * `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects
22
+ * for having more than the currency's allowed decimals.
23
+ *
24
+ * Money amounts are non-negative (see `MoneyAmount`), so a negative input is a
25
+ * programming error and throws rather than silently dropping the sign.
26
+ */
27
+ function stripeUnitsToMoneyAmount(stripeUnits, currency) {
28
+ if (!Number.isFinite(stripeUnits) || Math.trunc(stripeUnits) !== stripeUnits) throw new __errors_js.HexclaveAssertionError("Stripe units must be an integer", { stripeUnits });
29
+ if (stripeUnits < 0) throw new __errors_js.HexclaveAssertionError("Money amounts are non-negative; cannot represent negative stripe units", { stripeUnits });
30
+ if (currency.stripeDecimals !== currency.decimals) throw new __errors_js.HexclaveAssertionError("unimplemented: TODO support different decimal configurations");
31
+ const decimals = currency.decimals;
32
+ if (decimals === 0) return `${stripeUnits}`;
33
+ const padded = stripeUnits.toString().padStart(decimals + 1, "0");
34
+ return `${padded.slice(0, padded.length - decimals)}.${padded.slice(padded.length - decimals)}`;
35
+ }
13
36
  //#endregion
14
37
  exports.moneyAmountToStripeUnits = moneyAmountToStripeUnits;
38
+ exports.stripeUnitsToMoneyAmount = stripeUnitsToMoneyAmount;
15
39
 
16
40
  //# sourceMappingURL=currencies.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"currencies.js","names":["HexclaveAssertionError"],"sources":["../../src/utils/currencies.tsx"],"sourcesContent":["import { moneyAmountSchema } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./currency-constants\";\nimport { HexclaveAssertionError } from \"./errors\";\n\nexport type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];\n\nexport function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number {\n const validated = moneyAmountSchema(currency).defined().validateSync(amount);\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n // `moneyAmountSchema` accepts strings with 0..currency.decimals fractional\n // digits, so we must right-pad the fractional part before stripping the dot.\n // A naïve `replace('.', '')` underweights inputs like \"5\" → 5 (should be 500\n // for USD) and \"0.5\" → 5 (should be 50).\n const [whole, fractional = \"\"] = validated.split(\".\");\n const paddedFractional = fractional.padEnd(currency.decimals, \"0\");\n return Number.parseInt(whole + paddedFractional, 10);\n}\n\nimport.meta.vitest?.describe(\"moneyAmountToStripeUnits\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n\n test(\"converts fully-padded USD amounts\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.00\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"0.01\" as MoneyAmount, USD)).toBe(1);\n expect(moneyAmountToStripeUnits(\"12.34\" as MoneyAmount, USD)).toBe(1234);\n });\n\n test(\"converts whole-number USD amounts (no decimals)\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"10\" as MoneyAmount, USD)).toBe(1000);\n expect(moneyAmountToStripeUnits(\"0\" as MoneyAmount, USD)).toBe(0);\n });\n\n test(\"converts USD amounts with one decimal digit\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.5\" as MoneyAmount, USD)).toBe(550);\n expect(moneyAmountToStripeUnits(\"0.5\" as MoneyAmount, USD)).toBe(50);\n });\n\n test(\"matches stripeUnitsToMoneyAmount round-trip\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n const padded = `${Math.floor(cents / 100)}.${(cents % 100).toString().padStart(2, \"0\")}` as MoneyAmount;\n expect(moneyAmountToStripeUnits(padded, USD)).toBe(cents);\n }\n });\n\n test(\"rejects invalid money strings via schema\", ({ expect }) => {\n expect(() => moneyAmountToStripeUnits(\"abc\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"5.555\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"05\" as MoneyAmount, USD)).toThrow();\n });\n});\n"],"mappings":";;;;;AAMA,SAAgB,yBAAyB,QAAqB,UAA4B;CACxF,MAAM,aAAA,GAAA,oBAAA,kBAAA,CAA8B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,MAAM;CAC3E,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAIA,YAAAA,uBAAuB,8DAA8D;CAMjG,MAAM,CAAC,OAAO,aAAa,MAAM,UAAU,MAAM,GAAG;CACpD,MAAM,mBAAmB,WAAW,OAAO,SAAS,UAAU,GAAG;CACjE,OAAO,OAAO,SAAS,QAAQ,kBAAkB,EAAE;AACrD"}
1
+ {"version":3,"file":"currencies.js","names":["HexclaveAssertionError"],"sources":["../../src/utils/currencies.tsx"],"sourcesContent":["import { moneyAmountSchema } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./currency-constants\";\nimport { HexclaveAssertionError } from \"./errors\";\n\nexport type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];\n\nexport function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number {\n const validated = moneyAmountSchema(currency).defined().validateSync(amount);\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n // `moneyAmountSchema` accepts strings with 0..currency.decimals fractional\n // digits, so we must right-pad the fractional part before stripping the dot.\n // A naïve `replace('.', '')` underweights inputs like \"5\" → 5 (should be 500\n // for USD) and \"0.5\" → 5 (should be 50).\n const [whole, fractional = \"\"] = validated.split(\".\");\n const paddedFractional = fractional.padEnd(currency.decimals, \"0\");\n return Number.parseInt(whole + paddedFractional, 10);\n}\n\n/**\n * Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount\n * (e.g. cents) back into the canonical decimal money string for the currency.\n * E.g. for USD (2 decimals): 5000 → \"50.00\", 1 → \"0.01\"; for JPY (0 decimals):\n * 500 → \"500\".\n *\n * Prefer this over `String(number)` whenever an amount is scaled: money math\n * must happen in integer minor units, because float multiplication like\n * `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects\n * for having more than the currency's allowed decimals.\n *\n * Money amounts are non-negative (see `MoneyAmount`), so a negative input is a\n * programming error and throws rather than silently dropping the sign.\n */\nexport function stripeUnitsToMoneyAmount(stripeUnits: number, currency: Currency): MoneyAmount {\n if (!Number.isFinite(stripeUnits) || Math.trunc(stripeUnits) !== stripeUnits) {\n throw new HexclaveAssertionError(\"Stripe units must be an integer\", { stripeUnits });\n }\n if (stripeUnits < 0) {\n throw new HexclaveAssertionError(\"Money amounts are non-negative; cannot represent negative stripe units\", { stripeUnits });\n }\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n const decimals = currency.decimals;\n if (decimals === 0) return `${stripeUnits}` as MoneyAmount;\n // Pad so there's always at least one integer digit plus `decimals` fractional\n // digits, then split at the dot position.\n const padded = stripeUnits.toString().padStart(decimals + 1, \"0\");\n const integerPart = padded.slice(0, padded.length - decimals);\n const fractionalPart = padded.slice(padded.length - decimals);\n return `${integerPart}.${fractionalPart}` as MoneyAmount;\n}\n\nimport.meta.vitest?.describe(\"moneyAmountToStripeUnits\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n\n test(\"converts fully-padded USD amounts\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.00\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"0.01\" as MoneyAmount, USD)).toBe(1);\n expect(moneyAmountToStripeUnits(\"12.34\" as MoneyAmount, USD)).toBe(1234);\n });\n\n test(\"converts whole-number USD amounts (no decimals)\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"10\" as MoneyAmount, USD)).toBe(1000);\n expect(moneyAmountToStripeUnits(\"0\" as MoneyAmount, USD)).toBe(0);\n });\n\n test(\"converts USD amounts with one decimal digit\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.5\" as MoneyAmount, USD)).toBe(550);\n expect(moneyAmountToStripeUnits(\"0.5\" as MoneyAmount, USD)).toBe(50);\n });\n\n test(\"matches stripeUnitsToMoneyAmount round-trip\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n const padded = `${Math.floor(cents / 100)}.${(cents % 100).toString().padStart(2, \"0\")}` as MoneyAmount;\n expect(moneyAmountToStripeUnits(padded, USD)).toBe(cents);\n }\n });\n\n test(\"rejects invalid money strings via schema\", ({ expect }) => {\n expect(() => moneyAmountToStripeUnits(\"abc\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"5.555\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"05\" as MoneyAmount, USD)).toThrow();\n });\n});\n\nimport.meta.vitest?.describe(\"stripeUnitsToMoneyAmount\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n const JPY = SUPPORTED_CURRENCIES.find((c) => c.code === \"JPY\")!;\n\n test(\"formats USD minor units as a 2-decimal string\", ({ expect }) => {\n expect(stripeUnitsToMoneyAmount(5000, USD)).toBe(\"50.00\");\n expect(stripeUnitsToMoneyAmount(1, USD)).toBe(\"0.01\");\n expect(stripeUnitsToMoneyAmount(100, USD)).toBe(\"1.00\");\n expect(stripeUnitsToMoneyAmount(0, USD)).toBe(\"0.00\");\n });\n\n test(\"formats 0-decimal currencies without a dot\", ({ expect }) => {\n expect(stripeUnitsToMoneyAmount(500, JPY)).toBe(\"500\");\n expect(stripeUnitsToMoneyAmount(0, JPY)).toBe(\"0\");\n });\n\n test(\"round-trips with moneyAmountToStripeUnits\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n expect(moneyAmountToStripeUnits(stripeUnitsToMoneyAmount(cents, USD), USD)).toBe(cents);\n }\n });\n\n test(\"scaling in minor units avoids float artifacts\", ({ expect }) => {\n // 19.99 * 3 in float is 59.97000000000001; via minor units it is exact.\n const scaled = moneyAmountToStripeUnits(\"19.99\" as MoneyAmount, USD) * 3;\n expect(stripeUnitsToMoneyAmount(scaled, USD)).toBe(\"59.97\");\n });\n\n test(\"rejects non-integer and negative inputs\", ({ expect }) => {\n expect(() => stripeUnitsToMoneyAmount(1.5, USD)).toThrow();\n expect(() => stripeUnitsToMoneyAmount(-1, USD)).toThrow();\n expect(() => stripeUnitsToMoneyAmount(Number.NaN, USD)).toThrow();\n });\n});\n"],"mappings":";;;;;AAMA,SAAgB,yBAAyB,QAAqB,UAA4B;CACxF,MAAM,aAAA,GAAA,oBAAA,kBAAA,CAA8B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,MAAM;CAC3E,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAIA,YAAAA,uBAAuB,8DAA8D;CAMjG,MAAM,CAAC,OAAO,aAAa,MAAM,UAAU,MAAM,GAAG;CACpD,MAAM,mBAAmB,WAAW,OAAO,SAAS,UAAU,GAAG;CACjE,OAAO,OAAO,SAAS,QAAQ,kBAAkB,EAAE;AACrD;;;;;;;;;;;;;;;AAgBA,SAAgB,yBAAyB,aAAqB,UAAiC;CAC7F,IAAI,CAAC,OAAO,SAAS,WAAW,KAAK,KAAK,MAAM,WAAW,MAAM,aAC/D,MAAM,IAAIA,YAAAA,uBAAuB,mCAAmC,EAAE,YAAY,CAAC;CAErF,IAAI,cAAc,GAChB,MAAM,IAAIA,YAAAA,uBAAuB,0EAA0E,EAAE,YAAY,CAAC;CAE5H,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAIA,YAAAA,uBAAuB,8DAA8D;CAEjG,MAAM,WAAW,SAAS;CAC1B,IAAI,aAAa,GAAG,OAAO,GAAG;CAG9B,MAAM,SAAS,YAAY,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,GAAG;CAGhE,OAAO,GAFa,OAAO,MAAM,GAAG,OAAO,SAAS,QAEhC,EAAE,GADC,OAAO,MAAM,OAAO,SAAS,QACd;AACxC"}
@@ -1,2 +1,2 @@
1
- import { a as fromNow, c as getIntervalsElapsed, i as addInterval, l as isWeekend, n as FAR_FUTURE_DATE, o as fromNowDetailed, r as Interval, s as getInputDatetimeLocalString, t as DayInterval, u as subtractInterval } from "../dates-B6ne9iOR.js";
2
- export { DayInterval, FAR_FUTURE_DATE, Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, getIntervalsElapsed, isWeekend, subtractInterval };
1
+ import { a as fromNow, c as getIntervalsElapsed, d as subtractInterval, i as addInterval, l as isWeekend, n as FAR_FUTURE_DATE, o as fromNowDetailed, r as Interval, s as getInputDatetimeLocalString, t as DayInterval, u as nthDayIntervalMillis } from "../dates-BRAvSk6L.js";
2
+ export { DayInterval, FAR_FUTURE_DATE, Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, getIntervalsElapsed, isWeekend, nthDayIntervalMillis, subtractInterval };
@@ -100,24 +100,45 @@ function getMsPerDayIntervalUnit(unit) {
100
100
  }
101
101
  function getIntervalsElapsed(anchor, to, repeat) {
102
102
  const [amount, unit] = repeat;
103
- if (to <= anchor) return 0;
103
+ const toMillis = to.getTime();
104
+ if (toMillis <= anchor.getTime()) return 0;
104
105
  if (unit === "day" || unit === "week") {
105
106
  const msPerUnit = getMsPerDayIntervalUnit(unit);
106
- const diffMs = to.getTime() - anchor.getTime();
107
+ const diffMs = toMillis - anchor.getTime();
107
108
  return Math.floor(diffMs / (msPerUnit * amount));
108
109
  }
109
- if (["month", "year"].includes(unit)) {
110
- let count = 0;
111
- let current = new Date(anchor);
112
- for (;;) {
113
- const next = addInterval(new Date(current), [amount, unit]);
114
- if (next > to) break;
115
- current = next;
116
- count += 1;
117
- }
118
- return count;
119
- }
120
- return 0;
110
+ let count = 0;
111
+ while (nthDayIntervalMillis(anchor.getTime(), repeat, count + 1) <= toMillis) count += 1;
112
+ return count;
113
+ }
114
+ /**
115
+ * The UTC millis of the `occurrence`-th (1-based) repeat of `interval` after `anchorMillis`.
116
+ *
117
+ * Each boundary is computed from the *original* anchor (never by stepping off the previous, possibly
118
+ * clamped, boundary) so the anchor's day-of-month is preserved across resets: a Jan 31 anchor yields
119
+ * Feb 28, Mar 31, Apr 30, ... (matching Stripe's billing-cycle behavior) rather than drifting to
120
+ * Feb 28, Mar 28, ... . Month/year overflow (e.g. Jan 31 -> Feb) is clamped to the target month's
121
+ * last day. Day/week are exact multiples (no calendar involved, so no drift possible).
122
+ *
123
+ * Everything is done in UTC (unlike `addInterval`, which uses local-time Date accessors) so the
124
+ * result is deterministic regardless of the server's timezone — this is relied upon by bulldozer
125
+ * folds, which must be reproducible across machines.
126
+ *
127
+ * `occurrence` 0 returns the anchor itself; `getIntervalsElapsed` counts these same boundaries, so
128
+ * the two are always consistent for a given DayInterval.
129
+ */
130
+ function nthDayIntervalMillis(anchorMillis, interval, occurrence) {
131
+ const [count, unit] = interval;
132
+ const totalUnits = count * occurrence;
133
+ if (unit === "day" || unit === "week") return anchorMillis + totalUnits * getMsPerDayIntervalUnit(unit);
134
+ const anchor = new Date(anchorMillis);
135
+ const monthsToAdd = unit === "year" ? totalUnits * 12 : totalUnits;
136
+ const absoluteMonth = anchor.getUTCFullYear() * 12 + anchor.getUTCMonth() + monthsToAdd;
137
+ const targetYear = Math.floor(absoluteMonth / 12);
138
+ const targetMonth = absoluteMonth - targetYear * 12;
139
+ const daysInTargetMonth = new Date(Date.UTC(targetYear, targetMonth + 1, 0)).getUTCDate();
140
+ const clampedDay = Math.min(anchor.getUTCDate(), daysInTargetMonth);
141
+ return Date.UTC(targetYear, targetMonth, clampedDay, anchor.getUTCHours(), anchor.getUTCMinutes(), anchor.getUTCSeconds(), anchor.getUTCMilliseconds());
121
142
  }
122
143
  //#endregion
123
144
  exports.FAR_FUTURE_DATE = FAR_FUTURE_DATE;
@@ -127,6 +148,7 @@ exports.fromNowDetailed = fromNowDetailed;
127
148
  exports.getInputDatetimeLocalString = getInputDatetimeLocalString;
128
149
  exports.getIntervalsElapsed = getIntervalsElapsed;
129
150
  exports.isWeekend = isWeekend;
151
+ exports.nthDayIntervalMillis = nthDayIntervalMillis;
130
152
  exports.subtractInterval = subtractInterval;
131
153
 
132
154
  //# sourceMappingURL=dates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dates.js","names":["intervalSchema","HexclaveAssertionError"],"sources":["../../src/utils/dates.tsx"],"sourcesContent":["import { intervalSchema } from \"../schema-fields\";\nimport { HexclaveAssertionError } from \"./errors\";\nimport { remainder } from \"./math\";\n\nexport function isWeekend(date: Date): boolean {\n return date.getDay() === 0 || date.getDay() === 6;\n}\n\nimport.meta.vitest?.test(\"isWeekend\", ({ expect }) => {\n // Sunday (day 0)\n expect(isWeekend(new Date(2023, 0, 1))).toBe(true);\n // Saturday (day 6)\n expect(isWeekend(new Date(2023, 0, 7))).toBe(true);\n // Monday (day 1)\n expect(isWeekend(new Date(2023, 0, 2))).toBe(false);\n // Friday (day 5)\n expect(isWeekend(new Date(2023, 0, 6))).toBe(false);\n});\n\nconst agoUnits = [\n [60, 'second'],\n [60, 'minute'],\n [24, 'hour'],\n [7, 'day'],\n [5, 'week'],\n] as const;\n\nexport function fromNow(date: Date): string {\n return fromNowDetailed(date).result;\n}\n\nimport.meta.vitest?.test(\"fromNow\", ({ expect }) => {\n // Set a fixed date for testing\n const fixedDate = new Date(\"2023-01-15T12:00:00.000Z\");\n\n // Use Vitest's fake timers\n import.meta.vitest?.vi.useFakeTimers();\n import.meta.vitest?.vi.setSystemTime(fixedDate);\n\n // Test past times\n expect(fromNow(new Date(\"2023-01-15T11:59:50.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T11:59:00.000Z\"))).toBe(\"1 minute ago\");\n expect(fromNow(new Date(\"2023-01-15T11:00:00.000Z\"))).toBe(\"1 hour ago\");\n expect(fromNow(new Date(\"2023-01-14T12:00:00.000Z\"))).toBe(\"1 day ago\");\n expect(fromNow(new Date(\"2023-01-08T12:00:00.000Z\"))).toBe(\"1 week ago\");\n\n // Test future times\n expect(fromNow(new Date(\"2023-01-15T12:00:10.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T12:01:00.000Z\"))).toBe(\"in 1 minute\");\n expect(fromNow(new Date(\"2023-01-15T13:00:00.000Z\"))).toBe(\"in 1 hour\");\n expect(fromNow(new Date(\"2023-01-16T12:00:00.000Z\"))).toBe(\"in 1 day\");\n expect(fromNow(new Date(\"2023-01-22T12:00:00.000Z\"))).toBe(\"in 1 week\");\n\n // Test very old dates (should use date format)\n expect(fromNow(new Date(\"2022-01-15T12:00:00.000Z\"))).toMatch(/Jan 15, 2022/);\n\n // Restore real timers\n import.meta.vitest?.vi.useRealTimers();\n});\n\nexport function fromNowDetailed(date: Date): {\n result: string,\n /**\n * May be Infinity if the result will never change.\n */\n secondsUntilChange: number,\n} {\n if (!(date instanceof Date)) {\n throw new Error(`fromNow only accepts Date objects (received: ${date})`);\n }\n\n const now = new Date();\n const elapsed = now.getTime() - date.getTime();\n\n let remainingInUnit = Math.abs(elapsed) / 1000;\n if (remainingInUnit < 15) {\n return {\n result: 'just now',\n secondsUntilChange: 15 - remainingInUnit,\n };\n }\n let unitInSeconds = 1;\n for (const [nextUnitSize, unitName] of agoUnits) {\n const rounded = Math.round(remainingInUnit);\n if (rounded < nextUnitSize) {\n if (elapsed < 0) {\n return {\n result: `in ${rounded} ${unitName}${rounded === 1 ? '' : 's'}`,\n secondsUntilChange: remainder((remainingInUnit - rounded + 0.5) * unitInSeconds, unitInSeconds),\n };\n } else {\n return {\n result: `${rounded} ${unitName}${rounded === 1 ? '' : 's'} ago`,\n secondsUntilChange: remainder((rounded - remainingInUnit - 0.5) * unitInSeconds, unitInSeconds),\n };\n }\n }\n unitInSeconds *= nextUnitSize;\n remainingInUnit /= nextUnitSize;\n }\n\n return {\n result: date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }),\n secondsUntilChange: Infinity,\n };\n}\n\n/**\n * Returns a string representation of the given date in the format expected by the `datetime-local` input type.\n */\nexport function getInputDatetimeLocalString(date: Date): string {\n date = new Date(date);\n date.setMinutes(date.getMinutes() - date.getTimezoneOffset());\n return date.toISOString().slice(0, 19);\n}\n\nimport.meta.vitest?.test(\"getInputDatetimeLocalString\", ({ expect }) => {\n // Use Vitest's fake timers to ensure consistent timezone behavior\n import.meta.vitest?.vi.useFakeTimers();\n\n // Test with a specific date\n const mockDate = new Date(\"2023-01-15T12:30:45.000Z\");\n const result = getInputDatetimeLocalString(mockDate);\n\n // The result should be in the format YYYY-MM-DDTHH:MM:SS\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n\n // Test with different dates\n const dates = [\n new Date(\"2023-01-01T00:00:00.000Z\"),\n new Date(\"2023-06-15T23:59:59.000Z\"),\n new Date(\"2023-12-31T12:34:56.000Z\"),\n ];\n\n for (const date of dates) {\n const result = getInputDatetimeLocalString(date);\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n }\n\n // Restore real timers\n import.meta.vitest?.vi.useRealTimers();\n});\n\n\nexport type Interval = [number, 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'];\nexport type DayInterval = [number, 'day' | 'week' | 'month' | 'year'];\n\nfunction applyInterval(date: Date, times: number, interval: Interval): Date {\n if (!intervalSchema.isValidSync(interval)) {\n throw new HexclaveAssertionError(`Invalid interval`, { interval });\n }\n const [amount, unit] = interval;\n switch (unit) {\n case 'millisecond': {\n date.setMilliseconds(date.getMilliseconds() + amount * times);\n break;\n }\n case 'second': {\n date.setSeconds(date.getSeconds() + amount * times);\n break;\n }\n case 'minute': {\n date.setMinutes(date.getMinutes() + amount * times);\n break;\n }\n case 'hour': {\n date.setHours(date.getHours() + amount * times);\n break;\n }\n case 'day': {\n date.setDate(date.getDate() + amount * times);\n break;\n }\n case 'week': {\n date.setDate(date.getDate() + amount * times * 7);\n break;\n }\n case 'month': {\n date.setMonth(date.getMonth() + amount * times);\n break;\n }\n case 'year': {\n date.setFullYear(date.getFullYear() + amount * times);\n break;\n }\n default: {\n throw new HexclaveAssertionError(`Invalid interval despite schema validation`, { interval });\n }\n }\n return date;\n}\n\nexport function subtractInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, -1, interval);\n}\n\nexport function addInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, 1, interval);\n}\n\nexport const FAR_FUTURE_DATE = new Date(8640000000000000); // 13 Sep 275760 00:00:00 UTC\n\nfunction getMsPerDayIntervalUnit(unit: 'day' | 'week'): number {\n if (unit === 'day') {\n return 24 * 60 * 60 * 1000;\n }\n return 7 * 24 * 60 * 60 * 1000;\n}\n\n\nexport function getIntervalsElapsed(anchor: Date, to: Date, repeat: DayInterval): number {\n const [amount, unit] = repeat;\n if (to <= anchor) return 0;\n if (unit === 'day' || unit === 'week') {\n const msPerUnit = getMsPerDayIntervalUnit(unit);\n const diffMs = to.getTime() - anchor.getTime();\n return Math.floor(diffMs / (msPerUnit * amount));\n }\n if ([\"month\", \"year\"].includes(unit)) {\n let count = 0;\n let current = new Date(anchor);\n for (; ;) {\n const next = addInterval(new Date(current), [amount, unit]);\n if (next > to) break;\n current = next;\n count += 1;\n }\n return count;\n }\n return 0;\n}\n\nimport.meta.vitest?.test(\"getIntervalsElapsed\", ({ expect }) => {\n const anchor = new Date('2025-01-01T00:00:00.000Z');\n const to = new Date('2025-01-15T00:00:00.000Z');\n expect(getIntervalsElapsed(anchor, to, [1, 'week'])).toBe(2);\n expect(getIntervalsElapsed(anchor, to, [3, 'day'])).toBe(4);\n\n const mAnchor = new Date('2023-01-31T00:00:00.000Z');\n const mTo = new Date('2023-03-01T00:00:00.000Z');\n expect(getIntervalsElapsed(mAnchor, mTo, [1, 'month'])).toBe(0);\n\n const yAnchor = new Date('2020-01-01T00:00:00.000Z');\n const yTo = new Date('2022-06-01T00:00:00.000Z');\n expect(getIntervalsElapsed(yAnchor, yTo, [1, 'year'])).toBe(2);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"dates.js","names":["intervalSchema","HexclaveAssertionError"],"sources":["../../src/utils/dates.tsx"],"sourcesContent":["import { intervalSchema } from \"../schema-fields\";\nimport { HexclaveAssertionError } from \"./errors\";\nimport { remainder } from \"./math\";\n\nexport function isWeekend(date: Date): boolean {\n return date.getDay() === 0 || date.getDay() === 6;\n}\n\nimport.meta.vitest?.test(\"isWeekend\", ({ expect }) => {\n // Sunday (day 0)\n expect(isWeekend(new Date(2023, 0, 1))).toBe(true);\n // Saturday (day 6)\n expect(isWeekend(new Date(2023, 0, 7))).toBe(true);\n // Monday (day 1)\n expect(isWeekend(new Date(2023, 0, 2))).toBe(false);\n // Friday (day 5)\n expect(isWeekend(new Date(2023, 0, 6))).toBe(false);\n});\n\nconst agoUnits = [\n [60, 'second'],\n [60, 'minute'],\n [24, 'hour'],\n [7, 'day'],\n [5, 'week'],\n] as const;\n\nexport function fromNow(date: Date): string {\n return fromNowDetailed(date).result;\n}\n\nimport.meta.vitest?.test(\"fromNow\", ({ expect }) => {\n // Set a fixed date for testing\n const fixedDate = new Date(\"2023-01-15T12:00:00.000Z\");\n\n // Use Vitest's fake timers\n import.meta.vitest?.vi.useFakeTimers();\n import.meta.vitest?.vi.setSystemTime(fixedDate);\n\n // Test past times\n expect(fromNow(new Date(\"2023-01-15T11:59:50.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T11:59:00.000Z\"))).toBe(\"1 minute ago\");\n expect(fromNow(new Date(\"2023-01-15T11:00:00.000Z\"))).toBe(\"1 hour ago\");\n expect(fromNow(new Date(\"2023-01-14T12:00:00.000Z\"))).toBe(\"1 day ago\");\n expect(fromNow(new Date(\"2023-01-08T12:00:00.000Z\"))).toBe(\"1 week ago\");\n\n // Test future times\n expect(fromNow(new Date(\"2023-01-15T12:00:10.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T12:01:00.000Z\"))).toBe(\"in 1 minute\");\n expect(fromNow(new Date(\"2023-01-15T13:00:00.000Z\"))).toBe(\"in 1 hour\");\n expect(fromNow(new Date(\"2023-01-16T12:00:00.000Z\"))).toBe(\"in 1 day\");\n expect(fromNow(new Date(\"2023-01-22T12:00:00.000Z\"))).toBe(\"in 1 week\");\n\n // Test very old dates (should use date format)\n expect(fromNow(new Date(\"2022-01-15T12:00:00.000Z\"))).toMatch(/Jan 15, 2022/);\n\n // Restore real timers\n import.meta.vitest?.vi.useRealTimers();\n});\n\nexport function fromNowDetailed(date: Date): {\n result: string,\n /**\n * May be Infinity if the result will never change.\n */\n secondsUntilChange: number,\n} {\n if (!(date instanceof Date)) {\n throw new Error(`fromNow only accepts Date objects (received: ${date})`);\n }\n\n const now = new Date();\n const elapsed = now.getTime() - date.getTime();\n\n let remainingInUnit = Math.abs(elapsed) / 1000;\n if (remainingInUnit < 15) {\n return {\n result: 'just now',\n secondsUntilChange: 15 - remainingInUnit,\n };\n }\n let unitInSeconds = 1;\n for (const [nextUnitSize, unitName] of agoUnits) {\n const rounded = Math.round(remainingInUnit);\n if (rounded < nextUnitSize) {\n if (elapsed < 0) {\n return {\n result: `in ${rounded} ${unitName}${rounded === 1 ? '' : 's'}`,\n secondsUntilChange: remainder((remainingInUnit - rounded + 0.5) * unitInSeconds, unitInSeconds),\n };\n } else {\n return {\n result: `${rounded} ${unitName}${rounded === 1 ? '' : 's'} ago`,\n secondsUntilChange: remainder((rounded - remainingInUnit - 0.5) * unitInSeconds, unitInSeconds),\n };\n }\n }\n unitInSeconds *= nextUnitSize;\n remainingInUnit /= nextUnitSize;\n }\n\n return {\n result: date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }),\n secondsUntilChange: Infinity,\n };\n}\n\n/**\n * Returns a string representation of the given date in the format expected by the `datetime-local` input type.\n */\nexport function getInputDatetimeLocalString(date: Date): string {\n date = new Date(date);\n date.setMinutes(date.getMinutes() - date.getTimezoneOffset());\n return date.toISOString().slice(0, 19);\n}\n\nimport.meta.vitest?.test(\"getInputDatetimeLocalString\", ({ expect }) => {\n // Use Vitest's fake timers to ensure consistent timezone behavior\n import.meta.vitest?.vi.useFakeTimers();\n\n // Test with a specific date\n const mockDate = new Date(\"2023-01-15T12:30:45.000Z\");\n const result = getInputDatetimeLocalString(mockDate);\n\n // The result should be in the format YYYY-MM-DDTHH:MM:SS\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n\n // Test with different dates\n const dates = [\n new Date(\"2023-01-01T00:00:00.000Z\"),\n new Date(\"2023-06-15T23:59:59.000Z\"),\n new Date(\"2023-12-31T12:34:56.000Z\"),\n ];\n\n for (const date of dates) {\n const result = getInputDatetimeLocalString(date);\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n }\n\n // Restore real timers\n import.meta.vitest?.vi.useRealTimers();\n});\n\n\nexport type Interval = [number, 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'];\nexport type DayInterval = [number, 'day' | 'week' | 'month' | 'year'];\n\nfunction applyInterval(date: Date, times: number, interval: Interval): Date {\n if (!intervalSchema.isValidSync(interval)) {\n throw new HexclaveAssertionError(`Invalid interval`, { interval });\n }\n const [amount, unit] = interval;\n switch (unit) {\n case 'millisecond': {\n date.setMilliseconds(date.getMilliseconds() + amount * times);\n break;\n }\n case 'second': {\n date.setSeconds(date.getSeconds() + amount * times);\n break;\n }\n case 'minute': {\n date.setMinutes(date.getMinutes() + amount * times);\n break;\n }\n case 'hour': {\n date.setHours(date.getHours() + amount * times);\n break;\n }\n case 'day': {\n date.setDate(date.getDate() + amount * times);\n break;\n }\n case 'week': {\n date.setDate(date.getDate() + amount * times * 7);\n break;\n }\n case 'month': {\n date.setMonth(date.getMonth() + amount * times);\n break;\n }\n case 'year': {\n date.setFullYear(date.getFullYear() + amount * times);\n break;\n }\n default: {\n throw new HexclaveAssertionError(`Invalid interval despite schema validation`, { interval });\n }\n }\n return date;\n}\n\nexport function subtractInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, -1, interval);\n}\n\n// One-shot local-time interval arithmetic that OVERFLOWS (Jan 31 + 1 month -> Mar 3, via\n// Date#setMonth) rather than clamping. Use this for single-step period math where JS/Stripe overflow\n// semantics are what we want (e.g. computing a subscription's currentPeriodEnd). For recurring\n// grant/reset BOUNDARIES, use `nthDayIntervalMillis` / `getIntervalsElapsed` instead — they clamp to\n// month-end and compute in UTC from a fixed anchor, and mixing the two would drift.\nexport function addInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, 1, interval);\n}\n\nexport const FAR_FUTURE_DATE = new Date(8640000000000000); // 13 Sep 275760 00:00:00 UTC\n\nfunction getMsPerDayIntervalUnit(unit: 'day' | 'week'): number {\n if (unit === 'day') {\n return 24 * 60 * 60 * 1000;\n }\n return 7 * 24 * 60 * 60 * 1000;\n}\n\n\n// The number of full `repeat` intervals elapsed from `anchor` up to (and including) `to`, i.e. the\n// largest n >= 0 with the n-th boundary <= to. Boundaries are the SAME ones `nthDayIntervalMillis`\n// computes (anchor-relative, UTC, month-end clamped), so counting and boundary-computation never\n// disagree — a Jan 31 monthly anchor has elapsed one interval by Feb 28, matching the reset the\n// bulldozer item-repeat fold actually emits. (This is why it must NOT be built on `addInterval`,\n// which is local-time and overflows instead of clamping.)\nexport function getIntervalsElapsed(anchor: Date, to: Date, repeat: DayInterval): number {\n const [amount, unit] = repeat;\n const toMillis = to.getTime();\n if (toMillis <= anchor.getTime()) return 0;\n if (unit === 'day' || unit === 'week') {\n const msPerUnit = getMsPerDayIntervalUnit(unit);\n const diffMs = toMillis - anchor.getTime();\n return Math.floor(diffMs / (msPerUnit * amount));\n }\n // month/year: walk anchor-relative boundaries. The count is small in practice (bounded by the\n // number of billing periods since the anchor), so a linear walk is fine.\n let count = 0;\n while (nthDayIntervalMillis(anchor.getTime(), repeat, count + 1) <= toMillis) count += 1;\n return count;\n}\n\nimport.meta.vitest?.test(\"getIntervalsElapsed\", ({ expect }) => {\n const anchor = new Date('2025-01-01T00:00:00.000Z');\n const to = new Date('2025-01-15T00:00:00.000Z');\n expect(getIntervalsElapsed(anchor, to, [1, 'week'])).toBe(2);\n expect(getIntervalsElapsed(anchor, to, [3, 'day'])).toBe(4);\n\n // Jan 31 monthly anchor: the first boundary is clamped to Feb 28, which is <= Mar 1, so one\n // interval has elapsed (anchor-relative clamped math, consistent with nthDayIntervalMillis).\n const mAnchor = new Date('2023-01-31T00:00:00.000Z');\n const mTo = new Date('2023-03-01T00:00:00.000Z');\n expect(getIntervalsElapsed(mAnchor, mTo, [1, 'month'])).toBe(1);\n\n const yAnchor = new Date('2020-01-01T00:00:00.000Z');\n const yTo = new Date('2022-06-01T00:00:00.000Z');\n expect(getIntervalsElapsed(yAnchor, yTo, [1, 'year'])).toBe(2);\n});\n\n/**\n * The UTC millis of the `occurrence`-th (1-based) repeat of `interval` after `anchorMillis`.\n *\n * Each boundary is computed from the *original* anchor (never by stepping off the previous, possibly\n * clamped, boundary) so the anchor's day-of-month is preserved across resets: a Jan 31 anchor yields\n * Feb 28, Mar 31, Apr 30, ... (matching Stripe's billing-cycle behavior) rather than drifting to\n * Feb 28, Mar 28, ... . Month/year overflow (e.g. Jan 31 -> Feb) is clamped to the target month's\n * last day. Day/week are exact multiples (no calendar involved, so no drift possible).\n *\n * Everything is done in UTC (unlike `addInterval`, which uses local-time Date accessors) so the\n * result is deterministic regardless of the server's timezone — this is relied upon by bulldozer\n * folds, which must be reproducible across machines.\n *\n * `occurrence` 0 returns the anchor itself; `getIntervalsElapsed` counts these same boundaries, so\n * the two are always consistent for a given DayInterval.\n */\nexport function nthDayIntervalMillis(anchorMillis: number, interval: DayInterval, occurrence: number): number {\n const [count, unit] = interval;\n const totalUnits = count * occurrence;\n if (unit === 'day' || unit === 'week') {\n return anchorMillis + totalUnits * getMsPerDayIntervalUnit(unit);\n }\n const anchor = new Date(anchorMillis);\n const monthsToAdd = unit === 'year' ? totalUnits * 12 : totalUnits;\n const absoluteMonth = anchor.getUTCFullYear() * 12 + anchor.getUTCMonth() + monthsToAdd;\n const targetYear = Math.floor(absoluteMonth / 12);\n const targetMonth = absoluteMonth - targetYear * 12;\n // Day 0 of the following month is the last day of the target month, so this gives its length.\n const daysInTargetMonth = new Date(Date.UTC(targetYear, targetMonth + 1, 0)).getUTCDate();\n const clampedDay = Math.min(anchor.getUTCDate(), daysInTargetMonth);\n return Date.UTC(\n targetYear,\n targetMonth,\n clampedDay,\n anchor.getUTCHours(),\n anchor.getUTCMinutes(),\n anchor.getUTCSeconds(),\n anchor.getUTCMilliseconds(),\n );\n}\n\nimport.meta.vitest?.test(\"nthDayIntervalMillis\", ({ expect }) => {\n const at = (iso: string) => new Date(iso).getTime();\n const iso = (millis: number) => new Date(millis).toISOString();\n\n // day / week are exact multiples (no drift), and honor the count.\n const dayAnchor = at('2025-01-01T08:30:00.000Z');\n expect(iso(nthDayIntervalMillis(dayAnchor, [1, 'day'], 1))).toBe('2025-01-02T08:30:00.000Z');\n expect(iso(nthDayIntervalMillis(dayAnchor, [3, 'day'], 4))).toBe('2025-01-13T08:30:00.000Z');\n expect(iso(nthDayIntervalMillis(dayAnchor, [2, 'week'], 3))).toBe('2025-02-12T08:30:00.000Z'); // 6 weeks = 42 days after Jan 1\n\n // Jan 31 monthly: clamp in short months, restore to the anchor day in long ones.\n const jan31 = at('2025-01-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(jan31, [1, 'month'], 1))).toBe('2025-02-28T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(jan31, [1, 'month'], 2))).toBe('2025-03-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(jan31, [1, 'month'], 3))).toBe('2025-04-30T00:00:00.000Z');\n\n // Anchor-day preservation: a Feb 28 anchor stays on day 28 (never jumps to Mar 31), unlike the\n // Jan 31 anchor above which restores to Mar 31. This is the evidence we compute from the anchor.\n const feb28 = at('2025-02-28T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(feb28, [1, 'month'], 1))).toBe('2025-03-28T00:00:00.000Z');\n\n // Leap-year Feb: Feb 29 anchor clamps to Feb 28 in a non-leap year and restores in the next leap year.\n const feb29 = at('2024-02-29T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(feb29, [1, 'year'], 1))).toBe('2025-02-28T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(feb29, [1, 'year'], 4))).toBe('2028-02-29T00:00:00.000Z');\n // Jan 31 monthly landing in a leap February clamps to Feb 29, not Feb 28.\n const jan31Leap = at('2024-01-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(jan31Leap, [1, 'month'], 1))).toBe('2024-02-29T00:00:00.000Z');\n\n // End-of-December rollover: absolute-month math carries the year.\n const dec31 = at('2025-12-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(dec31, [1, 'month'], 1))).toBe('2026-01-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(dec31, [1, 'month'], 2))).toBe('2026-02-28T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(dec31, [1, 'month'], 3))).toBe('2026-03-31T00:00:00.000Z');\n expect(iso(nthDayIntervalMillis(dec31, [1, 'year'], 1))).toBe('2026-12-31T00:00:00.000Z');\n\n // Time-of-day is preserved through month clamping.\n const withTime = at('2025-01-31T13:45:59.123Z');\n expect(iso(nthDayIntervalMillis(withTime, [1, 'month'], 1))).toBe('2025-02-28T13:45:59.123Z');\n});\n"],"mappings":";;;;;AAIA,SAAgB,UAAU,MAAqB;CAC7C,OAAO,KAAK,OAAO,MAAM,KAAK,KAAK,OAAO,MAAM;AAClD;AAaA,MAAM,WAAW;CACf,CAAC,IAAI,QAAQ;CACb,CAAC,IAAI,QAAQ;CACb,CAAC,IAAI,MAAM;CACX,CAAC,GAAG,KAAK;CACT,CAAC,GAAG,MAAM;AACZ;AAEA,SAAgB,QAAQ,MAAoB;CAC1C,OAAO,gBAAgB,IAAI,CAAC,CAAC;AAC/B;AA+BA,SAAgB,gBAAgB,MAM9B;CACA,IAAI,EAAE,gBAAgB,OACpB,MAAM,IAAI,MAAM,gDAAgD,KAAK,EAAE;CAIzE,MAAM,2BAAU,IADA,KACE,EAAA,CAAE,QAAQ,IAAI,KAAK,QAAQ;CAE7C,IAAI,kBAAkB,KAAK,IAAI,OAAO,IAAI;CAC1C,IAAI,kBAAkB,IACpB,OAAO;EACL,QAAQ;EACR,oBAAoB,KAAK;CAC3B;CAEF,IAAI,gBAAgB;CACpB,KAAK,MAAM,CAAC,cAAc,aAAa,UAAU;EAC/C,MAAM,UAAU,KAAK,MAAM,eAAe;EAC1C,IAAI,UAAU,cACZ,IAAI,UAAU,GACZ,OAAO;GACL,QAAQ,MAAM,QAAQ,GAAG,WAAW,YAAY,IAAI,KAAK;GACzD,qBAAA,GAAA,UAAA,UAAA,EAA+B,kBAAkB,UAAU,MAAO,eAAe,aAAa;EAChG;OAEA,OAAO;GACL,QAAQ,GAAG,QAAQ,GAAG,WAAW,YAAY,IAAI,KAAK,IAAI;GAC1D,qBAAA,GAAA,UAAA,UAAA,EAA+B,UAAU,kBAAkB,MAAO,eAAe,aAAa;EAChG;EAGJ,iBAAiB;EACjB,mBAAmB;CACrB;CAEA,OAAO;EACL,QAAQ,KAAK,mBAAmB,SAAS;GAAE,MAAM;GAAW,OAAO;GAAS,KAAK;EAAU,CAAC;EAC5F,oBAAoB;CACtB;AACF;;;;AAKA,SAAgB,4BAA4B,MAAoB;CAC9D,OAAO,IAAI,KAAK,IAAI;CACpB,KAAK,WAAW,KAAK,WAAW,IAAI,KAAK,kBAAkB,CAAC;CAC5D,OAAO,KAAK,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;AACvC;AAiCA,SAAS,cAAc,MAAY,OAAe,UAA0B;CAC1E,IAAI,CAACA,oBAAAA,eAAe,YAAY,QAAQ,GACtC,MAAM,IAAIC,YAAAA,uBAAuB,oBAAoB,EAAE,SAAS,CAAC;CAEnE,MAAM,CAAC,QAAQ,QAAQ;CACvB,QAAQ,MAAR;EACE,KAAK;GACH,KAAK,gBAAgB,KAAK,gBAAgB,IAAI,SAAS,KAAK;GAC5D;EAEF,KAAK;GACH,KAAK,WAAW,KAAK,WAAW,IAAI,SAAS,KAAK;GAClD;EAEF,KAAK;GACH,KAAK,WAAW,KAAK,WAAW,IAAI,SAAS,KAAK;GAClD;EAEF,KAAK;GACH,KAAK,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK;GAC9C;EAEF,KAAK;GACH,KAAK,QAAQ,KAAK,QAAQ,IAAI,SAAS,KAAK;GAC5C;EAEF,KAAK;GACH,KAAK,QAAQ,KAAK,QAAQ,IAAI,SAAS,QAAQ,CAAC;GAChD;EAEF,KAAK;GACH,KAAK,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK;GAC9C;EAEF,KAAK;GACH,KAAK,YAAY,KAAK,YAAY,IAAI,SAAS,KAAK;GACpD;EAEF,SACE,MAAM,IAAIA,YAAAA,uBAAuB,8CAA8C,EAAE,SAAS,CAAC;CAE/F;CACA,OAAO;AACT;AAEA,SAAgB,iBAAiB,MAAY,UAA0B;CACrE,OAAO,cAAc,MAAM,IAAI,QAAQ;AACzC;AAOA,SAAgB,YAAY,MAAY,UAA0B;CAChE,OAAO,cAAc,MAAM,GAAG,QAAQ;AACxC;AAEA,MAAa,kCAAkB,IAAI,KAAK,MAAgB;AAExD,SAAS,wBAAwB,MAA8B;CAC7D,IAAI,SAAS,OACX,OAAO,OAAU,KAAK;CAExB,OAAO,QAAc,KAAK;AAC5B;AASA,SAAgB,oBAAoB,QAAc,IAAU,QAA6B;CACvF,MAAM,CAAC,QAAQ,QAAQ;CACvB,MAAM,WAAW,GAAG,QAAQ;CAC5B,IAAI,YAAY,OAAO,QAAQ,GAAG,OAAO;CACzC,IAAI,SAAS,SAAS,SAAS,QAAQ;EACrC,MAAM,YAAY,wBAAwB,IAAI;EAC9C,MAAM,SAAS,WAAW,OAAO,QAAQ;EACzC,OAAO,KAAK,MAAM,UAAU,YAAY,OAAO;CACjD;CAGA,IAAI,QAAQ;CACZ,OAAO,qBAAqB,OAAO,QAAQ,GAAG,QAAQ,QAAQ,CAAC,KAAK,UAAU,SAAS;CACvF,OAAO;AACT;;;;;;;;;;;;;;;;;AAmCA,SAAgB,qBAAqB,cAAsB,UAAuB,YAA4B;CAC5G,MAAM,CAAC,OAAO,QAAQ;CACtB,MAAM,aAAa,QAAQ;CAC3B,IAAI,SAAS,SAAS,SAAS,QAC7B,OAAO,eAAe,aAAa,wBAAwB,IAAI;CAEjE,MAAM,SAAS,IAAI,KAAK,YAAY;CACpC,MAAM,cAAc,SAAS,SAAS,aAAa,KAAK;CACxD,MAAM,gBAAgB,OAAO,eAAe,IAAI,KAAK,OAAO,YAAY,IAAI;CAC5E,MAAM,aAAa,KAAK,MAAM,gBAAgB,EAAE;CAChD,MAAM,cAAc,gBAAgB,aAAa;CAEjD,MAAM,oBAAoB,IAAI,KAAK,KAAK,IAAI,YAAY,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW;CACxF,MAAM,aAAa,KAAK,IAAI,OAAO,WAAW,GAAG,iBAAiB;CAClE,OAAO,KAAK,IACV,YACA,aACA,YACA,OAAO,YAAY,GACnB,OAAO,cAAc,GACrB,OAAO,cAAc,GACrB,OAAO,mBAAmB,CAC5B;AACF"}
@@ -20,8 +20,8 @@ declare const webhookEvents: readonly [WebhookEvent<yup$1.ObjectSchema<{
20
20
  client_metadata?: {} | null | undefined;
21
21
  client_read_only_metadata?: {} | null | undefined;
22
22
  server_metadata?: {} | null | undefined;
23
- id: string;
24
23
  display_name: string;
24
+ id: string;
25
25
  profile_image_url: string | null;
26
26
  created_at_millis: number;
27
27
  } | null;
@@ -110,8 +110,8 @@ declare const webhookEvents: readonly [WebhookEvent<yup$1.ObjectSchema<{
110
110
  client_metadata?: {} | null | undefined;
111
111
  client_read_only_metadata?: {} | null | undefined;
112
112
  server_metadata?: {} | null | undefined;
113
- id: string;
114
113
  display_name: string;
114
+ id: string;
115
115
  profile_image_url: string | null;
116
116
  created_at_millis: number;
117
117
  } | null;
@@ -323,4 +323,4 @@ declare const webhookEvents: readonly [WebhookEvent<yup$1.ObjectSchema<{
323
323
  }];
324
324
  //#endregion
325
325
  export { webhookEvents as n, WebhookEvent as t };
326
- //# sourceMappingURL=webhooks-C5gG85Ce.d.ts.map
326
+ //# sourceMappingURL=webhooks-ByXrdSOx.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks-C5gG85Ce.d.ts","names":[],"sources":["../src/interface/webhooks.ts"],"mappings":";;;KAMY,YAAA,WAAuB,KAAA,CAAI,MAAA;EACrC,IAAA;EACA,MAAA,EAAQ,CAAC;EACT,QAAA;IACE,OAAA;IACA,WAAA;IACA,IAAA;EAAA;AAAA;AAAA,cAIS,aAAA,YAAa,YAAA,CAAA,KAAA,CAAA,YAAA"}
1
+ {"version":3,"file":"webhooks-ByXrdSOx.d.ts","names":[],"sources":["../src/interface/webhooks.ts"],"mappings":";;;KAMY,YAAA,WAAuB,KAAA,CAAI,MAAA;EACrC,IAAA;EACA,MAAA,EAAQ,CAAC;EACT,QAAA;IACE,OAAA;IACA,WAAA;IACA,IAAA;EAAA;AAAA;AAAA,cAIS,aAAA,YAAa,YAAA,CAAA,KAAA,CAAA,YAAA"}