# Quick API Serve any JSON file as a REST API — filtering, sorting, and pagination included. Drop a file in `data/`, start the server, your API is ready. --- ## Why this exists During development, you often need to consume JSON data through an HTTP API before the real backend is ready — or simply to inspect, filter, and paginate a dataset quickly without writing any server code. Quick API was built out of that need. Drop a JSON file in a folder, start the server, and you immediately have a filterable, sortable, paginated REST API on top of your data. No configuration required to get started. It can also serve as a starting point for a more complete Express API, since the project is already structured with routes, controllers, services, and middleware. --- ## Getting started ```bash npm install npm run dev ``` The server starts on `http://localhost:3000`. --- ## Adding a resource Place a JSON file in the `data/` directory: ``` data/ users.json -> GET /users products.json -> GET /products orders.json -> GET /orders ``` Restart the server. The route is created automatically. The JSON file must be an **array of objects**: ```json [ { "id": 1, "name": "Half-Life 3", "status": "rumored", "studio": "Valve", "genre": "fps", "released": false, "year": null }, { "id": 2, "name": "Portal 3", "status": "rumored", "studio": "Valve", "genre": "puzzle", "released": false, "year": null }, { "id": 3, "name": "Silksong", "status": "released", "studio": "Team Cherry", "genre": "metroidvania", "released": true, "year": 2025 }, { "id": 4, "name": "Elder Scrolls VI", "status": "rumored", "studio": "Bethesda", "genre": "rpg", "released": false, "year": null } ] ``` --- ## Available routes ### System routes | Route | Description | |-------------------------|---------------------------------------------------| | `GET /` | Full documentation and list of loaded resources | | `GET /health` | Health check (status, uptime) | | `GET /resources` | Lists all available resources | | `GET /schema/:resource` | Inferred schema (unique field names) of a resource| ### Dynamic resource routes | Route | Description | |-----------------------|---------------------------------------------------| | `GET /:resource` | All records (query param filtering supported) | | `GET /:resource/:id` | Single record by `id` | | `POST /:resource` | Replace the in-memory dataset (not persisted) | --- ## Query params ### Field filtering ``` GET /users?role=admin # contains (string) or equals (number) GET /users?role_ne=admin # not equal GET /users?age_gte=18 # greater than or equal GET /users?age_lte=65 # less than or equal GET /users?age_gt=17 # strictly greater than GET /users?age_lt=66 # strictly less than ``` Filters are combinable: ``` GET /users?role=admin&active=true ``` ### Full-text search ``` GET /users?_q=alice # searches "alice" across all fields ``` ### Sorting ``` GET /users?_sort=name GET /users?_sort=name&_order=desc ``` Dot notation is supported for nested fields: ``` GET /users?_sort=address.city ``` ### Pagination ``` GET /users?_limit=10 GET /users?_limit=10&_page=2 ``` Pagination metadata is available in the response headers: ``` X-Total-Count: 42 X-Page: 2 X-Limit: 10 ``` ### Field projection ``` GET /users?_fields=id,name,role ``` --- ## Configuration All environment variables are optional: | Variable | Default | Description | |---------------|----------|------------------------------------------------| | `PORT` | `3000` | Server listening port | | `DATA_DIR` | `./data` | Path to the JSON files directory | | `BODY_LIMIT` | `10mb` | Maximum POST request body size | | `LOG_ENABLED` | `true` | Enable HTTP request logging in the console | ```bash PORT=8080 DATA_DIR=./my-data npm run dev ``` All defaults are centralized in `src/config/config.js`. --- ## Project structure ``` quick-api/ ├── data/ # JSON files -> automatic routes │ └── users.json # Example file ├── src/ │ ├── index.js # Entry point — bootstrap │ ├── app.js # Express factory (middleware + routes) │ ├── config/ │ │ └── config.js # Centralized configuration │ ├── controllers/ │ │ ├── resource.controller.js # getAll / getById / replaceAll │ │ └── system.controller.js # getDocs / getHealth / getResources / getSchema │ ├── middleware/ │ │ ├── requestLogger.middleware.js # Colored HTTP logs with response time │ │ ├── resourceGuard.middleware.js # 404 if resource does not exist │ │ ├── errorHandler.middleware.js # Global error handler │ │ └── notFoundHandler.middleware.js # Catch-all 404 │ ├── routes/ │ │ ├── resource.routes.js # Dynamic routes /:resource │ │ └── system.routes.js # Fixed routes (/, /health, /schema...) │ ├── services/ │ │ ├── datasetRegistry.service.js # In-memory dataset store │ │ └── filter.service.js # Filtering, sorting, pagination engine │ └── utils/ │ └── response.utils.js # HTTP response helpers └── package.json ``` --- ## Adding a custom endpoint 1. Create your controller in `src/controllers/` 2. Create your route file in `src/routes/` 3. Mount it in `src/app.js` **before** `resourceRouter` ```js // src/app.js const myRouter = require('./routes/my.routes'); app.use('/custom', myRouter); // must come before resourceRouter ``` --- ## Notes - Data is loaded **into memory** at startup. A `POST /:resource` updates the in-memory dataset but **does not write back** to the JSON file on disk. - Restarting the server reloads files from disk. - The `maxLimit` value in `config.js` caps the `_limit` param to avoid oversized responses (default: 500).