+240
-106
README.md
+240
-106
README.md
···
1
1
# BankingMockAPI
2
2
3
-
## Getting Started
3
+
A simple mock banking API for testing and prototyping.
4
+
Provides authentication, accounts, cards, and transactions endpoints backed by a seeded SQLite database.
5
+
Includes a React Native demo app powered by [Expo](https://expo.dev/).
6
+
7
+
---
8
+
9
+
## 🚀 Getting Started
4
10
5
11
### Prerequisites
6
12
7
-
- [Node.js](https://nodejs.org/) (v18 or higher)
13
+
- [Node.js](https://nodejs.org/) **v18 or higher**
8
14
- [Docker](https://www.docker.com/) (optional, for containerized setup)
15
+
- [Expo CLI](https://docs.expo.dev/get-started/installation/) (for running the React Native app):
16
+
17
+
```bash
18
+
npm install -g expo
19
+
```
20
+
21
+
---
9
22
10
23
### Installation
11
24
12
-
1. Clone the repository:
25
+
```bash
26
+
git clone git@tangled.sh:mokkenstorm.dev/react-native-demo
27
+
cd react-native-demo
28
+
```
29
+
30
+
---
31
+
32
+
### Running the Server
33
+
34
+
#### Run directly with Node.js
13
35
14
36
```bash
15
-
git clone <repo-url>
16
-
cd BankingMockAPI
37
+
cd server && npx ts-node src/server.ts
17
38
```
18
39
19
-
2. Install dependencies:
40
+
The server will be available at:
41
+
👉 `http://localhost:3001`
20
42
21
-
```bash
22
-
npm install
23
-
```
43
+
#### Run with Docker Compose
24
44
25
-
### Running the Server
45
+
```bash
46
+
docker compose up --build
47
+
```
26
48
27
-
#### With Node.js
49
+
Stop the service:
28
50
29
51
```bash
30
-
node server.js
52
+
docker compose down
31
53
```
32
54
33
-
The server will start on [http://localhost:3001](http://localhost:3001) by default.
55
+
Server base URL: `http://localhost:3001`
56
+
57
+
---
58
+
59
+
### 🎨 Running the App
34
60
35
-
#### With Docker
61
+
The repository includes a React Native demo app that connects to the API.
62
+
63
+
To generate client code from the OpenAPI spec and start the app with Expo:
36
64
37
65
```bash
38
-
docker build -t banking-mock-api .
39
-
docker run --name banking-mock-api -d -p 3001:3001 banking-mock-api
66
+
cd app
67
+
npm run generate
68
+
npm run ios
40
69
```
41
70
42
-
Same as mentioned aboe the api will be available at on [http://localhost:3001](http://localhost:3001)
71
+
You can replace `npm run ios` with:
72
+
73
+
- `npm run android` — to run on Android
74
+
- `npm run web` — to run in a web browser
75
+
76
+
⚠️ **Note:** The app requires and **API server** (see instructions above).
77
+
Without the server running on `http://localhost:3001`, login and data
78
+
fetches will fail by default. If you need a different backend port/url
79
+
and set the `SERVER_URL` environment variable before generating the
80
+
client code, and optionally configure the `compose.yaml` for a different port.
81
+
82
+
Expo will guide you through launching the app on your chosen platform.
83
+
84
+
---
85
+
86
+
## 📚 API Documentation
87
+
88
+
Interactive documentation and the raw OpenAPI specification are exposed by the server:
89
+
90
+
- **Swagger UI:**
91
+
[http://localhost:3001](http://localhost:3001)
92
+
A browsable interface to test and explore the API endpoints.
93
+
94
+
- **OpenAPI Spec (YAML):**
95
+
[http://localhost:3001/openapi.yaml](http://localhost:3001/openapi.yaml)
96
+
The raw machine-readable specification, suitable for client generation.
97
+
98
+
---
43
99
44
-
Use following commands to stop or start the container:
100
+
## 📖 API Endpoints
101
+
102
+
All protected routes require a **JWT** in the `Authorization` header:
45
103
46
104
```bash
47
-
docker container stop banking-mock-api
48
-
docker container start banking-mock-api
105
+
Authorization: Bearer <JWT>
49
106
```
50
107
51
-
## API Endpoints
108
+
### 🔑 Authentication
52
109
53
-
### Authentication
110
+
#### `POST /login`
54
111
55
-
#### `POST /login`
112
+
Authenticate and receive a token pair.
113
+
114
+
**Request Body**
56
115
57
-
Authenticate user and receive JWT and refresh token.
116
+
```json
117
+
{
118
+
"username": "test@test.test",
119
+
"password": "password@123"
120
+
}
121
+
```
58
122
59
-
- **Body:**
123
+
Response 200\*\*
60
124
61
-
```json
62
-
{
63
-
"username": "test@test.test",
64
-
"password": "password@123"
65
-
}
66
-
```
67
-
- **Response:**
68
-
```json
69
-
{
70
-
"token": "<JWT>",
71
-
"refreshToken": "<refresh_token>"
125
+
```json
126
+
{
127
+
"accessToken": "<JWT>",
128
+
"refreshToken": "<refresh_JWT>",
129
+
"expires": "2024-06-01T10:05:00Z"
130
+
}
131
+
```
132
+
133
+
Response 401\*\*
134
+
135
+
```json
136
+
{
137
+
"errors": [],
138
+
"properties": {
139
+
"username": { "errors": ["Invalid email address"] },
140
+
"password": {
141
+
"errors": ["Too small: expected string to have >=8 characters"]
142
+
}
72
143
}
73
-
```
144
+
}
145
+
```
146
+
147
+
---
74
148
75
149
#### `POST /refresh-token`
76
150
77
-
Get a new JWT using a refresh token.
151
+
Exchange a refresh token for a new pair.
152
+
153
+
**Request Body**
154
+
155
+
```json
156
+
{
157
+
"refreshToken": "<refresh_JWT>"
158
+
}
159
+
```
160
+
161
+
Response 200\*\*
78
162
79
-
- **Body:**
80
-
```json
81
-
{
82
-
"refreshToken": "<refresh_token>"
83
-
}
84
-
```
85
-
- **Response:**
86
-
```json
163
+
```json
164
+
{
165
+
"accessToken": "<new_JWT>",
166
+
"refreshToken": "<new_refresh_JWT>"
167
+
}
168
+
```
169
+
170
+
---
171
+
172
+
### 👤 Me
173
+
174
+
#### `GET /me`
175
+
176
+
Returns the authenticated user.
177
+
178
+
Response 200\*\*
179
+
180
+
```json
181
+
{
182
+
"id": 2,
183
+
"username": "nmokkenstorm",
184
+
"fullname": "Niels Mokkenstorm",
185
+
"created": "2024-06-01T10:00:00Z"
186
+
}
187
+
```
188
+
189
+
---
190
+
191
+
### 🏦 Accounts
192
+
193
+
#### `GET /accounts`
194
+
195
+
List accounts for the authenticated user.
196
+
197
+
Response 200\*\*
198
+
199
+
```json
200
+
[
87
201
{
88
-
"token": "<new_JWT>",
89
-
"refreshToken": "<new_refresh_token>"
202
+
"id": 1,
203
+
"user_id": 1,
204
+
"iban": "NL00BANK0123456789",
205
+
"name": "Checking",
206
+
"balance": 1680.16
90
207
}
91
-
```
208
+
]
209
+
```
210
+
211
+
#### `GET /accounts/{accountId}`
92
212
93
-
### Accounts
213
+
Retrieve a single account by ID.
94
214
95
-
#### `GET /accounts`
215
+
Response 200\*\*
96
216
97
-
Get all accounts for the authenticated user.
217
+
```json
218
+
{
219
+
"id": 1,
220
+
"user_id": 1,
221
+
"iban": "NL00BANK0123456789",
222
+
"name": "Checking",
223
+
"balance": 1680.16
224
+
}
225
+
```
98
226
99
-
- **Headers:**
100
-
- `Authorization: Bearer <JWT>`
101
-
- **Response:**
102
-
```json
103
-
[
104
-
{
105
-
"id": 1,
106
-
"user_id": 1,
107
-
"name": "Checking",
108
-
"balance": 1500.5
109
-
},
110
-
...
111
-
]
112
-
```
227
+
---
113
228
114
-
### Cards
229
+
### 💳 Cards
115
230
116
231
#### `GET /cards`
117
232
118
-
Get all cards for the authenticated user.
233
+
List stored cards (**demo only**: returns full PAN and CVV).
234
+
235
+
Response 200\*\*
236
+
237
+
```json
238
+
[
239
+
{
240
+
"id": 1,
241
+
"user_id": 1,
242
+
"number": "4111111111111111",
243
+
"expiry": "12/26",
244
+
"cvv": "123"
245
+
}
246
+
]
247
+
```
119
248
120
-
- **Headers:**
121
-
- `Authorization: Bearer <JWT>`
122
-
- **Response:**
123
-
```json
124
-
[
125
-
{
126
-
"id": 1,
127
-
"user_id": 1,
128
-
"number": "4111111111111111",
129
-
"expiry": "12/26",
130
-
"cvv": "123"
131
-
},
132
-
...
133
-
]
134
-
```
249
+
---
135
250
136
-
### Transactions
251
+
### 🧾 Transactions
137
252
138
253
#### `GET /transactions`
139
254
140
-
Get transactions for the authenticated user, with search, sort, and pagination.
255
+
Search/sort/paginate transactions. Query params: `search`, `sort` (default `date`), `order` (`asc|desc`, default `desc`), `page` (default `1`), `limit` (default `25`), `accountId`, `type`.
141
256
142
-
- **Headers:**
143
-
- `Authorization: Bearer <JWT>`
144
-
- **Query Parameters:**
145
-
- `search` (optional): Search by description or type
146
-
- `sort` (optional): Field to sort by (default: `date`)
147
-
- `order` (optional): `asc` or `desc` (default: `desc`)
148
-
- `page` (optional): Page number (default: `1`)
149
-
- `limit` (optional): Items per page (default: `10`)
150
-
- **Response:**
151
-
```json
152
-
[
257
+
Response 200\*\*
258
+
259
+
```json
260
+
{
261
+
"data": [
153
262
{
154
263
"id": 1,
155
-
"user_id": 1,
156
-
"account_id": 1,
264
+
"userId": 1,
265
+
"accountId": 1,
157
266
"amount": -50.25,
158
267
"type": "debit",
159
268
"description": "Grocery Store",
160
269
"date": "2024-06-01T10:00:00Z"
161
-
},
162
-
...
163
-
]
164
-
```
270
+
}
271
+
],
272
+
"meta": {
273
+
"page": 1,
274
+
"limit": 25,
275
+
"hasMore": false,
276
+
"total": 1
277
+
}
278
+
}
279
+
```
280
+
281
+
---
282
+
283
+
#### `GET /transaction-types`
284
+
285
+
Aggregate transaction types.
286
+
287
+
Response 200\*\*
288
+
289
+
```json
290
+
[
291
+
{ "name": "debit", "count": 12 },
292
+
{ "name": "credit", "count": 5 }
293
+
]
294
+
```
295
+
296
+
---
165
297
166
-
## Default Test User
298
+
## 👤 Default Test User
167
299
168
300
- **Username:** `test@test.test`
169
301
- **Password:** `password@123`
170
302
171
-
## Database
303
+
---
172
304
173
-
- The SQLite database is used.
174
-
- The database is reset and seeded with test data every time the server starts.
305
+
## 🗄️ Database
306
+
307
+
- Uses **SQLite**.
308
+
- The database is reset and seeded with test data on every server start.
+1
-1
app/openapi-ts.config.ts
+1
-1
app/openapi-ts.config.ts