@dalmore/api-contracts 1.0.8 → 1.0.10
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.
- package/README.md +48 -39
- package/common/helpers/index.ts +59 -0
- package/{src/common → common}/types/account-contact.types.ts +2 -1
- package/{src/common → common}/types/account-manager.types.ts +3 -7
- package/common/types/account-setting.types.ts +65 -0
- package/{src/common → common}/types/account.types.ts +1 -0
- package/{src/common → common}/types/activity.types.ts +1 -1
- package/{src/common → common}/types/api-key-logs.types.ts +1 -1
- package/{src/common → common}/types/asset.types.ts +14 -14
- package/{src/common → common}/types/auth.types.ts +7 -18
- package/{src/common → common}/types/bonus-tier.types.ts +33 -0
- package/{src/common → common}/types/cart.types.ts +4 -1
- package/{src/common → common}/types/common.types.ts +39 -7
- package/{src/common → common}/types/contact-us.types.ts +6 -2
- package/{src/common → common}/types/covered-person.types.ts +2 -1
- package/{src/common → common}/types/dashboard.types.ts +2 -9
- package/{src/common → common}/types/data-record.types.ts +1 -1
- package/{src/common → common}/types/disbursements.types.ts +119 -3
- package/{src/common → common}/types/escrow-account.types.ts +3 -3
- package/{src/common → common}/types/file.types.ts +20 -4
- package/common/types/i-will-do-it-later.types.ts +68 -0
- package/{src/common → common}/types/index.ts +2 -0
- package/{src/common → common}/types/individuals.types.ts +5 -17
- package/{src/common → common}/types/investor-account.types.ts +2 -1
- package/{src/common → common}/types/invite.types.ts +27 -1
- package/{src/common → common}/types/issuer-offering.types.ts +113 -30
- package/{src/common → common}/types/issuer-payment-method.types.ts +41 -0
- package/{src/common → common}/types/issuer.types.ts +9 -0
- package/{src/common → common}/types/legal-entity.types.ts +3 -2
- package/{src/common → common}/types/note.types.ts +1 -1
- package/common/types/notification.types.ts +544 -0
- package/{src/common → common}/types/offering.types.ts +106 -20
- package/{src/common → common}/types/page.types.ts +1 -1
- package/{src/common → common}/types/phone.type.ts +1 -1
- package/{src/common → common}/types/site-settings.types.ts +2 -1
- package/{src/common → common}/types/site.types.ts +2 -9
- package/{src/common/types/trade-line-item.type.ts → common/types/trade-line-item.types.ts} +2 -9
- package/{src/common → common}/types/trade.types.ts +137 -4
- package/{src/common → common}/types/transaction.types.ts +12 -1
- package/{src/common → common}/types/trusted-contact.types.ts +7 -7
- package/{src/common → common}/types/user.types.ts +17 -33
- package/{src/common → common}/types/zip.type.ts +1 -1
- package/contracts/clients/cart/index.ts +80 -0
- package/{src/contracts → contracts}/clients/index.ts +10 -0
- package/contracts/clients/issuer-payment-methods/index.ts +39 -0
- package/contracts/clients/payment-methods/index.ts +85 -0
- package/contracts/clients/trade-line-items/index.ts +66 -0
- package/{src/contracts → contracts}/clients/trades/index.ts +65 -1
- package/contracts/clients/transactions/index.ts +37 -0
- package/index.ts +10 -0
- package/package.json +32 -11
- package/index.mjs +0 -10970
- package/src/common/types/address.spec.ts +0 -203
- package/src/common/types/common.types.spec.ts +0 -336
- package/src/common/types/contract-helpers.ts +0 -205
- package/src/common/types/files.types.spec.ts +0 -154
- package/src/common/types/issuer-payment-method.types.spec.ts +0 -612
- package/src/common/types/notification.types.ts +0 -58
- package/src/common/types/offering.types.spec.ts +0 -91
- package/src/common/types/phone.spec.ts +0 -76
- package/src/common/types/site-link.types.spec.ts +0 -134
- /package/{src/common → common}/types/account-detail.types.ts +0 -0
- /package/{src/common → common}/types/account-integration.types.ts +0 -0
- /package/{src/common → common}/types/address.types.ts +0 -0
- /package/{src/common → common}/types/aic.types.ts +0 -0
- /package/{src/common → common}/types/aml.types.ts +0 -0
- /package/{src/common → common}/types/api-keys.types.ts +0 -0
- /package/{src/common → common}/types/batch-jobs.types.ts +0 -0
- /package/{src/common → common}/types/checklist-items.types.ts +0 -0
- /package/{src/common → common}/types/checklist.types.ts +0 -0
- /package/{src/common → common}/types/comply-advantage-api.types.ts +0 -0
- /package/{src/common → common}/types/comply-advantage.types.ts +0 -0
- /package/{src/common → common}/types/countries.types.ts +0 -0
- /package/{src/common → common}/types/data-room.types.ts +0 -0
- /package/{src/common → common}/types/default-theme-config.types.ts +0 -0
- /package/{src/common → common}/types/disbursement-adjustment.types.ts +0 -0
- /package/{src/common → common}/types/disbursement-approval-user.types.ts +0 -0
- /package/{src/common → common}/types/disbursement-review.types.ts +0 -0
- /package/{src/common → common}/types/disbursement-transaction.types.ts +0 -0
- /package/{src/common → common}/types/domain-filter.types.ts +0 -0
- /package/{src/common → common}/types/email-theme.types.ts +0 -0
- /package/{src/common → common}/types/entity.types.ts +0 -0
- /package/{src/common → common}/types/error-responses.types.ts +0 -0
- /package/{src/common → common}/types/exchange-api-key.types.ts +0 -0
- /package/{src/common → common}/types/exchange-import.types.ts +0 -0
- /package/{src/common → common}/types/exchange-provider.types.ts +0 -0
- /package/{src/common → common}/types/health.types.ts +0 -0
- /package/{src/common → common}/types/investorAccountIdSchema.type.ts +0 -0
- /package/{src/common → common}/types/investors-offering.types.ts +0 -0
- /package/{src/common → common}/types/issuer-bank-account.types.ts +0 -0
- /package/{src/common → common}/types/job-item.types.ts +0 -0
- /package/{src/common → common}/types/jobs.types.ts +0 -0
- /package/{src/common → common}/types/kyb.types.ts +0 -0
- /package/{src/common → common}/types/kyc.types.ts +0 -0
- /package/{src/common → common}/types/login-history.types.ts +0 -0
- /package/{src/common → common}/types/mail-template.types.ts +0 -0
- /package/{src/common → common}/types/north-cap-integration.types.ts +0 -0
- /package/{src/common → common}/types/notion-api.types.ts +0 -0
- /package/{src/common → common}/types/notion-database.types.ts +0 -0
- /package/{src/common → common}/types/notion-page.types.ts +0 -0
- /package/{src/common → common}/types/offering-reports.types.ts +0 -0
- /package/{src/common → common}/types/offering-submission.types.ts +0 -0
- /package/{src/common → common}/types/page-revision.types.ts +0 -0
- /package/{src/common → common}/types/password.type.ts +0 -0
- /package/{src/common → common}/types/payment-methods.types.ts +0 -0
- /package/{src/common → common}/types/portfolio.types.ts +0 -0
- /package/{src/common → common}/types/privacy-policy-and-tos.types.ts +0 -0
- /package/{src/common → common}/types/queue.types.ts +0 -0
- /package/{src/common → common}/types/registered-reps.types.ts +0 -0
- /package/{src/common → common}/types/rejection-reasons.types.ts +0 -0
- /package/{src/common → common}/types/reminder-config.types.ts +0 -0
- /package/{src/common → common}/types/review.types.ts +0 -0
- /package/{src/common → common}/types/role.types.ts +0 -0
- /package/{src/common → common}/types/secondary-customer.types.ts +0 -0
- /package/{src/common → common}/types/secondary-issuer.types.ts +0 -0
- /package/{src/common → common}/types/secondary-order.types.ts +0 -0
- /package/{src/common → common}/types/secondary-security.types.ts +0 -0
- /package/{src/common → common}/types/secondary-trade.entity.ts +0 -0
- /package/{src/common → common}/types/secondary-trade.types.ts +0 -0
- /package/{src/common → common}/types/secure-request.types.ts +0 -0
- /package/{src/common → common}/types/signer.types.ts +0 -0
- /package/{src/common → common}/types/site-link.types.ts +0 -0
- /package/{src/common → common}/types/sms.types.ts +0 -0
- /package/{src/common → common}/types/state-machine.types.ts +0 -0
- /package/{src/common → common}/types/states.types.ts +0 -0
- /package/{src/common → common}/types/subdoc-preview.types.ts +0 -0
- /package/{src/common → common}/types/task.types.ts +0 -0
- /package/{src/common → common}/types/trade-adjustment.type.ts +0 -0
- /package/{src/common → common}/types/typography.types.ts +0 -0
- /package/{src/common → common}/types/user-manual.types.ts +0 -0
- /package/{src/common → common}/types/user-setting.types.ts +0 -0
- /package/{src/common → common}/types/webhook.types.ts +0 -0
- /package/{src/contracts → contracts}/clients/accounts/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/aic/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/api-key-logs/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/api-keys/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/assets/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/auth/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/files/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/files-public/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/individuals/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/investor-accounts/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/issuers/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/legal-entities/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/offerings/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/secure-requests/index.ts +0 -0
- /package/{src/contracts → contracts}/clients/sites/index.ts +0 -0
package/README.md
CHANGED
|
@@ -2,73 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
Type-safe API contracts for Dalmore Client Portal, powered by [ts-rest](https://ts-rest.com/).
|
|
4
4
|
|
|
5
|
-
This package provides **full end-to-end type inference** by shipping TypeScript source files alongside compiled JavaScript.
|
|
6
|
-
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
8
|
+
# Production (stable releases from main branch)
|
|
10
9
|
npm install @dalmore/api-contracts
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
### Peer Dependencies
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
npm install @
|
|
11
|
+
# Development (latest from dev branch)
|
|
12
|
+
npm install @dalmore/api-contracts@dev
|
|
17
13
|
```
|
|
18
14
|
|
|
19
15
|
## Usage
|
|
20
16
|
|
|
17
|
+
### Import from main entry
|
|
18
|
+
|
|
21
19
|
```typescript
|
|
22
20
|
import { clientsContract } from '@dalmore/api-contracts';
|
|
21
|
+
import type { IInvestorAccount } from '@dalmore/api-contracts';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Import specific subpaths (recommended for tree-shaking)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
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';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Create a typed client
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { clientsContract } from '@dalmore/api-contracts/clients';
|
|
23
38
|
import { initClient } from '@ts-rest/core';
|
|
24
39
|
|
|
25
40
|
const client = initClient(clientsContract, {
|
|
26
|
-
baseUrl: 'https://
|
|
41
|
+
baseUrl: 'https://platform.dalmoregroup.com',
|
|
27
42
|
baseHeaders: {
|
|
28
|
-
'
|
|
43
|
+
'X-API-Key': `${apiKey}`,
|
|
29
44
|
},
|
|
30
45
|
});
|
|
31
46
|
|
|
32
|
-
// Fully typed API calls
|
|
33
|
-
const { status, body } = await client.accounts.getAccounts(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const trade = await client.trades.getTrade({ params: { id: 'trade_123' } });
|
|
47
|
+
// Fully typed API calls
|
|
48
|
+
const { status, body } = await client.accounts.getAccounts({
|
|
49
|
+
query: { page: 1, limit: 10 },
|
|
50
|
+
});
|
|
37
51
|
```
|
|
38
52
|
|
|
53
|
+
## Peer Dependencies
|
|
54
|
+
|
|
55
|
+
This package requires the following peer dependencies:
|
|
56
|
+
|
|
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
|
|
61
|
+
|
|
62
|
+
## Available Exports
|
|
63
|
+
|
|
64
|
+
- `clientsContract` - Client 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
|
|
71
|
+
|
|
39
72
|
## TypeScript Configuration
|
|
40
73
|
|
|
41
|
-
|
|
74
|
+
This package ships TypeScript source files for maximum type safety. Your `tsconfig.json` should include:
|
|
42
75
|
|
|
43
76
|
```json
|
|
44
77
|
{
|
|
45
78
|
"compilerOptions": {
|
|
46
|
-
"skipLibCheck": true, // Recommended for faster compilation
|
|
47
79
|
"moduleResolution": "node",
|
|
48
80
|
"esModuleInterop": true
|
|
49
81
|
}
|
|
50
82
|
}
|
|
51
83
|
```
|
|
52
|
-
|
|
53
|
-
## Available Endpoints
|
|
54
|
-
|
|
55
|
-
The `clientsContract` includes:
|
|
56
|
-
|
|
57
|
-
| Endpoint | Description |
|
|
58
|
-
| ------------------ | ----------------------- |
|
|
59
|
-
| `accounts` | Account management |
|
|
60
|
-
| `aic` | AIC verification |
|
|
61
|
-
| `auth` | Authentication |
|
|
62
|
-
| `apiKeys` | API key management |
|
|
63
|
-
| `apiKeyLogs` | API key usage logs |
|
|
64
|
-
| `assets` | Asset management |
|
|
65
|
-
| `files` | File uploads |
|
|
66
|
-
| `filesPublic` | Public file access |
|
|
67
|
-
| `individuals` | Individual management |
|
|
68
|
-
| `investorAccounts` | Investor accounts |
|
|
69
|
-
| `issuers` | Issuer information |
|
|
70
|
-
| `legalEntities` | Legal entity management |
|
|
71
|
-
| `offerings` | Offering data |
|
|
72
|
-
| `secureRequests` | Secure request handling |
|
|
73
|
-
| `sites` | Site configuration |
|
|
74
|
-
| `trades` | Trade management |
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract helpers - minimal subset for API documentation generation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
type CurlOptions = {
|
|
6
|
+
query?: Record<string, string>;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
body?: Record<string, unknown>;
|
|
9
|
+
formData?: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const authHeader: CurlOptions['headers'] = {
|
|
13
|
+
Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const generateCurlExample = (
|
|
17
|
+
method: string,
|
|
18
|
+
path: string,
|
|
19
|
+
options: CurlOptions,
|
|
20
|
+
) => {
|
|
21
|
+
const baseUrl = 'https://dalmore-client-portal-api-prod.onrender.com/api/v1';
|
|
22
|
+
let curl = `curl -X ${method.toUpperCase()} '${baseUrl}${path}`;
|
|
23
|
+
if (options.query) {
|
|
24
|
+
const queryString = new URLSearchParams(options.query).toString();
|
|
25
|
+
curl += `?${queryString}`;
|
|
26
|
+
}
|
|
27
|
+
curl += "'";
|
|
28
|
+
if (options.headers) {
|
|
29
|
+
Object.entries(options.headers).forEach(([key, value]) => {
|
|
30
|
+
curl += ` \\\n --header '${key}: ${value}'`;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (options.body) {
|
|
34
|
+
curl += ` \\\n --header 'Content-Type: application/json'`;
|
|
35
|
+
curl += ` \\\n --data '${JSON.stringify(options.body)}'`;
|
|
36
|
+
}
|
|
37
|
+
if (options.formData) {
|
|
38
|
+
Object.entries(options.formData).forEach(([key, value]) => {
|
|
39
|
+
curl += ` \\\n --form '${key}=${value}'`;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return curl;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const generateApiDescription = (
|
|
46
|
+
summary: string,
|
|
47
|
+
method: string,
|
|
48
|
+
path: string,
|
|
49
|
+
options: CurlOptions,
|
|
50
|
+
) => {
|
|
51
|
+
const curlExample = generateCurlExample(method, path, options);
|
|
52
|
+
return `${summary}
|
|
53
|
+
|
|
54
|
+
### Example curl request
|
|
55
|
+
|
|
56
|
+
\`\`\`bash
|
|
57
|
+
${curlExample}
|
|
58
|
+
\`\`\``;
|
|
59
|
+
};
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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
|
+
>;
|
|
@@ -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(),
|
|
@@ -12,7 +12,7 @@ export const ApiLogsFiltersZod = z.object({
|
|
|
12
12
|
endpoint: z.string().optional(),
|
|
13
13
|
apiKeyId: apiKeyIdSchema.optional(),
|
|
14
14
|
method: z.nativeEnum(HttpMethod).optional(),
|
|
15
|
-
status: z.nativeEnum(HttpStatus).optional(),
|
|
15
|
+
status: z.preprocess(Number, z.nativeEnum(HttpStatus)).optional(),
|
|
16
16
|
from: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
17
17
|
to: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
18
18
|
});
|
|
@@ -29,7 +29,7 @@ export const assetIdSchema = z.string().refine(
|
|
|
29
29
|
message: `Invalid asset ID format. Must be a valid TypeID with "asset" prefix. Example: asset_01j5y5ghx5fg68d663j1fvy2x7`,
|
|
30
30
|
},
|
|
31
31
|
);
|
|
32
|
-
export enum
|
|
32
|
+
export enum AssetTemplateType {
|
|
33
33
|
STANDARD = 'STANDARD',
|
|
34
34
|
TIERED = 'TIERED',
|
|
35
35
|
}
|
|
@@ -51,7 +51,7 @@ export const IAsset = IBaseEntity.extend({
|
|
|
51
51
|
.lazy(() => IOffering)
|
|
52
52
|
.optional()
|
|
53
53
|
.nullable(), // Use z.lazy here
|
|
54
|
-
template: z.nativeEnum(
|
|
54
|
+
template: z.nativeEnum(AssetTemplateType),
|
|
55
55
|
tiers: z.array(z.number().positive()).nullable(),
|
|
56
56
|
enableBonus: z.boolean(),
|
|
57
57
|
});
|
|
@@ -102,16 +102,16 @@ const PostAssetBase = z.object({
|
|
|
102
102
|
.optional()
|
|
103
103
|
.openapi({ example: DurationType.DAY }),
|
|
104
104
|
template: z
|
|
105
|
-
.nativeEnum(
|
|
106
|
-
.default(
|
|
107
|
-
.openapi({ example:
|
|
105
|
+
.nativeEnum(AssetTemplateType)
|
|
106
|
+
.default(AssetTemplateType.STANDARD)
|
|
107
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
108
108
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
109
109
|
enableBonus: z.boolean().default(false).openapi({ example: false }),
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
const postAssetRefinement = (data: any, ctx: any) => {
|
|
112
|
+
export const postAssetRefinement = (data: any, ctx: any) => {
|
|
113
113
|
// If type is bond, yield and duration must be provided (cannot be null or undefined)
|
|
114
|
-
if (data.type === AssetType.BOND) {
|
|
114
|
+
if (data.assetType === AssetType.BOND || data.type === AssetType.BOND) {
|
|
115
115
|
if (data.yield === null || data.yield === undefined) {
|
|
116
116
|
ctx.addIssue({
|
|
117
117
|
path: ['yield'],
|
|
@@ -139,7 +139,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// If type is stock, yield and duration must be either null or undefined
|
|
142
|
-
if (data.type === AssetType.STOCK) {
|
|
142
|
+
if (data.assetType === AssetType.STOCK || data.type === AssetType.STOCK) {
|
|
143
143
|
if (data.yield !== null && data.yield !== undefined) {
|
|
144
144
|
ctx.addIssue({
|
|
145
145
|
path: ['yield'],
|
|
@@ -162,7 +162,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
if (data.template ===
|
|
165
|
+
if (data.template === AssetTemplateType.TIERED) {
|
|
166
166
|
if (data.tiers === null || data.tiers === undefined) {
|
|
167
167
|
ctx.addIssue({
|
|
168
168
|
path: ['tiers'],
|
|
@@ -172,7 +172,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
// If template is STANDARD, tiers must be null or undefined
|
|
175
|
-
if (data.template ===
|
|
175
|
+
if (data.template === AssetTemplateType.STANDARD) {
|
|
176
176
|
if (data.tiers !== null && data.tiers !== undefined) {
|
|
177
177
|
ctx.addIssue({
|
|
178
178
|
path: ['tiers'],
|
|
@@ -233,9 +233,9 @@ export const PutAsset = z.object({
|
|
|
233
233
|
.optional()
|
|
234
234
|
.openapi({ example: DurationType.DAY }),
|
|
235
235
|
template: z
|
|
236
|
-
.nativeEnum(
|
|
237
|
-
.default(
|
|
238
|
-
.openapi({ example:
|
|
236
|
+
.nativeEnum(AssetTemplateType)
|
|
237
|
+
.default(AssetTemplateType.STANDARD)
|
|
238
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
239
239
|
.nullable()
|
|
240
240
|
.optional(),
|
|
241
241
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
@@ -262,7 +262,7 @@ export const AssetsIncludeQuery = z.object({
|
|
|
262
262
|
assetsInclude.options.includes(include as any),
|
|
263
263
|
),
|
|
264
264
|
{
|
|
265
|
-
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',
|
|
265
|
+
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',')}`,
|
|
266
266
|
},
|
|
267
267
|
)
|
|
268
268
|
.openapi({
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(),
|
|
@@ -4,7 +4,7 @@ import { z } from 'zod';
|
|
|
4
4
|
import { TypeID } from 'typeid-js';
|
|
5
5
|
import { ErrorHttpStatusCode } from '@ts-rest/core';
|
|
6
6
|
import { TwoFactorMethod } from './sms.types';
|
|
7
|
-
import { normalizeShortDate } from '
|
|
7
|
+
import { normalizeShortDate } from '../helpers';
|
|
8
8
|
import { HttpStatus } from '@nestjs/common';
|
|
9
9
|
|
|
10
10
|
extendZodWithOpenApi(z);
|
|
@@ -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
|
-
|
|
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 {
|
|
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:
|
|
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:
|
|
141
|
+
email: EmailSchema.nullable().optional(),
|
|
141
142
|
idType: z
|
|
142
143
|
.nativeEnum(IDType)
|
|
143
144
|
.optional()
|