doc: edit readme

Changed files
+241 -107
app
+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 import { defineConfig } from "@hey-api/openapi-ts"; 2 2 3 3 export default defineConfig({ 4 - input: "http://localhost:3001/openapi.yaml", 4 + input: process.env.SERVER_URL || "http://localhost:3001/openapi.yaml", 5 5 output: "generated", 6 6 plugins: [ 7 7 "@tanstack/react-query",