carbon-baas-sdk 1.0.3 → 1.0.4
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 +44 -13
- package/dist/accounts.d.ts +12 -2
- package/package.json +1 -1
- package/src/accounts.ts +15 -2
- package/tests/accounts.test.ts +196 -0
package/README.md
CHANGED
|
@@ -22,8 +22,12 @@ const carbon = require('carbon-baas-sdk');
|
|
|
22
22
|
|
|
23
23
|
carbon.initialize('your_api_key_here', 'sandbox');
|
|
24
24
|
|
|
25
|
-
// Create an account
|
|
26
|
-
carbon.createAccount(
|
|
25
|
+
// Create an account for a third-party customer
|
|
26
|
+
carbon.createAccount({
|
|
27
|
+
account_type: 'static',
|
|
28
|
+
third_party: true,
|
|
29
|
+
customer_id: 'customer_123'
|
|
30
|
+
})
|
|
27
31
|
.then(response => console.log(response))
|
|
28
32
|
.catch(error => console.error(error));
|
|
29
33
|
|
|
@@ -31,25 +35,34 @@ carbon.createAccount('customer_id', 'static')
|
|
|
31
35
|
carbon.fetchAccount('account_number')
|
|
32
36
|
.then(response => console.log(response))
|
|
33
37
|
.catch(error => console.error(error));
|
|
38
|
+
|
|
39
|
+
// Fetch all accounts with pagination
|
|
40
|
+
carbon.fetchAccounts(1, 10) // page 1, limit 10
|
|
41
|
+
.then(response => console.log(response))
|
|
42
|
+
.catch(error => console.error(error));
|
|
34
43
|
```
|
|
35
44
|
|
|
36
45
|
### ES Modules
|
|
37
46
|
|
|
38
47
|
```javascript
|
|
39
|
-
import { initialize, createAccount, fetchAccount } from 'carbon-baas-sdk';
|
|
48
|
+
import { initialize, createAccount, fetchAccount, fetchAccounts } from 'carbon-baas-sdk';
|
|
40
49
|
|
|
41
50
|
initialize('your_api_key_here', 'sandbox');
|
|
42
51
|
|
|
43
|
-
// Create an account
|
|
44
|
-
const account = await createAccount(
|
|
52
|
+
// Create an account for a third-party customer
|
|
53
|
+
const account = await createAccount({
|
|
54
|
+
account_type: 'static',
|
|
55
|
+
third_party: true,
|
|
56
|
+
customer_id: 'customer_123'
|
|
57
|
+
});
|
|
45
58
|
console.log(account);
|
|
46
59
|
|
|
47
60
|
// Fetch an account
|
|
48
61
|
const accountDetails = await fetchAccount('account_number');
|
|
49
62
|
console.log(accountDetails);
|
|
50
63
|
|
|
51
|
-
//Fetch accounts
|
|
52
|
-
const accounts = await fetchAccounts(page
|
|
64
|
+
// Fetch accounts
|
|
65
|
+
const accounts = await fetchAccounts(1, 10); // page 1, limit 10
|
|
53
66
|
console.log(accounts);
|
|
54
67
|
```
|
|
55
68
|
|
|
@@ -69,9 +82,16 @@ initialize(apiKey: string, mode: 'live' | 'sandbox')
|
|
|
69
82
|
### Accounts
|
|
70
83
|
```javascript
|
|
71
84
|
createAccount(accountData: CreateAccountRequest)
|
|
72
|
-
// accountData: {
|
|
85
|
+
// accountData: {
|
|
86
|
+
// account_type: "static", // Must always be "static"
|
|
87
|
+
// third_party?: boolean, // true for third-party customer, false for own business sub-account (defaults to true)
|
|
88
|
+
// customer_id?: string, // Required if third_party is true
|
|
89
|
+
// account_name?: string // Required if third_party is false
|
|
90
|
+
// }
|
|
73
91
|
|
|
74
92
|
fetchAccount(accountNumber: string)
|
|
93
|
+
|
|
94
|
+
fetchAccounts(page?: number, limit?: number)
|
|
75
95
|
```
|
|
76
96
|
|
|
77
97
|
### Customers
|
|
@@ -150,16 +170,27 @@ resendWebhookEvent(eventId: string)
|
|
|
150
170
|
|
|
151
171
|
### Managing Accounts
|
|
152
172
|
```javascript
|
|
153
|
-
import { createAccount, fetchAccount } from 'carbon-baas-sdk';
|
|
173
|
+
import { createAccount, fetchAccount, fetchAccounts } from 'carbon-baas-sdk';
|
|
174
|
+
|
|
175
|
+
// Create an account for a third-party customer
|
|
176
|
+
const newCustomerAccount = await createAccount({
|
|
177
|
+
account_type: 'static',
|
|
178
|
+
third_party: true,
|
|
179
|
+
customer_id: 'customer_123'
|
|
180
|
+
});
|
|
154
181
|
|
|
155
|
-
// Create
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
182
|
+
// Create a sub-account for your own business (for collections)
|
|
183
|
+
const newSubAccount = await createAccount({
|
|
184
|
+
account_type: 'static',
|
|
185
|
+
third_party: false,
|
|
186
|
+
account_name: 'Collections'
|
|
159
187
|
});
|
|
160
188
|
|
|
161
189
|
// Fetch account details
|
|
162
190
|
const accountDetails = await fetchAccount('1234567890');
|
|
191
|
+
|
|
192
|
+
// Fetch all accounts (with pagination)
|
|
193
|
+
const accounts = await fetchAccounts(1, 20); // page 1, 20 items per page
|
|
163
194
|
```
|
|
164
195
|
|
|
165
196
|
### Managing Customers
|
package/dist/accounts.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
interface CreateAccountRequest {
|
|
2
|
-
|
|
3
|
-
account_type:
|
|
2
|
+
/** Must always be "static". */
|
|
3
|
+
account_type: "static";
|
|
4
|
+
/**
|
|
5
|
+
* Set to true when creating an account for a third-party customer (business use).
|
|
6
|
+
* Set to false when creating a sub-account for your own business (collections).
|
|
7
|
+
* Defaults to true if not provided.
|
|
8
|
+
*/
|
|
9
|
+
third_party?: boolean;
|
|
10
|
+
/** Required if third_party is true. The customer to associate the account with. */
|
|
11
|
+
customer_id?: string;
|
|
12
|
+
/** Required if third_party is false. The sub-account name (e.g."SUBACCOUNT" -> BUSINESS NAME - SUBACCOUNT). */
|
|
13
|
+
account_name?: string;
|
|
4
14
|
}
|
|
5
15
|
export declare function createAccount(accountData: CreateAccountRequest): Promise<any>;
|
|
6
16
|
export declare function fetchAccount(accountNumber: string): Promise<any>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "carbon-baas-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "## Welcome to our API Developer Documentation\n\nCarbon aims to unlock the full potential of your business with a feature-rich account designed for growth.\n\n## Integrations\n\nWe aim to provide our APIs for developers and businesses to offer financial services to their existing customer base through REST APIs without doing the heavy lifting. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.\n\n### Authentication\n\n`Authorization : API Key`\n\nHeader \n`x-carbon-key : value`\n\n`x-carbon-key` can be generated via developer page on Carbon Business\n\n| Enviroment | URL |\n| --- | --- |\n| Live | |\n| Sandbox | [https://carbonapistagingsecure.getcarbon.co/baas/api](https://carbonapistagingsecure.getcarbon.co/baas/api) |\n\n### **Handling Errors**\n\nWe use the conventional HTTP response codes to indicate the success or failure of an API request. \nCodes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, etc.). Codes in the 5xx range indicate an error with our servers.\n\n| Error | Description |\n| --- | --- |\n| 400 - Bad Request | The request was unacceptable, often due to missing a required parameter. |\n| 401 - Unauthorized | Not a valid API key was provided. |\n| 402 - Request Failed | The parameters were valid but the request failed. |\n| 403 - Forbidden | The API key doesn't have permission to perform the request. |\n| 404 - Not Found | The requested resource doesn't exist. |\n| 429 - Too Many Requests | Too many requests hit the API |\n| 500, 502, 503, 504 - Server Errors | System Error |",
|
|
5
5
|
"author":"Gabriel Ajenifuja",
|
|
6
6
|
"main": "dist/index.cjs.js",
|
package/src/accounts.ts
CHANGED
|
@@ -2,8 +2,21 @@ import { getInstance } from './index';
|
|
|
2
2
|
import { handleError } from './util';
|
|
3
3
|
|
|
4
4
|
interface CreateAccountRequest {
|
|
5
|
-
|
|
6
|
-
account_type:
|
|
5
|
+
/** Must always be "static". */
|
|
6
|
+
account_type: "static";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set to true when creating an account for a third-party customer (business use).
|
|
10
|
+
* Set to false when creating a sub-account for your own business (collections).
|
|
11
|
+
* Defaults to true if not provided.
|
|
12
|
+
*/
|
|
13
|
+
third_party?: boolean;
|
|
14
|
+
|
|
15
|
+
/** Required if third_party is true. The customer to associate the account with. */
|
|
16
|
+
customer_id?: string;
|
|
17
|
+
|
|
18
|
+
/** Required if third_party is false. The sub-account name (e.g."SUBACCOUNT" -> BUSINESS NAME - SUBACCOUNT). */
|
|
19
|
+
account_name?: string;
|
|
7
20
|
}
|
|
8
21
|
|
|
9
22
|
export async function createAccount(accountData: CreateAccountRequest) {
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { createAccount, fetchAccount, fetchAccounts } from '../src/accounts';
|
|
2
|
+
import { beforeEach, describe, expect, it, jest } from '@jest/globals';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
// Mock the getInstance function instead of axios directly
|
|
6
|
+
jest.mock('../src/index', () => ({
|
|
7
|
+
getInstance: () => axios,
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
// Now mock axios
|
|
11
|
+
jest.mock('axios');
|
|
12
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
|
13
|
+
|
|
14
|
+
describe('Account API', () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
// Clear all mocks before each test
|
|
17
|
+
jest.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('createAccount', () => {
|
|
21
|
+
it('should create an account for a third-party customer', async () => {
|
|
22
|
+
const accountData = {
|
|
23
|
+
account_type: "static" as const,
|
|
24
|
+
third_party: true,
|
|
25
|
+
customer_id: '1732ca47-42b2-4990-a65d-c369e934eed3'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const responseData = {
|
|
29
|
+
status: 'success',
|
|
30
|
+
data: {
|
|
31
|
+
account_number: '1234567890',
|
|
32
|
+
account_name: 'John Doe',
|
|
33
|
+
...accountData
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
mockedAxios.post.mockResolvedValueOnce({ data: responseData });
|
|
38
|
+
|
|
39
|
+
const result = await createAccount(accountData);
|
|
40
|
+
expect(result).toEqual(responseData);
|
|
41
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('/v1/accounts', accountData);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should create a sub-account for the business itself', async () => {
|
|
45
|
+
const accountData = {
|
|
46
|
+
account_type: "static" as const,
|
|
47
|
+
third_party: false,
|
|
48
|
+
account_name: 'Collections'
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const responseData = {
|
|
52
|
+
status: 'success',
|
|
53
|
+
data: {
|
|
54
|
+
account_number: '0987654321',
|
|
55
|
+
business_name: 'BUSINESS NAME',
|
|
56
|
+
...accountData
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
mockedAxios.post.mockResolvedValueOnce({ data: responseData });
|
|
61
|
+
|
|
62
|
+
const result = await createAccount(accountData);
|
|
63
|
+
expect(result).toEqual(responseData);
|
|
64
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('/v1/accounts', accountData);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should handle API errors during account creation', async () => {
|
|
68
|
+
const accountData = {
|
|
69
|
+
account_type: "static" as const,
|
|
70
|
+
third_party: true,
|
|
71
|
+
// Missing customer_id which is required when third_party is true
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const errorResponse = {
|
|
75
|
+
response: {
|
|
76
|
+
data: {
|
|
77
|
+
status: 'failed',
|
|
78
|
+
message: 'bad request',
|
|
79
|
+
errors: [
|
|
80
|
+
{ msg: 'customer_id is required when third_party is true', param: 'customer_id' }
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
mockedAxios.post.mockRejectedValueOnce(errorResponse);
|
|
87
|
+
|
|
88
|
+
const result = await createAccount(accountData);
|
|
89
|
+
expect(result).toEqual(errorResponse.response.data);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('fetchAccount', () => {
|
|
94
|
+
it('should fetch a single account by account number', async () => {
|
|
95
|
+
const accountNumber = '1234567890';
|
|
96
|
+
const responseData = {
|
|
97
|
+
status: 'success',
|
|
98
|
+
data: {
|
|
99
|
+
account_number: accountNumber,
|
|
100
|
+
account_name: 'John Doe',
|
|
101
|
+
account_type: 'static',
|
|
102
|
+
balance: '10000.00'
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
mockedAxios.get.mockResolvedValueOnce({ data: responseData });
|
|
107
|
+
|
|
108
|
+
const result = await fetchAccount(accountNumber);
|
|
109
|
+
expect(result).toEqual(responseData);
|
|
110
|
+
expect(mockedAxios.get).toHaveBeenCalledWith(`/v1/accounts/${accountNumber}`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should handle API errors when fetching an account', async () => {
|
|
114
|
+
const accountNumber = 'invalid-account';
|
|
115
|
+
const errorResponse = {
|
|
116
|
+
response: {
|
|
117
|
+
data: {
|
|
118
|
+
status: 'failed',
|
|
119
|
+
message: 'Account not found',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
mockedAxios.get.mockRejectedValueOnce(errorResponse);
|
|
125
|
+
|
|
126
|
+
const result = await fetchAccount(accountNumber);
|
|
127
|
+
expect(result).toEqual(errorResponse.response.data);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('fetchAccounts', () => {
|
|
132
|
+
it('should fetch all accounts with default pagination', async () => {
|
|
133
|
+
const responseData = {
|
|
134
|
+
status: 'success',
|
|
135
|
+
data: {
|
|
136
|
+
accounts: [
|
|
137
|
+
{ account_number: '1234567890', account_name: 'John Doe', account_type: 'static' },
|
|
138
|
+
{ account_number: '0987654321', account_name: 'Jane Smith', account_type: 'static' }
|
|
139
|
+
],
|
|
140
|
+
pagination: {
|
|
141
|
+
total: 2,
|
|
142
|
+
page: 1,
|
|
143
|
+
limit: 10
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
mockedAxios.get.mockResolvedValueOnce({ data: responseData });
|
|
149
|
+
|
|
150
|
+
const result = await fetchAccounts();
|
|
151
|
+
expect(result).toEqual(responseData);
|
|
152
|
+
expect(mockedAxios.get).toHaveBeenCalledWith('/v1/accounts', { params: { page: 1, limit: 10 } });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should fetch accounts with custom pagination', async () => {
|
|
156
|
+
const page = 2;
|
|
157
|
+
const limit = 5;
|
|
158
|
+
const responseData = {
|
|
159
|
+
status: 'success',
|
|
160
|
+
data: {
|
|
161
|
+
accounts: [
|
|
162
|
+
{ account_number: '1112223334', account_name: 'Alice Johnson', account_type: 'static' },
|
|
163
|
+
{ account_number: '5556667778', account_name: 'Bob Miller', account_type: 'static' }
|
|
164
|
+
],
|
|
165
|
+
pagination: {
|
|
166
|
+
total: 7,
|
|
167
|
+
page: page,
|
|
168
|
+
limit: limit
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
mockedAxios.get.mockResolvedValueOnce({ data: responseData });
|
|
174
|
+
|
|
175
|
+
const result = await fetchAccounts(page, limit);
|
|
176
|
+
expect(result).toEqual(responseData);
|
|
177
|
+
expect(mockedAxios.get).toHaveBeenCalledWith('/v1/accounts', { params: { page, limit } });
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should handle API errors when fetching accounts', async () => {
|
|
181
|
+
const errorResponse = {
|
|
182
|
+
response: {
|
|
183
|
+
data: {
|
|
184
|
+
status: 'failed',
|
|
185
|
+
message: 'Unauthorized access',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
mockedAxios.get.mockRejectedValueOnce(errorResponse);
|
|
191
|
+
|
|
192
|
+
const result = await fetchAccounts();
|
|
193
|
+
expect(result).toEqual(errorResponse.response.data);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|