{"id":16254161,"url":"https://github.com/sumn2u/hai-server","last_synced_at":"2025-07-29T12:13:10.642Z","repository":{"id":38808888,"uuid":"169891439","full_name":"sumn2u/hai-server","owner":"sumn2u","description":"Build JSON API with authentication in just minutes.","archived":false,"fork":false,"pushed_at":"2024-12-05T23:14:33.000Z","size":1315,"stargazers_count":16,"open_issues_count":11,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-27T09:30:38.165Z","etag":null,"topics":["api-development","authentication","authorization","backend-development","javascript","json-api","json-server","jwt-authentication","mocking-server","nodejs","rest-api"],"latest_commit_sha":null,"homepage":"https://medium.com/@sumn2u/build-a-rest-api-s-from-json-with-authentication-2ee4d21a64a6","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sumn2u.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-02-09T17:14:16.000Z","updated_at":"2024-12-02T12:58:52.000Z","dependencies_parsed_at":"2024-03-31T15:26:42.423Z","dependency_job_id":"b40b67fe-9d68-40ea-b5ba-b7d944381656","html_url":"https://github.com/sumn2u/hai-server","commit_stats":{"total_commits":26,"total_committers":3,"mean_commits":8.666666666666666,"dds":0.3076923076923077,"last_synced_commit":"79003f8d8940dcea34a5fc5e4a0b2ea377dcec4d"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumn2u%2Fhai-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumn2u%2Fhai-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumn2u%2Fhai-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumn2u%2Fhai-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sumn2u","download_url":"https://codeload.github.com/sumn2u/hai-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243815561,"owners_count":20352189,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-development","authentication","authorization","backend-development","javascript","json-api","json-server","jwt-authentication","mocking-server","nodejs","rest-api"],"created_at":"2024-10-10T15:20:14.231Z","updated_at":"2025-03-16T13:30:48.742Z","avatar_url":"https://github.com/sumn2u.png","language":"JavaScript","readme":"# HAI Server \n[![GitHub issues](https://img.shields.io/github/issues/sumn2u/hai-server.svg)](https://github.com/sumn2u/hai-server/issues) [![GitHub forks](https://img.shields.io/github/forks/sumn2u/hai-server.svg)](https://github.com/sumn2u/hai-server/network) [![GitHub stars](https://img.shields.io/github/stars/sumn2u/hai-server.svg)](https://github.com/sumn2u/hai-server/stargazers) [![GitHub license](https://img.shields.io/github/license/sumn2u/hai-server.svg)](https://github.com/sumn2u/hai-server/blob/master/LICENSE) [![Twitter](https://img.shields.io/twitter/url/https/github.com/sumn2u/hai-server.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:\u0026url=https%3A%2F%2Fgithub.com%2Fsumn2u%2Fhai-server)\n[![GitHub tag](https://img.shields.io/github/tag/sumn2u/hai-server.svg)](https://GitHub.com/sumn2u/hai-server/tags/)\n[![GitHub release](https://img.shields.io/github/release/sumn2u/hai-server.svg)](https://GitHub.com/sumn2u/hai-server/releases/)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/sumn2u/hai-server/graphs/commit-activity)\n\u003ca href=\"https://npmjs.com/package/hai-server\"\u003e\u003cimg src=\"https://img.shields.io/npm/dt/hai-server.svg\" alt=\"npm Downloads\"\u003e\u003c/a\u003e \n\n\n\u003c!-- tocstop --\u003e\nInspired and Forked from [JSON Server](https://github.com/typicode/json-server)\n\nGet a full fake REST API with authorization.\n\n\n## Authentication using HAI Server\n[![Authentication using HAI-Server](https://img.youtube.com/vi/R8DccIqyER4/0.jpg)](https://www.youtube.com/watch?v=R8DccIqyER4)\n\n## Getting started\n\nInstall HAI Server \n\n```\nnpm install -g hai-server\n```\n\nCreate a `db.json` file with some data\n\n```json\n{\n  \"posts\": [\n    { \"id\": 1, \"title\": \"hai-server\", \"author\": \"sumn2u\" }\n  ],\n  \"comments\": [\n    { \"id\": 1, \"body\": \"some comment\", \"postId\": 1 }\n  ],\n  \"profile\": { \"name\": \"sumn2u\" }\n}\n```\n\nStart HAI Server\n\n```bash\nhai-server --watch db.json\n```\n\nNow if you go to [http://localhost:3000/posts/1](http://localhost:3000/posts/1), you'll get\n\n```json\n{ \"id\": 1, \"title\": \"hai-server\", \"author\": \"sumn2u\" }\n```\n\nAlso when doing requests, it's good to know that:\n\n- If you make POST, PUT, PATCH or DELETE requests, changes will be automatically and safely saved to `db.json` using [lowdb](https://github.com/sumn2u/lowdb).\n- Your request body JSON should be object enclosed, just like the GET output. (for example `{\"name\": \"Foobar\"}`)\n- Id values are not mutable. Any `id` value in the body of your PUT or PATCH request will be ignored. Only a value set in a POST request will be respected, but only if not already taken.\n- A POST, PUT or PATCH request should include a `Content-Type: application/json` header to use the JSON in the request body. Otherwise it will result in a 200 OK but without changes being made to the data.\n\n## Routes\n\nBased on the previous `db.json` file, here are all the default routes. You can also add [other routes](#add-custom-routes) using `--routes`.\n\n### Plural routes\n\n```\nGET    /posts\nGET    /posts/1\nPOST   /posts\nPUT    /posts/1\nPATCH  /posts/1\nDELETE /posts/1\n```\n\n### Singular routes\n\n```\nGET    /profile\nPOST   /profile\nPUT    /profile\nPATCH  /profile\n```\n\n### Filter\n\nUse `.` to access deep properties\n\n```\nGET /posts?title=hai-server\u0026author=sumn2u\nGET /posts?id=1\u0026id=2\nGET /comments?author.name=sumn2u\n```\n\n### Paginate\n\nUse `_page` and optionally `_limit` to paginate returned data.\n\nIn the `Link` header you'll get `first`, `prev`, `next` and `last` links.\n\n\n```\nGET /posts?_page=7\nGET /posts?_page=7\u0026_limit=20\n```\n\n_10 items are returned by default_\n\n### Sort\n\nAdd `_sort` and `_order` (ascending order by default)\n\n```\nGET /posts?_sort=views\u0026_order=asc\nGET /posts/1/comments?_sort=votes\u0026_order=asc\n```\n\nFor multiple fields, use the following format:\n\n```\nGET /posts?_sort=user,views\u0026_order=desc,asc\n```\n\n### Slice\n\nAdd `_start` and `_end` or `_limit` (an `X-Total-Count` header is included in the response)\n\n```\nGET /posts?_start=20\u0026_end=30\nGET /posts/1/comments?_start=20\u0026_end=30\nGET /posts/1/comments?_start=20\u0026_limit=10\n```\n\n_Works exactly as [Array.slice](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) (i.e. `_start` is inclusive and `_end` exclusive)_\n\n### Operators\n\nAdd `_gte` or `_lte` for getting a range\n\n```\nGET /posts?views_gte=10\u0026views_lte=20\n```\n\nAdd `_ne` to exclude a value\n\n```\nGET /posts?id_ne=1\n```\n\nAdd `_like` to filter (RegExp supported)\n\n```\nGET /posts?title_like=server\n```\n\n### Full-text search\n\nAdd `q`\n\n```\nGET /posts?q=internet\n```\n\n### Relationships\n\nTo include children resources, add `_embed`\n\n```\nGET /posts?_embed=comments\nGET /posts/1?_embed=comments\n```\n\nTo include parent resource, add `_expand`\n\n```\nGET /comments?_expand=post\nGET /comments/1?_expand=post\n```\n\nTo get or create nested resources (by default one level, [add custom routes](#add-custom-routes) for more)\n\n```\nGET  /posts/1/comments\nPOST /posts/1/comments\n```\n\n### Database\n\n```\nGET /db\n```\n\n### Homepage\n\nReturns default index file or serves `./public` directory\n\n```\nGET /\n```\n\n## Extras\n\n### Static file server\n\nYou can use HAI Server to serve your HTML, JS and CSS, simply create a `./public` directory\nor use `--static` to set a different static files directory.\n\n```bash\nmkdir public\necho 'hello world' \u003e public/index.html\nhai-server db.json\n```\n\n```bash\nhai-server db.json --static ./some-other-dir\n```\n\n### Alternative port\n\nYou can start HAI Server on other ports with the `--port` flag:\n\n```bash\n$ hai-server --watch db.json --port 3004\n```\n\n### Access from anywhere\n\nYou can access your fake API from anywhere using CORS and JSONP.\n\n### Remote schema\n\nYou can load remote schemas.\n\n```bash\n$ hai-server http://example.com/file.json\n$ hai-server http://jsonplaceholder.sumn2u.com/db\n```\n\n### Generate random data\n\nUsing JS instead of a JSON file, you can create data programmatically.\n\n```javascript\n// index.js\nmodule.exports = () =\u003e {\n  const data = { users: [] }\n  // Create 1000 users\n  for (let i = 0; i \u003c 1000; i++) {\n    data.users.push({ id: i, name: `user${i}` })\n  }\n  return data\n}\n```\n\n```bash\n$ hai-server index.js\n```\n\n__Tip__ use modules like [Faker](https://github.com/Marak/faker.js), [Casual](https://github.com/boo1ean/casual), [Chance](https://github.com/victorquinn/chancejs) or [JSON Schema Faker](https://github.com/json-schema-faker/json-schema-faker).\n\n### HTTPS\n\nThere are many ways to set up SSL in development. One simple way is to use [hotel](https://github.com/sumn2u/hotel).\n\n### Add custom routes\n\nCreate a `routes.json` file. Pay attention to start every route with `/`.\n\n```json\n{\n  \"/api/*\": \"/$1\",\n  \"/:resource/:id/show\": \"/:resource/:id\",\n  \"/posts/:category\": \"/posts?category=:category\",\n  \"/articles\\\\?id=:id\": \"/posts/:id\"\n}\n```\n\nStart HAI Server with `--routes` option.\n\n```bash\nhai-server db.json --routes routes.json\n```\n\nNow you can access resources using additional routes.\n\n```sh\n/api/posts # → /posts\n/api/posts/1  # → /posts/1\n/posts/1/show # → /posts/1\n/posts/javascript # → /posts?category=javascript\n/articles?id=1 # → /posts/1\n```\n\n### Add middlewares\n\nYou can add your middlewares from the CLI using `--middlewares` option:\n\n```js\n// hello.js\nmodule.exports = (req, res, next) =\u003e {\n  res.header('X-Hello', 'World')\n  next()\n}\n```\n\n```bash\nhai-server db.json --middlewares ./hello.js\nhai-server db.json --middlewares ./first.js ./second.js\n```\n\n### CLI usage\n\n```\nhai-server [options] \u003csource\u003e\n\nOptions:\n  --config, -c       Path to config file           [default: \"hai-server.json\"]\n  --port, -p         Set port                                    [default: 3000]\n  --host, -H         Set host                             [default: \"localhost\"]\n  --watch, -w        Watch file(s)                                     [boolean]\n  --routes, -r       Path to routes file\n  --middlewares, -m  Paths to middleware files                           [array]\n  -- auth, -a        Authentication file                               \n  --static, -s       Set static files directory\n  --read-only, --ro  Allow only GET requests                           [boolean]\n  --no-cors, --nc    Disable Cross-Origin Resource Sharing             [boolean]\n  --no-gzip, --ng    Disable GZIP Content-Encoding                     [boolean]\n  --snapshots, -S    Set snapshots directory                      [default: \".\"]\n  --delay, -d        Add delay to responses (ms)\n  --id, -i           Set database id property (e.g. _id)         [default: \"id\"]\n  --foreignKeySuffix, --fks  Set foreign key suffix, (e.g. _id as in post_id)\n                                                                 [default: \"Id\"]\n  --quiet, -q        Suppress log messages from output                 [boolean]\n  --help, -h         Show help                                         [boolean]\n  --version, -v      Show version number                               [boolean]\n\nExamples:\n  hai-server db.json\n  hai-server file.js\n  hai-server http://example.com/db.json\n\nhttps://github.com/sumn2u/hai-server\n```\n\nYou can also set options in a `hai-server.json` configuration file.\n\n```json\n{\n  \"port\": 3000\n}\n```\n\n### Module\n\nIf you need to add authentication, validation, or __any behavior__, you can use the project as a module in combination with other Express middlewares.\n\n#### Simple example\n\n```sh\n$ npm install hai-server --save-dev\n```\n\n```js\n// server.js\nconst jsonServer = require('hai-server').haijsServer\nconst server = jsonServer.create()\nconst router = jsonServer.router('db.json')\nconst middlewares = jsonServer.defaults()\n\nserver.use(middlewares)\nserver.use(router)\nserver.listen(3000, () =\u003e {\n  console.log('HAI Server is running')\n})\n```\n\n```sh\n$ node server.js\n```\n\nThe path you provide to the `jsonServer.router` function  is relative to the directory from where you launch your node process. If you run the above code from another directory, it’s better to use an absolute path:\n\n```js\nconst path = require('path')\nconst router = jsonServer.router(path.join(__dirname, 'db.json'))\n```\n\nFor an in-memory database, simply pass an object to `jsonServer.router()`.\n\nPlease note also that `jsonServer.router()` can be used in existing Express projects.\n\n#### Custom routes example\n\nLet's say you want a route that echoes query parameters and another one that set a timestamp on every resource created.\n\n```js\nconst jsonServer = require('hai-server').haijsServer\nconst server = jsonServer.create()\nconst router = jsonServer.router('db.json')\nconst middlewares = jsonServer.defaults()\n\n// Set default middlewares (logger, static, cors and no-cache)\nserver.use(middlewares)\n\n// Add custom routes before HAI Server router\nserver.get('/echo', (req, res) =\u003e {\n  res.jsonp(req.query)\n})\n\n// To handle POST, PUT and PATCH you need to use a body-parser\n// You can use the one used by HAI Server\nserver.use(jsonServer.bodyParser)\nserver.use((req, res, next) =\u003e {\n  if (req.method === 'POST') {\n    req.body.createdAt = Date.now()\n  }\n  // Continue to HAI Server router\n  next()\n})\n\n// Use default router\nserver.use(router)\nserver.listen(3000, () =\u003e {\n  console.log('HAI Server is running')\n})\n```  \n\n#### Access control example\nCreate a file name `auth.json` similar like the one shown below. Provide your own `secretKey`, `expiresIn`, and collection of authenticated users. Here the `authenticatedURL` indicates the collection of URL's that needs authorization and `authenticationURL` is the URL to get accesstoken.\n\n```json\n{\n    \"secretKey\":\"123456789\",\n    \"expiresIn\": \"1h\",\n    \"users\": [\n        {\n          \"id\": 1,\n          \"name\": \"bruno\",\n          \"email\": \"bruno@email.com\",\n          \"password\": \"bruno\"\n        },\n        {\n          \"id\": 2,\n          \"name\": \"techie\",\n          \"email\": \"techie@email.com\",\n          \"password\": \"techie\"\n        },\n        {\n          \"id\": 3,\n          \"name\": \"nilson\",\n          \"email\": \"nilson@email.com\",\n          \"password\": \"nilson\"\n        }\n      ],\n    \"authenticationURL\":\"/auth/login\",\n    \"authenticatedURL\":[\"/users\"]\n\n}\n```\n```\nhai-server --watch db.json --auth auth.json --port 3000\n```\n## How to login?\n\nYou can login by sending a POST request to\n\n```json\nPOST http://localhost:3000/auth/login\n```\nwith the following data \n\n```json\n{\n  \"email\": \"nilson@email.com\",\n  \"password\":\"nilson\"\n}\n```\n\nYou should receive an access token with the following format \n\n```json\n{\n   \"access_token\": \"\u003cACCESS_TOKEN\u003e\"\n}\n```\n\n\nYou should send this authorization with any request to the protected endpoints\n\n```json\nAuthorization: Bearer \u003cACCESS_TOKEN\u003e\n```\n\n\n#### Custom output example\n\nTo modify responses, overwrite `router.render` method:\n\n```javascript\n// In this example, returned resources will be wrapped in a body property\nrouter.render = (req, res) =\u003e {\n  res.jsonp({\n    body: res.locals.data\n  })\n}\n```\n\nYou can set your own status code for the response:\n\n\n```javascript\n// In this example we simulate a server side error response\nrouter.render = (req, res) =\u003e {\n  res.status(500).jsonp({\n    error: \"error message here\"\n  })\n}\n```\n\n#### Rewriter example\n\nTo add rewrite rules, use `jsonServer.rewriter()`:\n\n```javascript\n// Add this before server.use(router)\nserver.use(jsonServer.rewriter({\n  '/api/*': '/$1',\n  '/blog/:resource/:id/show': '/:resource/:id'\n}))\n```\n\n#### Mounting HAI Server on another endpoint example\n\nAlternatively, you can also mount the router on `/api`.\n\n```javascript\nserver.use('/api', router)\n```\n\n#### API\n\n__`jsonServer.create()`__\n\nReturns an Express server.\n\n__`jsonServer.defaults([options])`__\n\nReturns middlewares used by HAI Server.\n\n| Option      | Description                                    | Default   |\n|-------------|------------------------------------------------|-----------|\n| `static`    | Path to static files                           | -         |\n| `logger`    | Enable logger middleware                       | `true`    |\n| `bodyParser`| Enable body-parser middleware                  | `true`    |\n| `noCors`    | Disable CORS                                  | `false`   |\n| `readOnly`  | Accept only GET requests                       | `false`   |\n\n\n__`jsonServer.router([path|object])`__\n\nReturns HAI Server router.\n\n\n## License\n\n[MIT](./LICENSE)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumn2u%2Fhai-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsumn2u%2Fhai-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumn2u%2Fhai-server/lists"}