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 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('customer_id', 'static')
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('customer_id', 'static');
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?: number, limit?: number);
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: { customer_id: string, account_type: string }
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 an account
156
- const newAccount = await createAccount({
157
- customer_id: 'customer_123',
158
- account_type: 'static'
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
@@ -1,6 +1,16 @@
1
1
  interface CreateAccountRequest {
2
- customer_id: string;
3
- account_type: string;
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",
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
- customer_id: string;
6
- account_type: string;
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
+ });