@dalmore/api-contracts 0.0.0-dev.d07da18 → 0.0.0-dev.d29fb02

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 (205) hide show
  1. package/README.md +23 -19
  2. package/common/types/account-contact.types.ts +2 -1
  3. package/common/types/account-manager.types.ts +3 -7
  4. package/common/types/account-setting.types.ts +65 -0
  5. package/common/types/account.types.ts +1 -0
  6. package/common/types/activity.types.ts +1 -1
  7. package/common/types/auth.types.ts +7 -18
  8. package/common/types/bonus-tier.types.ts +33 -0
  9. package/common/types/cart.types.ts +4 -1
  10. package/common/types/common.types.ts +38 -6
  11. package/common/types/contact-us.types.ts +6 -2
  12. package/common/types/covered-person.types.ts +2 -1
  13. package/common/types/dashboard.types.ts +2 -9
  14. package/common/types/disbursements.types.ts +119 -3
  15. package/common/types/escrow-account.types.ts +3 -3
  16. package/common/types/file.types.ts +17 -1
  17. package/common/types/i-will-do-it-later.types.ts +68 -0
  18. package/common/types/index.ts +2 -0
  19. package/common/types/individuals.types.ts +5 -17
  20. package/common/types/investor-account.types.ts +2 -1
  21. package/common/types/invite.types.ts +27 -1
  22. package/common/types/issuer-offering.types.ts +13 -17
  23. package/common/types/issuer-payment-method.types.ts +41 -0
  24. package/common/types/issuer.types.ts +9 -0
  25. package/common/types/legal-entity.types.ts +3 -2
  26. package/common/types/mail-template.types.ts +34 -0
  27. package/common/types/note.types.ts +1 -1
  28. package/common/types/notification.types.ts +525 -29
  29. package/common/types/offering.types.ts +4 -9
  30. package/common/types/site-settings.types.ts +2 -1
  31. package/common/types/site.types.ts +2 -9
  32. package/common/types/{trade-line-item.type.ts → trade-line-item.types.ts} +2 -9
  33. package/common/types/trade.types.ts +48 -2
  34. package/common/types/transaction.types.ts +12 -1
  35. package/common/types/trusted-contact.types.ts +7 -7
  36. package/common/types/user.types.ts +17 -33
  37. package/contracts/clients/cart/index.ts +21 -1
  38. package/contracts/clients/index.ts +6 -0
  39. package/contracts/{investors → clients}/issuer-payment-methods/index.ts +5 -2
  40. package/contracts/{compliance → clients}/payment-methods/index.ts +40 -12
  41. package/contracts/clients/trade-line-items/index.ts +1 -1
  42. package/contracts/clients/trades/index.ts +1 -1
  43. package/contracts/{investors → clients}/transactions/index.ts +3 -3
  44. package/index.ts +10 -0
  45. package/package.json +23 -32
  46. package/contracts/compliance/account-contacts/index.ts +0 -82
  47. package/contracts/compliance/account-managers/index.ts +0 -142
  48. package/contracts/compliance/accounts/index.ts +0 -187
  49. package/contracts/compliance/activities/index.ts +0 -55
  50. package/contracts/compliance/aic/index.ts +0 -60
  51. package/contracts/compliance/api-keys/index.ts +0 -91
  52. package/contracts/compliance/assets/index.ts +0 -122
  53. package/contracts/compliance/auth/index.ts +0 -134
  54. package/contracts/compliance/batch-jobs/index.ts +0 -62
  55. package/contracts/compliance/bonus-tiers/index.ts +0 -55
  56. package/contracts/compliance/checklist/index.ts +0 -87
  57. package/contracts/compliance/checklist-items/index.ts +0 -86
  58. package/contracts/compliance/covered-persons/index.ts +0 -97
  59. package/contracts/compliance/dashboard/index.ts +0 -111
  60. package/contracts/compliance/data-records/index.ts +0 -116
  61. package/contracts/compliance/data-rooms/index.ts +0 -113
  62. package/contracts/compliance/default-theme-configs/index.ts +0 -95
  63. package/contracts/compliance/disbursement/index.ts +0 -165
  64. package/contracts/compliance/disbursement-approval-users/index.ts +0 -84
  65. package/contracts/compliance/disbursement-transactions/index.ts +0 -37
  66. package/contracts/compliance/domain-filters/index.ts +0 -117
  67. package/contracts/compliance/email-themes/index.ts +0 -284
  68. package/contracts/compliance/escrow-accounts/index.ts +0 -85
  69. package/contracts/compliance/exchange-api-keys/index.ts +0 -129
  70. package/contracts/compliance/exchange-imports/index.ts +0 -137
  71. package/contracts/compliance/files/index.ts +0 -267
  72. package/contracts/compliance/files-public/index.ts +0 -188
  73. package/contracts/compliance/health/index.ts +0 -26
  74. package/contracts/compliance/index.ts +0 -147
  75. package/contracts/compliance/individuals/index.ts +0 -57
  76. package/contracts/compliance/investor-accounts/index.ts +0 -141
  77. package/contracts/compliance/invites/index.ts +0 -137
  78. package/contracts/compliance/issuer-bank-accounts/index.ts +0 -81
  79. package/contracts/compliance/issuer-payment-methods/index.ts +0 -81
  80. package/contracts/compliance/issuers/index.ts +0 -97
  81. package/contracts/compliance/job-items/index.ts +0 -58
  82. package/contracts/compliance/jobs/index.ts +0 -59
  83. package/contracts/compliance/kyb/index.ts +0 -54
  84. package/contracts/compliance/kyc/index.ts +0 -77
  85. package/contracts/compliance/legal-entities/index.ts +0 -57
  86. package/contracts/compliance/login-histories/index.ts +0 -37
  87. package/contracts/compliance/notes/index.ts +0 -69
  88. package/contracts/compliance/notion-databases/index.ts +0 -107
  89. package/contracts/compliance/notion-pages/index.ts +0 -105
  90. package/contracts/compliance/offering-reports/index.ts +0 -149
  91. package/contracts/compliance/offerings/index.ts +0 -233
  92. package/contracts/compliance/pages/index.ts +0 -178
  93. package/contracts/compliance/rejection-reasons/index.ts +0 -32
  94. package/contracts/compliance/review/index.ts +0 -169
  95. package/contracts/compliance/roles/index.ts +0 -34
  96. package/contracts/compliance/secondary-customers/index.ts +0 -77
  97. package/contracts/compliance/secondary-orders/index.ts +0 -60
  98. package/contracts/compliance/secondary-trades/index.ts +0 -100
  99. package/contracts/compliance/secure-requests/index.ts +0 -54
  100. package/contracts/compliance/signer/index.ts +0 -369
  101. package/contracts/compliance/site-links/index.ts +0 -128
  102. package/contracts/compliance/site-settings/index.ts +0 -669
  103. package/contracts/compliance/sites/index.ts +0 -56
  104. package/contracts/compliance/state-machine/index.ts +0 -94
  105. package/contracts/compliance/tasks/index.ts +0 -91
  106. package/contracts/compliance/third-parties/index.ts +0 -52
  107. package/contracts/compliance/trade-line-items/index.ts +0 -59
  108. package/contracts/compliance/trades/index.ts +0 -230
  109. package/contracts/compliance/transactions/index.ts +0 -161
  110. package/contracts/compliance/user-manuals/index.ts +0 -271
  111. package/contracts/compliance/user-settings/index.ts +0 -189
  112. package/contracts/compliance/users/index.ts +0 -200
  113. package/contracts/compliance/webhooks/index.ts +0 -41
  114. package/contracts/compliance-apikey/accounts/index.ts +0 -58
  115. package/contracts/compliance-apikey/index.ts +0 -14
  116. package/contracts/index.ts +0 -6
  117. package/contracts/investors/account-contacts/index.ts +0 -58
  118. package/contracts/investors/aic/index.ts +0 -59
  119. package/contracts/investors/assets/index.ts +0 -61
  120. package/contracts/investors/auth/index.ts +0 -116
  121. package/contracts/investors/bonus-tiers/index.ts +0 -37
  122. package/contracts/investors/cart/index.ts +0 -75
  123. package/contracts/investors/contact-us/index.ts +0 -48
  124. package/contracts/investors/data-records/index.ts +0 -113
  125. package/contracts/investors/data-rooms/index.ts +0 -96
  126. package/contracts/investors/files/index.ts +0 -167
  127. package/contracts/investors/files-public/index.ts +0 -185
  128. package/contracts/investors/index.ts +0 -72
  129. package/contracts/investors/individuals/index.ts +0 -99
  130. package/contracts/investors/investor-accounts/index.ts +0 -110
  131. package/contracts/investors/issuers/index.ts +0 -30
  132. package/contracts/investors/legal-entities/index.ts +0 -93
  133. package/contracts/investors/notes/index.ts +0 -69
  134. package/contracts/investors/offerings/index.ts +0 -93
  135. package/contracts/investors/pages/index.ts +0 -88
  136. package/contracts/investors/payment-methods/index.ts +0 -149
  137. package/contracts/investors/portfolios/index.ts +0 -53
  138. package/contracts/investors/sites/index.ts +0 -96
  139. package/contracts/investors/tasks/index.ts +0 -111
  140. package/contracts/investors/trade-line-items/index.ts +0 -75
  141. package/contracts/investors/trades/index.ts +0 -114
  142. package/contracts/investors/trusted-contacts/index.ts +0 -93
  143. package/contracts/investors/user-manuals/index.ts +0 -62
  144. package/contracts/investors/user-settings/index.ts +0 -170
  145. package/contracts/investors/users/index.ts +0 -45
  146. package/contracts/investors/webhooks/index.ts +0 -30
  147. package/contracts/issuers/account-contacts/index.ts +0 -76
  148. package/contracts/issuers/account-integrations/index.ts +0 -97
  149. package/contracts/issuers/accounts/index.ts +0 -97
  150. package/contracts/issuers/activities/index.ts +0 -54
  151. package/contracts/issuers/aic/index.ts +0 -39
  152. package/contracts/issuers/api-key-logs/index.ts +0 -53
  153. package/contracts/issuers/api-keys/index.ts +0 -93
  154. package/contracts/issuers/assets/index.ts +0 -122
  155. package/contracts/issuers/auth/index.ts +0 -152
  156. package/contracts/issuers/bonus-tiers/index.ts +0 -55
  157. package/contracts/issuers/contact-us/index.ts +0 -48
  158. package/contracts/issuers/covered-persons/index.ts +0 -136
  159. package/contracts/issuers/dashboard/index.ts +0 -72
  160. package/contracts/issuers/data-records/index.ts +0 -257
  161. package/contracts/issuers/data-rooms/index.ts +0 -134
  162. package/contracts/issuers/disbursement-approval-users/index.ts +0 -82
  163. package/contracts/issuers/disbursement-transactions/index.ts +0 -53
  164. package/contracts/issuers/disbursements/index.ts +0 -153
  165. package/contracts/issuers/email-themes/index.ts +0 -242
  166. package/contracts/issuers/escrow-accounts/index.ts +0 -81
  167. package/contracts/issuers/exchange-api-keys/index.ts +0 -144
  168. package/contracts/issuers/files/index.ts +0 -166
  169. package/contracts/issuers/files-public/index.ts +0 -166
  170. package/contracts/issuers/health/index.ts +0 -24
  171. package/contracts/issuers/index.ts +0 -112
  172. package/contracts/issuers/investor-accounts/index.ts +0 -148
  173. package/contracts/issuers/invites/index.ts +0 -129
  174. package/contracts/issuers/issuer/index.ts +0 -94
  175. package/contracts/issuers/issuer-bank-accounts/index.ts +0 -81
  176. package/contracts/issuers/issuer-payment-methods/index.ts +0 -136
  177. package/contracts/issuers/kyc/index.ts +0 -38
  178. package/contracts/issuers/login-histories/index.ts +0 -51
  179. package/contracts/issuers/notes/index.ts +0 -69
  180. package/contracts/issuers/offerings/index.ts +0 -206
  181. package/contracts/issuers/pages/index.ts +0 -138
  182. package/contracts/issuers/payment-methods/index.ts +0 -61
  183. package/contracts/issuers/portfolios/index.ts +0 -36
  184. package/contracts/issuers/rejection-reasons/index.ts +0 -32
  185. package/contracts/issuers/review/index.ts +0 -63
  186. package/contracts/issuers/secondary-customers/index.ts +0 -55
  187. package/contracts/issuers/secondary-orders/index.ts +0 -57
  188. package/contracts/issuers/secondary-trades/index.ts +0 -57
  189. package/contracts/issuers/secure-requests/index.ts +0 -34
  190. package/contracts/issuers/site-links/index.ts +0 -116
  191. package/contracts/issuers/site-settings/index.ts +0 -585
  192. package/contracts/issuers/sites/index.ts +0 -32
  193. package/contracts/issuers/tasks/index.ts +0 -111
  194. package/contracts/issuers/trades/index.ts +0 -132
  195. package/contracts/issuers/transactions/index.ts +0 -158
  196. package/contracts/issuers/user-manuals/index.ts +0 -62
  197. package/contracts/issuers/user-settings/index.ts +0 -170
  198. package/contracts/issuers/users/index.ts +0 -126
  199. package/contracts/secondaries/accounts/index.ts +0 -58
  200. package/contracts/secondaries/index.ts +0 -23
  201. package/contracts/secondaries/secondary-customers/index.ts +0 -55
  202. package/contracts/secondaries/secondary-issuers/index.ts +0 -94
  203. package/contracts/secondaries/secondary-orders/index.ts +0 -56
  204. package/contracts/secondaries/secondary-securities/index.ts +0 -95
  205. package/contracts/secondaries/secondary-trades/index.ts +0 -56
package/README.md CHANGED
@@ -14,32 +14,33 @@ npm install @dalmore/api-contracts@dev
14
14
 
15
15
  ## Usage
16
16
 
17
- ### Import specific contracts (recommended for tree-shaking)
17
+ ### Import from main entry
18
18
 
19
19
  ```typescript
20
- import { complianceContract } from '@dalmore/api-contracts/compliance';
21
- import { investorsContract } from '@dalmore/api-contracts/investors';
22
- import { issuersContract } from '@dalmore/api-contracts/issuers';
23
- import { clientsContract } from '@dalmore/api-contracts/clients';
20
+ import { clientsContract } from '@dalmore/api-contracts';
21
+ import type { IInvestorAccount } from '@dalmore/api-contracts';
24
22
  ```
25
23
 
26
- ### Import types
24
+ ### Import specific subpaths (recommended for tree-shaking)
27
25
 
28
26
  ```typescript
29
- import type { IInvestorAccount } from '@dalmore/api-contracts/types/investor-account.types';
30
- import type { ITrade } from '@dalmore/api-contracts/types/trade.types';
27
+ // Import clients contract
28
+ import { clientsContract } from '@dalmore/api-contracts/clients';
29
+
30
+ // Import types
31
+ import type { IInvestorAccount, ITrade } from '@dalmore/api-contracts/types';
31
32
  ```
32
33
 
33
34
  ### Create a typed client
34
35
 
35
36
  ```typescript
36
- import { complianceContract } from '@dalmore/api-contracts/compliance';
37
+ import { clientsContract } from '@dalmore/api-contracts/clients';
37
38
  import { initClient } from '@ts-rest/core';
38
39
 
39
- const client = initClient(complianceContract, {
40
+ const client = initClient(clientsContract, {
40
41
  baseUrl: 'https://platform.dalmoregroup.com',
41
42
  baseHeaders: {
42
- Authorization: `Bearer ${token}`,
43
+ 'X-API-Key': `${apiKey}`,
43
44
  },
44
45
  });
45
46
 
@@ -53,17 +54,20 @@ const { status, body } = await client.accounts.getAccounts({
53
54
 
54
55
  This package requires the following peer dependencies:
55
56
 
56
- - `@ts-rest/core` ^3.0.0
57
- - `zod` ^3.0.0
57
+ - `@anatine/zod-openapi` ^1.14.2
58
+ - `@ts-rest/core` ^3.52.1
59
+ - `typeid-js` ^1.2.0
60
+ - `zod` ^3.24.4
58
61
 
59
- ## Available Contracts
62
+ ## Available Exports
60
63
 
61
- - `complianceContract` - Compliance portal API
62
- - `investorsContract` - Investor portal API
63
- - `issuersContract` - Issuer portal API
64
64
  - `clientsContract` - Client API (API key auth)
65
- - `secondariesContract` - Secondaries API
66
- - `complianceApiKeyContract` - Compliance API (API key auth)
65
+
66
+ ## Available Subpath Exports
67
+
68
+ - `@dalmore/api-contracts` - Main entry (clients contract and types)
69
+ - `@dalmore/api-contracts/clients` - Clients contract
70
+ - `@dalmore/api-contracts/types` - All common types
67
71
 
68
72
  ## TypeScript Configuration
69
73
 
@@ -6,6 +6,7 @@ import { PhoneZodSchema } from './phone.type';
6
6
  import {
7
7
  AccountContactType,
8
8
  AccountZod,
9
+ EmailSchema,
9
10
  IPaginationMeta,
10
11
  } from './common.types';
11
12
  import { IBaseEntity } from './entity.types';
@@ -60,7 +61,7 @@ export const PatchAccountContactZod = z.object({
60
61
  .openapi({ example: 'Mr' }),
61
62
  firstName: z.string().min(1).max(150).openapi({ example: 'John' }),
62
63
  lastName: z.string().min(1).max(150).openapi({ example: 'Doe' }),
63
- email: z.string().email().openapi({ example: 'john.doe@example.com' }),
64
+ email: EmailSchema.openapi({ example: 'john.doe@example.com' }),
64
65
  phone: PhoneZodSchema.nullable()
65
66
  .optional()
66
67
  .openapi({ example: '+12124567890' }),
@@ -4,7 +4,7 @@ import { TypeID } from 'typeid-js';
4
4
  import { IBaseEntity } from './entity.types';
5
5
  import { PhoneNumberData } from './sms.types';
6
6
  import { userIdSchema, UserZod } from './user.types';
7
- import { IPaginationMeta } from './common.types';
7
+ import { EmailSchema, IPaginationMeta } from './common.types';
8
8
  import { PhoneZodSchema } from './phone.type';
9
9
 
10
10
  extendZodWithOpenApi(z);
@@ -68,7 +68,7 @@ export type IAccountManagerZod = z.infer<typeof IAccountManagerZod>;
68
68
  export const PostAccountManagerZod = z.object({
69
69
  firstName: z.string().min(1).max(255).openapi({ example: 'John' }),
70
70
  lastName: z.string().min(1).max(255).openapi({ example: 'Doe' }),
71
- email: z.string().email().openapi({ example: 'john.doe@example.com' }),
71
+ email: EmailSchema,
72
72
  phone: PhoneZodSchema.nullable()
73
73
  .optional()
74
74
  .openapi({ example: '+12124567890' }),
@@ -80,11 +80,7 @@ export type PostAccountManagerZod = z.infer<typeof PostAccountManagerZod>;
80
80
  export const PatchAccountManagerZod = z.object({
81
81
  firstName: z.string().min(1).max(255).optional().openapi({ example: 'John' }),
82
82
  lastName: z.string().min(1).max(255).optional().openapi({ example: 'Doe' }),
83
- email: z
84
- .string()
85
- .email()
86
- .optional()
87
- .openapi({ example: 'john.doe@example.com' }),
83
+ email: EmailSchema.optional(),
88
84
  phone: PhoneZodSchema.nullable()
89
85
  .optional()
90
86
  .openapi({ example: '+12124567890' }),
@@ -0,0 +1,65 @@
1
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
+ import { z } from 'zod';
3
+ import { TypeID } from 'typeid-js';
4
+ import { IBaseEntity } from './entity.types';
5
+ import { IPaginationMeta } from './common.types';
6
+ import { accountIdSchema } from './account.types';
7
+
8
+ extendZodWithOpenApi(z);
9
+
10
+ export const accountSettingIdSchema = z.string().refine(
11
+ (value) => {
12
+ try {
13
+ const tid = TypeID.fromString(value);
14
+ return tid.getType() === 'account_setting';
15
+ } catch {
16
+ return false;
17
+ }
18
+ },
19
+ {
20
+ message:
21
+ 'Invalid account setting ID format. Must be a valid TypeID with "account_setting" prefix.',
22
+ },
23
+ );
24
+
25
+ export const IAccountSettingZod = IBaseEntity.extend({
26
+ id: accountSettingIdSchema.openapi({
27
+ example: 'account_setting_01j5y5ghx8fvc83dmx3pznq7hv',
28
+ }),
29
+ accountId: z.string().openapi({
30
+ example: 'account_01j5y5ghx8fvc83dmx3pznq7hv',
31
+ }),
32
+ });
33
+ export type IAccountSettingZod = z.infer<typeof IAccountSettingZod>;
34
+
35
+ export const IPaginatedAccountSetting = z.object({
36
+ items: z.array(IAccountSettingZod),
37
+ meta: IPaginationMeta,
38
+ });
39
+ export type IPaginatedAccountSetting = z.infer<typeof IPaginatedAccountSetting>;
40
+
41
+ export const AccountSettingsFilters = z.object({
42
+ accountId: accountIdSchema.optional(),
43
+ });
44
+ export type AccountSettingsFilters = z.infer<typeof AccountSettingsFilters>;
45
+
46
+ export const accountSettingsInclude = z.enum(['notificationChannels']);
47
+
48
+ export const AccountSettingsIncludeQuery = z.object({
49
+ include: z
50
+ .string()
51
+ .optional()
52
+ .transform((str) => (str ? str.split(',') : []))
53
+ .refine(
54
+ (includes) =>
55
+ includes.every((include) =>
56
+ accountSettingsInclude.options.includes(include as any),
57
+ ),
58
+ {
59
+ message: `Invalid include value. Valid values are: ${accountSettingsInclude.options.join(', ')}`,
60
+ },
61
+ ),
62
+ });
63
+ export type AccountSettingsIncludeQuery = z.infer<
64
+ typeof AccountSettingsIncludeQuery
65
+ >;
@@ -91,6 +91,7 @@ export const AccountFiltersZod = z.object({
91
91
  const accountsInclude = z.enum([
92
92
  'accountManager',
93
93
  'accountIntegrations',
94
+ 'accountSettings',
94
95
  'apiKeys',
95
96
  'assets',
96
97
  'dataRooms',
@@ -199,7 +199,7 @@ export const ActivityZod = IBaseEntity.extend({
199
199
  userId: z.string().nullable(),
200
200
  activityTypeId: z.string(),
201
201
  accountId: z.string().nullable(),
202
- user: UserForActivityZod,
202
+ user: UserForActivityZod.nullable(),
203
203
  activityType: ActivityTypeZod,
204
204
  targetObject: z.string().nullable().optional(),
205
205
  __entity: z.string().optional(),
@@ -8,6 +8,7 @@ import {
8
8
  ManagedByType,
9
9
  UserRole,
10
10
  createUrlSchema,
11
+ EmailSchema,
11
12
  } from './common.types';
12
13
  import { TypeID } from 'typeid-js';
13
14
  import { TwoFactorMethod } from './sms.types';
@@ -60,13 +61,7 @@ const BaseAuthBody = z.object({
60
61
  .openapi({
61
62
  example: 'Armstrong',
62
63
  }),
63
- email: z
64
- .string()
65
- .email()
66
- .transform((val) => val.toLowerCase())
67
- .openapi({
68
- example: 'neil@dalmoregroup.com',
69
- }),
64
+ email: EmailSchema,
70
65
  password: PasswordSchema,
71
66
  });
72
67
 
@@ -99,13 +94,7 @@ export const IChangePasswordBodyZod = z
99
94
  });
100
95
 
101
96
  export const LoginBody = z.object({
102
- email: z
103
- .string()
104
- .email()
105
- .transform((val) => val.toLowerCase())
106
- .openapi({
107
- example: 'neil@dalmoregroup.com',
108
- }),
97
+ email: EmailSchema,
109
98
  password: z.string().openapi({
110
99
  example: 'Secretpassword6#',
111
100
  }),
@@ -297,7 +286,7 @@ export const RegisterBodyInvestors = BaseAuthBody.extend({
297
286
  });
298
287
 
299
288
  export const ResetPasswordVerifyBody = z.object({
300
- email: z.string().email(),
289
+ email: EmailSchema,
301
290
  code: z.string().length(6, 'code is not 6 characters').openapi({
302
291
  example: '123456',
303
292
  }),
@@ -315,7 +304,7 @@ export type ResetPasswordVerifyResponseType = z.infer<
315
304
  >;
316
305
 
317
306
  export const ResetPasswordBody = z.object({
318
- email: z.string().email(),
307
+ email: EmailSchema,
319
308
  code: z.string().length(6, 'code is not 6 characters').openapi({
320
309
  example: '123456',
321
310
  }),
@@ -337,7 +326,7 @@ export type ClientAuthSuccessResponse = z.infer<
337
326
  >;
338
327
 
339
328
  export const AdminForgotPasswordRequestZod = z.object({
340
- email: z.string().email(),
329
+ email: EmailSchema,
341
330
  portal: z.nativeEnum(PortalType),
342
331
  });
343
332
  export type AdminForgotPasswordRequestZod = z.infer<
@@ -345,7 +334,7 @@ export type AdminForgotPasswordRequestZod = z.infer<
345
334
  >;
346
335
 
347
336
  export const InvestorForgotPasswordRequestZod = z.object({
348
- email: z.string().email(),
337
+ email: EmailSchema,
349
338
  url: createUrlSchema({ strict: true }),
350
339
  });
351
340
  export type InvestorForgotPasswordRequestZod = z.infer<
@@ -98,6 +98,15 @@ export type EstimateBonusTierCalculationZod = z.infer<
98
98
  typeof EstimateBonusTierCalculationZod
99
99
  >;
100
100
 
101
+ export const ComplianceEstimateBonusTierCalculationZod =
102
+ EstimateBonusTierCalculationZod.and(
103
+ z.object({
104
+ accountId: accountIdSchema,
105
+ }),
106
+ );
107
+ export type ComplianceEstimateBonusTierCalculationZod = z.infer<
108
+ typeof ComplianceEstimateBonusTierCalculationZod
109
+ >;
101
110
  export const EstimateBonusTierCalculationResponseZod = z.object({
102
111
  bonusTierId: bonusTierIdSchema
103
112
  .nullable()
@@ -145,3 +154,27 @@ export const CompliancePostBonusTierZod = PostBonusTierZod.extend({
145
154
  export type CompliancePostBonusTierZod = z.infer<
146
155
  typeof CompliancePostBonusTierZod
147
156
  >;
157
+ export const PurchaseCalculationZod = z.object({
158
+ assetId: assetIdSchema,
159
+ totalAmount: z.number().positive().openapi({ example: 1000 }),
160
+ purchasedShares: z.number().positive().int().openapi({ example: 100 }),
161
+ });
162
+ export type PurchaseCalculationZod = z.infer<typeof PurchaseCalculationZod>;
163
+
164
+ export const PurchaseCalculationResponseZod = z.object({
165
+ bonusTierId: bonusTierIdSchema
166
+ .nullable()
167
+ .openapi({ example: 'bonus_tier_01j5y5ghx5fg68d663j1fvy2x7' }),
168
+ assetId: assetIdSchema.openapi({
169
+ example: 'asset_00041061050r3gg28a1c60t3gf',
170
+ }),
171
+ type: z
172
+ .nativeEnum(BonusType)
173
+ .nullable()
174
+ .openapi({ example: BonusType.PERCENTAGE }),
175
+ bonusShares: z.number().int().openapi({ example: 100 }),
176
+ });
177
+
178
+ export type PurchaseCalculationResponseZod = z.infer<
179
+ typeof PurchaseCalculationResponseZod
180
+ >;
@@ -3,6 +3,7 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
3
3
  import { TradeStatus } from './common.types';
4
4
  import { investorAccountIdSchema } from './investor-account.types';
5
5
  import { paymentMethodIdSchema } from './payment-methods.types';
6
+ import { userIdSchema } from './user.types';
6
7
 
7
8
  extendZodWithOpenApi(z);
8
9
 
@@ -10,7 +11,9 @@ export const PlaceTradeResponse = z.object({
10
11
  tradeStatus: z.nativeEnum(TradeStatus).optional(),
11
12
  });
12
13
  export const PlaceTradeBody = z.object({});
13
-
14
+ export const ClientPlacetradeBody = z.object({
15
+ userId: userIdSchema,
16
+ });
14
17
  export const PatchCartBody = z.object({
15
18
  investorAccountId: investorAccountIdSchema.optional(),
16
19
  paymentMethodId: paymentMethodIdSchema.optional(),
@@ -69,6 +69,10 @@ export enum BaseStatus {
69
69
  VOIDED = 'VOIDED',
70
70
  JOIN = 'JOIN',
71
71
  RESTORE = 'RESTORE',
72
+ ACTIVE = 'ACTIVE',
73
+ LOCKED = 'LOCKED',
74
+ ENABLED = 'ENABLED',
75
+ DISABLED = 'DISABLED',
72
76
  }
73
77
 
74
78
  export const UserWithoutPasswordAccountZod = IBaseEntity.extend({
@@ -111,6 +115,10 @@ export enum HttpMethod {
111
115
  OPTIONS = 'OPTIONS',
112
116
  }
113
117
 
118
+ export enum UserStatus {
119
+ ACTIVE = 'ACTIVE',
120
+ LOCKED = 'LOCKED',
121
+ }
114
122
  export const SENSITIVE_PATTERNS = [
115
123
  /password/i,
116
124
  /credit.*card/i,
@@ -200,11 +208,6 @@ export enum UserType {
200
208
  DEMO = 'DEMO',
201
209
  }
202
210
 
203
- export enum UserStatus {
204
- ACTIVE = 'ACTIVE',
205
- LOCKED = 'LOCKED',
206
- }
207
-
208
211
  export enum UserRole {
209
212
  API_KEY = 'API_KEY',
210
213
  IMPORT = 'IMPORT',
@@ -306,7 +309,7 @@ export const AuthUserReq = BaseAuthReq.extend({
306
309
  lastName: z.string(),
307
310
  email: z.string().email(),
308
311
  provider: z.string(),
309
- status: z.lazy(() => z.nativeEnum(UserStatus)),
312
+ locked: z.boolean(),
310
313
  lastLoginAt: z.date().nullable(),
311
314
  loginCount: z.number(),
312
315
  requiresTwoFactorSetup: z.boolean().optional(),
@@ -809,6 +812,8 @@ export enum EventField {
809
812
  SA_STATUS = 'saStatus',
810
813
  ONBOARDING_STATUS = 'onboardingStatus',
811
814
  TRANSACTION_STATUS = 'transactionStatus',
815
+ ACTIVE = 'active',
816
+ LOCKED = 'locked',
812
817
  }
813
818
 
814
819
  export enum EventName {
@@ -1518,3 +1523,30 @@ export const SUBJECT_TYPE_MAP: Record<BulkExportType, string> = {
1518
1523
  [BulkExportType.SECONDARY_CUSTOMERS]: 'Secondary Customers',
1519
1524
  [BulkExportType.SECONDARY_TRADES]: 'Secondary Trades',
1520
1525
  };
1526
+
1527
+ export const StringToBooleanSchema = z.preprocess(
1528
+ (val) =>
1529
+ val === 'true' || val === '1'
1530
+ ? true
1531
+ : val === 'false' || val === '0'
1532
+ ? false
1533
+ : val,
1534
+ z.boolean(),
1535
+ );
1536
+ export type StringToBooleanSchema = z.infer<typeof StringToBooleanSchema>;
1537
+
1538
+ /**
1539
+ * Reusable email schema that validates email format, transforms to lowercase,
1540
+ * and includes OpenAPI metadata.
1541
+ *
1542
+ * @example
1543
+ * EmailSchema.parse('John.Doe@EXAMPLE.COM'); // returns 'john.doe@example.com'
1544
+ * EmailSchema.optional().parse(undefined); // returns undefined
1545
+ */
1546
+ export const EmailSchema = z
1547
+ .string()
1548
+ .email()
1549
+ .transform((val) => val.toLowerCase())
1550
+ .openapi({
1551
+ example: 'neil@dalmoregroup.com',
1552
+ });
@@ -1,7 +1,11 @@
1
1
  import { z } from 'zod';
2
2
  import { extendZodWithOpenApi } from '@anatine/zod-openapi';
3
3
  import { TypeID } from 'typeid-js';
4
- import { BaseContactUsOptions, createUrlSchema } from './common.types';
4
+ import {
5
+ BaseContactUsOptions,
6
+ createUrlSchema,
7
+ EmailSchema,
8
+ } from './common.types';
5
9
  extendZodWithOpenApi(z);
6
10
 
7
11
  export const contactUsIdSchema = z.string().refine(
@@ -55,7 +59,7 @@ export const InvestorPostContactUsZod = PostContactUsZod.extend({
55
59
  export type InvestorPostContactUsZod = z.infer<typeof InvestorPostContactUsZod>;
56
60
 
57
61
  export const PublicInvestorContactUsZod = PostContactUsZod.extend({
58
- email: z.string().email().openapi({ example: 'email@example.com' }),
62
+ email: EmailSchema,
59
63
  firstName: z.string().min(1).max(100).openapi({ example: 'John' }),
60
64
  lastName: z.string().min(1).max(100).openapi({ example: 'Doe' }),
61
65
  contactOption: z.nativeEnum(InvestorContactOptions).openapi({
@@ -6,6 +6,7 @@ import {
6
6
  ComplianceReview,
7
7
  CoveredPersonsRoleType,
8
8
  CoveredPersonsStatus,
9
+ EmailSchema,
9
10
  IDType,
10
11
  IPaginationMeta,
11
12
  } from './common.types';
@@ -137,7 +138,7 @@ export const PatchCoveredPersonsZod = z
137
138
  .openapi({ example: CoveredPersonsRoleType.ACCOUNTING }),
138
139
 
139
140
  ownership: z.number().min(0).max(100).openapi({ example: 15 }).optional(),
140
- email: z.string().nullable().optional(),
141
+ email: EmailSchema.nullable().optional(),
141
142
  idType: z
142
143
  .nativeEnum(IDType)
143
144
  .optional()
@@ -7,6 +7,7 @@ import {
7
7
  FileLabels,
8
8
  IPaginationMeta,
9
9
  OfferingType,
10
+ StringToBooleanSchema,
10
11
  } from './common.types';
11
12
  import { accountIdSchema } from './account.types';
12
13
 
@@ -330,15 +331,7 @@ export const GetInvestmentDashboardQueryZod = z.object({
330
331
  offerings: OfferingsArrayQueryZod.optional(),
331
332
  offeringTypes: OfferingTypesQueryZod.optional(),
332
333
  timeFilteringType: z.nativeEnum(DashboardTimeFilteringType),
333
- debug: z.preprocess(
334
- (val) =>
335
- val === 'true' || val === '1'
336
- ? true
337
- : val === 'false' || val === '0'
338
- ? false
339
- : val,
340
- z.boolean().optional(),
341
- ),
334
+ debug: StringToBooleanSchema.optional(),
342
335
  });
343
336
  export type GetInvestmentDashboardQueryZod = z.infer<
344
337
  typeof GetInvestmentDashboardQueryZod
@@ -11,14 +11,17 @@ import {
11
11
  import { tradeIdSchema } from './trade.types';
12
12
  import { accountIdSchema } from './account.types';
13
13
  import { TypeID } from 'typeid-js';
14
- import { issuerIdSchema } from './issuer.types';
15
- import { issuerBankAccountIdSchema } from './issuer-bank-account.types';
14
+ import { IIssuer, issuerIdSchema } from './issuer.types';
15
+ import {
16
+ IIssuerBankAccount,
17
+ issuerBankAccountIdSchema,
18
+ } from './issuer-bank-account.types';
16
19
  import { userIdSchema, UserZod } from './user.types';
17
20
  import {
18
21
  PostDisbursementAdjustmentZod,
19
22
  DisbursementAdjustmentType,
20
23
  } from './disbursement-adjustment.types';
21
- import { escrowAccountIdSchema } from './escrow-account.types';
24
+ import { IEscrowAccount, escrowAccountIdSchema } from './escrow-account.types';
22
25
 
23
26
  export const disbursementIdSchema = z.string().refine(
24
27
  (value) => {
@@ -308,3 +311,116 @@ export const DisbursementSummaryZod = z.object({
308
311
  amountToBeTransferred: z.number(),
309
312
  });
310
313
  export type DisbursementSummaryZod = z.infer<typeof DisbursementSummaryZod>;
314
+
315
+ // GET /disbursements/preview query parameters
316
+ export const GetDisbursementPreviewQueryZod = z.object({
317
+ offeringId: offeringIdSchema,
318
+ selectedTrades: z
319
+ .string()
320
+ .optional()
321
+ .transform((str) => (str ? str.split(',') : []))
322
+ .refine(
323
+ (ids) =>
324
+ ids.every((id) => {
325
+ try {
326
+ const tid = TypeID.fromString(id);
327
+ return tid.getType() === 'trade';
328
+ } catch {
329
+ return false;
330
+ }
331
+ }),
332
+ {
333
+ message: 'All selected trades must be valid trade IDs',
334
+ },
335
+ )
336
+ .openapi({
337
+ example: 'trade_01abc123,trade_01def456',
338
+ }),
339
+ });
340
+ export type GetDisbursementPreviewQueryZod = z.infer<
341
+ typeof GetDisbursementPreviewQueryZod
342
+ >;
343
+
344
+ // Context fields for disbursement preview
345
+ export const DisbursementPreviewContextZod = z.object({
346
+ issuer: z.lazy(() => IIssuer).nullable(),
347
+ offering: z.lazy(() => IOffering).nullable(),
348
+ escrowAccount: z.lazy(() => IEscrowAccount).nullable(),
349
+ destinationBank: z.lazy(() => IIssuerBankAccount).nullable(),
350
+ });
351
+ export type DisbursementPreviewContextZod = z.infer<
352
+ typeof DisbursementPreviewContextZod
353
+ >;
354
+
355
+ // Balance values for disbursement preview
356
+ export const DisbursementPreviewBalanceZod = z.object({
357
+ totalRaised: z.number(),
358
+ totalDisbursed: z.number(),
359
+ pending: z.number(),
360
+ refundPool: z.number(),
361
+ availableForDisbursement: z.number(),
362
+ });
363
+ export type DisbursementPreviewBalanceZod = z.infer<
364
+ typeof DisbursementPreviewBalanceZod
365
+ >;
366
+
367
+ // Trade summary for disbursement preview
368
+ export const DisbursementPreviewTradeSummaryZod = z.object({
369
+ selectedTradesCount: z.number(),
370
+ selectedTradesTotalAmount: z.number(),
371
+ });
372
+ export type DisbursementPreviewTradeSummaryZod = z.infer<
373
+ typeof DisbursementPreviewTradeSummaryZod
374
+ >;
375
+
376
+ // Contingency validation result
377
+ export const DisbursementPreviewContingencyZod = z.object({
378
+ contingencyPassed: z.boolean(),
379
+ contingencyMessage: z.string().nullable(),
380
+ contingencyAmount: z.number(),
381
+ });
382
+ export type DisbursementPreviewContingencyZod = z.infer<
383
+ typeof DisbursementPreviewContingencyZod
384
+ >;
385
+
386
+ // Amount defaults and constraints
387
+ export const DisbursementPreviewAmountZod = z.object({
388
+ defaultAmount: z.number(),
389
+ minAmount: z.number(),
390
+ maxAmount: z.number(),
391
+ });
392
+ export type DisbursementPreviewAmountZod = z.infer<
393
+ typeof DisbursementPreviewAmountZod
394
+ >;
395
+
396
+ // Complete response for GET /disbursements/preview
397
+ export const DisbursementPreviewZod = z.object({
398
+ context: DisbursementPreviewContextZod,
399
+ balance: DisbursementPreviewBalanceZod,
400
+ tradeSummary: DisbursementPreviewTradeSummaryZod,
401
+ contingency: DisbursementPreviewContingencyZod,
402
+ amount: DisbursementPreviewAmountZod,
403
+ });
404
+ export type DisbursementPreviewZod = z.infer<typeof DisbursementPreviewZod>;
405
+
406
+ export const EligibleOfferingZod = z.object({
407
+ offeringId: offeringIdSchema,
408
+ offeringName: z.string(),
409
+ availableAmount: z.number(),
410
+ });
411
+ export type EligibleOfferingZod = z.infer<typeof EligibleOfferingZod>;
412
+
413
+ export const IPaginatedEligibleOffering = z.object({
414
+ items: z.array(EligibleOfferingZod),
415
+ meta: IPaginationMeta,
416
+ });
417
+ export type IPaginatedEligibleOffering = z.infer<
418
+ typeof IPaginatedEligibleOffering
419
+ >;
420
+
421
+ export const EligibleOfferingsFiltersZod = z.object({
422
+ search: z.string().optional(),
423
+ });
424
+ export type EligibleOfferingsFiltersZod = z.infer<
425
+ typeof EligibleOfferingsFiltersZod
426
+ >;
@@ -1,6 +1,6 @@
1
1
  import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
2
  import { z } from 'zod';
3
- import { AccountZod, IPaginationMeta } from './common.types';
3
+ import { AccountZod, EmailSchema, IPaginationMeta } from './common.types';
4
4
  import { IBaseEntity } from './entity.types';
5
5
  import { TypeID } from 'typeid-js';
6
6
  import { accountIdSchema } from './account.types';
@@ -43,7 +43,7 @@ export const PostEscrowAccount = z.object({
43
43
  accountNumber: z.string().optional().nullable(),
44
44
  routingNumber: z.string().min(9).max(9).optional().nullable(),
45
45
  agentName: z.string().min(2).max(50),
46
- agentEmail: z.string().email(),
46
+ agentEmail: EmailSchema,
47
47
  });
48
48
 
49
49
  export type PostEscrowAccount = z.infer<typeof PostEscrowAccount>;
@@ -65,7 +65,7 @@ export const PatchEscrowAccount = z.object({
65
65
  accountNumber: z.string().min(10).max(18).optional().nullable().optional(),
66
66
  routingNumber: z.string().min(9).max(9).optional().nullable().optional(),
67
67
  agentName: z.string().min(2).max(50).optional(),
68
- agentEmail: z.string().email().optional(),
68
+ agentEmail: EmailSchema.optional(),
69
69
  });
70
70
 
71
71
  export type PatchEscrowAccount = z.infer<typeof PatchEscrowAccount>;