Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions .github/workflows/postman.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,44 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
- run: curl -o- "https://dl-cli.pstmn.io/install/unix.sh" | sh

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "yarn"
node-version: 20
cache: "npm"

- run: curl -o- "https://dl-cli.pstmn.io/install/unix.sh" | sh
- name: Install dependencies
run: npm install

- name: Validate and sync
- name: Start server in background
run: |
npm run dev &
echo $! > pidfile
# Wait for server to be ready (port 3000)
for i in {1..20}; do
if nc -z localhost 3000; then
echo "Server is up!"
break
fi
echo "Waiting for server..."
sleep 2
done

- name: Validate Collection and Push to Cloud
env:
POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }}
run: |
postman login --with-api-key "$POSTMAN_API_KEY"
yarn install --frozen-lockfile
yarn start &
sleep 3
yarn test:api
postman collection run ./postman/collections/Book-API
postman workspace prepare
postman workspace push -y

- name: Stop server
if: always()
run: |
if [ -f pidfile ]; then
kill $(cat pidfile) || true
rm pidfile
fi
9 changes: 9 additions & 0 deletions .postman/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Use this workspace to collaborate
workspace:
id: 6c050d74-b1e6-4dfb-943e-2f7a2565e4e5

# All resources in the `postman/` folder are automatically registered in Local View.
# Point to additional files outside the `postman/` folder to register them individually. Example:
#localResources:
# collections:
# - ../tests/E2E Test Collection/
126 changes: 51 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,106 +1,82 @@
# 🌌 Intergalactic Bank API
# Book API

REST API for bank accounts and transactions with multi-currency support (COSMIC_COINS, GALAXY_GOLD, MOON_BUCKS).
Simple REST API for books – CRUD only, no auth. Good for demos and learning.

## Quick Start
## Quick start

```bash
npm install && npm run dev
curl http://localhost:3000/health
```

Default: **http://localhost:3000**. Generate API key: `GET /api/v1/auth`. Default admin key: `1234`.
Base URL: **http://localhost:3000**

## Endpoints

| Endpoint | Method | Auth | Description |
|----------|--------|------|-------------|
| `/health` | GET | No | Health check |
| `/api/v1/auth` | GET | No | Generate API key |
| `/api/v1/accounts` | GET, POST | Yes | List / create accounts |
| `/api/v1/accounts/:id` | GET, PUT, DELETE | Yes | Get / update / delete (soft) |
| `/api/v1/transactions` | GET, POST | Yes | List / transfer or deposit |
| `/api/v1/transactions/:id` | GET | Yes | Get transaction |
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/health` | Health check |
| GET | `/api/v1/books` | List all books |
| GET | `/api/v1/books/:id` | Get one book |
| POST | `/api/v1/books` | Create a book |
| PUT | `/api/v1/books/:id` | Update a book |
| DELETE | `/api/v1/books/:id` | Delete a book |

**Auth:** send `x-api-key: your-key` on all protected routes. **Rate limit:** 300 req/min per key.
No authentication required.

## Postman
## Examples

1. Import `OpenAPI/Bank API Reference Documentation.postman_collection.json`
2. Set `baseUrl` → `http://localhost:3000`, `apiKey` → `1234`

## Commands

| Command | Description |
|---------|-------------|
| `npm run dev` | Dev server (auto-reload) |
| `npm start` | Production |
| `npm test` | Run tests |
| `npm test -- --coverage` | Tests + coverage |
| `npm run lint` | Lint |

## Config (optional `.env`)

```
PORT=3000
ADMIN_API_KEY=1234
RATE_LIMIT_REQUESTS=300
RATE_LIMIT_WINDOW_MS=60000
```

## Project Layout

```
src/
├── server.js # Entry
├── database/db.js # In-memory store
├── models/ # Account, Transaction
├── routes/ # admin, accounts, transactions
└── middleware/ # auth, errorHandler, rateLimit
**List books**
```bash
curl http://localhost:3000/api/v1/books
```

## Important Behavior

- **Ownership** – Accounts are scoped to the API key that created them.
- **Soft delete** – Deleted accounts are flagged; history kept.
- **Editable** – Only `owner` and `accountType`; balance/currency change via transactions only.

## Example Requests

**Create account** `POST /api/v1/accounts`:
```json
{ "owner": "John Doe", "currency": "COSMIC_COINS", "balance": 1000, "accountType": "STANDARD" }
**Create book**
```bash
curl -X POST http://localhost:3000/api/v1/books \
-H "Content-Type: application/json" \
-d '{"title":"Dune","author":"Frank Herbert","year":1965}'
```

**Transfer** `POST /api/v1/transactions`:
```json
{ "fromAccountId": "123", "toAccountId": "456", "amount": 500, "currency": "COSMIC_COINS" }
**Update book** (PUT with full or partial fields)
```bash
curl -X PUT http://localhost:3000/api/v1/books/1 \
-H "Content-Type: application/json" \
-d '{"title":"Dune","author":"Frank Herbert","year":1965}'
```

**Deposit** – Use `"fromAccountId": "0"`.

## Error Format

```json
{ "error": { "name": "errorType", "message": "Description" } }
**Delete book**
```bash
curl -X DELETE http://localhost:3000/api/v1/books/1
```

Common codes: **400** validation, **401** auth, **403** forbidden, **404** not found, **429** rate limit, **500** server error.
## Book shape

## Sample Data (on startup)
- **title** (string, required)
- **author** (string, required)
- **year** (number, optional)

- Nova Newman (10k COSMIC_COINS), Gary Galaxy (237 COSMIC_COINS), Luna Starlight (5k GALAXY_GOLD) – all under admin key `1234`.
Responses use `{ book: {...} }` or `{ books: [...] }`. Errors use `{ error: { name, message } }`.

## Account Types & Currencies
## Commands

**Types:** STANDARD, PREMIUM, BUSINESS. **Currencies:** COSMIC_COINS, GALAXY_GOLD, MOON_BUCKS.
- `npm run dev` – dev server with reload
- `npm start` – production
- `npm test` – run tests
- `npm run lint` – lint

## Replacing Storage
## Project layout

Swap in a real DB by updating `src/database/db.js` with your driver and CRUD; the rest of the app stays the same.
```
src/
├── server.js
├── database/db.js # In-memory store
├── models/Book.js
├── routes/books.js
└── middleware/errorHandler.js
```

---
## Config

**More detail** → `CLAUDE.md` · **Tests** → `npm test`
Optional `.env`: `PORT=3000`

License: ISC
5 changes: 5 additions & 0 deletions postman/collections/Book-API/.resources/definition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$kind: collection
name: Book API
variables:
- key: baseUrl
value: 'http://localhost:3000'
16 changes: 16 additions & 0 deletions postman/collections/Book-API/Books/create-book.request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
$kind: http-request
name: Create Book
method: POST
url: '{{baseUrl}}/api/v1/books'
order: 3000
headers:
- key: Content-Type
value: application/json
body:
type: json
content: |-
{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"year": 1925
}
8 changes: 8 additions & 0 deletions postman/collections/Book-API/Books/delete-book.request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$kind: http-request
name: Delete Book
method: DELETE
url: '{{baseUrl}}/api/v1/books/:id'
order: 5000
pathVariables:
- key: id
value: '1'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
$kind: http-request
name: 'Get Book by ID'
method: GET
url: '{{baseUrl}}/api/v1/books/:id'
order: 2000
pathVariables:
- key: id
value: '1'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$kind: http-request
name: List All Books
method: GET
url: '{{baseUrl}}/api/v1/books'
order: 1000
19 changes: 19 additions & 0 deletions postman/collections/Book-API/Books/update-book.request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
$kind: http-request
name: Update Book
method: PUT
url: '{{baseUrl}}/api/v1/books/:id'
order: 4000
pathVariables:
- key: id
value: '1'
headers:
- key: Content-Type
value: application/json
body:
type: json
content: |-
{
"title": "The Great Gatsby (Updated)",
"author": "F. Scott Fitzgerald",
"year": 1925
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$kind: http-request
name: Health Check
method: GET
url: '{{baseUrl}}/health'
order: 2000
5 changes: 5 additions & 0 deletions postman/collections/Book-API/General/root.request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$kind: http-request
name: Root (Welcome)
method: GET
url: '{{baseUrl}}/'
order: 1000
2 changes: 2 additions & 0 deletions postman/globals/workspace.globals.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Globals
values: []
Loading
Loading