Roughing out the demo app
This commit is contained in:
12
node_modules/json-server/.babelrc
generated
vendored
Normal file
12
node_modules/json-server/.babelrc
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "8"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
2
node_modules/json-server/.eslintignore
generated
vendored
Normal file
2
node_modules/json-server/.eslintignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
src/server/public
|
||||
lib
|
||||
14
node_modules/json-server/.eslintrc.js
generated
vendored
Normal file
14
node_modules/json-server/.eslintrc.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
extends: ['standard', 'prettier'],
|
||||
plugins: ['prettier'],
|
||||
rules: {
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
singleQuote: true,
|
||||
semi: false,
|
||||
},
|
||||
]
|
||||
},
|
||||
env: { jest: true }
|
||||
}
|
||||
2
node_modules/json-server/.github/FUNDING.yml
generated
vendored
Normal file
2
node_modules/json-server/.github/FUNDING.yml
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
github: typicode
|
||||
patreon: typicode
|
||||
4
node_modules/json-server/.travis.yml
generated
vendored
Normal file
4
node_modules/json-server/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "node"
|
||||
- "8"
|
||||
303
node_modules/json-server/CHANGELOG.md
generated
vendored
Normal file
303
node_modules/json-server/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
# Change Log
|
||||
|
||||
Changes for 0.15.1+ can now be found in https://github.com/typicode/json-server/releases
|
||||
|
||||
## 0.15.0 - 2019-05-21
|
||||
|
||||
* __Breaking__ Require Node 8
|
||||
* Upgrade dependencies
|
||||
* Reduce package size
|
||||
|
||||
## 0.14.2 - 2018-12-26
|
||||
|
||||
* Fix `db.getState is not a function`
|
||||
|
||||
## 0.14.1 - 2018-12-25
|
||||
|
||||
* Show error message if port is already used
|
||||
* Upgrade to [lowdb](https://github.com/typicode/lowdb) `1.0`
|
||||
|
||||
## 0.14.0 - 2018-06-09
|
||||
|
||||
* Listen to `localhost` by default, instead of `0.0.0.0`
|
||||
|
||||
## 0.13.0 - 2018-05-30
|
||||
|
||||
* Bundle all index page assets so that you access it without network connection
|
||||
* Drop Node 4 support
|
||||
|
||||
## 0.12.2 - 2018-04-26
|
||||
|
||||
* Add `_delay` query parameter
|
||||
* Upgrade `please-upgrade-node` dependency
|
||||
|
||||
## 0.12.1 - 2017-11-02
|
||||
|
||||
* Disable logging for static content requests
|
||||
* Remove bad `console.log`
|
||||
* Update `dependencies`
|
||||
* Use [`nanoid`](https://github.com/ai/nanoid)
|
||||
|
||||
## 0.12.0 - 2017-08-02
|
||||
|
||||
Re-include `body-parser` in `jsonServer.defaults()`
|
||||
|
||||
If you're using JSON Server in an Express server and experience issues, you can disable it by passing
|
||||
|
||||
```js
|
||||
jsonServer.defaults({ bodyParser: false })
|
||||
```
|
||||
|
||||
## 0.11.2 - 2017-07-10
|
||||
|
||||
Fix `engines` field in `package.json`
|
||||
|
||||
## 0.11.1 - 2017-07-10
|
||||
|
||||
Add [please-upgrade-node](https://github.com/typicode/please-upgrade-node)
|
||||
|
||||
## 0.11.0 - 2017-07-05
|
||||
|
||||
Switch to [express-urlrewrite](https://github.com/kapouer/express-urlrewrite) to support rewriting query parameters (e.g. `/articles?id=1 # → /posts/1`)
|
||||
|
||||
If you're rewriting default routes, you'll need to update your `routes.json` file
|
||||
(see [add custom routes](https://github.com/typicode/json-server#add-custom-routes) for updated doc).
|
||||
|
||||
## 0.10.3 - 2017-06-28
|
||||
|
||||
* Fix `line-break` error in CLI
|
||||
|
||||
## 0.10.2 - 2017-06-28
|
||||
|
||||
* Add `--foreignKeySuffix` option (e.g. snake case `post_id`) [#556](https://github.com/typicode/json-server/pull/556) [#570](https://github.com/typicode/json-server/pull/570)
|
||||
|
||||
## 0.10.1 - 2017-05-16
|
||||
|
||||
* Multiple fields sorting `GET /posts?_sort=user,views&_order=desc,asc`
|
||||
|
||||
## 0.10.0 - 2017-04-26
|
||||
|
||||
* __Drop Node `v0.12` support__
|
||||
* Prevent `TypeError` when a filter is applied on a `null` value [#510](https://github.com/typicode/json-server/issues/510)
|
||||
|
||||
## 0.9.6 - 2017-03-08
|
||||
|
||||
* Update index page
|
||||
* Improve performances ([lowdb](https://github.com/typicode/lowdb) `v0.15`)
|
||||
* Add `Location` header to newly created resources [#473](https://github.com/typicode/json-server/pull/473)
|
||||
|
||||
## 0.9.5 - 2017-02-11
|
||||
|
||||
* Display custom routes on homepage
|
||||
* Fix duplicate query params error [#352](https://github.com/typicode/json-server/issues/352)
|
||||
|
||||
## 0.9.4 - 2016-12-08
|
||||
|
||||
* Improve rewriter [#431](https://github.com/typicode/json-server/issues/431)
|
||||
* Improve watch mode [#427](https://github.com/typicode/json-server/pull/427)
|
||||
|
||||
## 0.9.3 - 2016-12-07
|
||||
|
||||
* Fix [#396](https://github.com/typicode/json-server/issues/396) PUT/PATCH saves the updated item with an id that has been converted to string
|
||||
|
||||
## 0.9.2 - 2016-11-29
|
||||
|
||||
* Fix [#221](https://github.com/typicode/json-server/issues/221) `nohup` support
|
||||
* Fix [#420](https://github.com/typicode/json-server/issues/420) TypeError when watching `db.json`
|
||||
|
||||
## 0.9.1 - 2016-11-21
|
||||
|
||||
* Fix
|
||||
* [#412](https://github.com/typicode/json-server/issues/412)
|
||||
* [#451](https://github.com/typicode/json-server/issues/411)
|
||||
|
||||
## 0.9.0 - 2016-11-11
|
||||
|
||||
* Shorter `uuid`
|
||||
* No automatic conversion of strings to boolean or integer
|
||||
* Create a default `db.json` file if it doesn't exist
|
||||
* Fix
|
||||
* [#361](https://github.com/typicode/json-server/issues/361)
|
||||
* [#363](https://github.com/typicode/json-server/issues/363) [#365](https://github.com/typicode/json-server/issues/365)
|
||||
* [#374](https://github.com/typicode/json-server/issues/374)
|
||||
* [#383](https://github.com/typicode/json-server/issues/383)
|
||||
* Updated dependencies and codebase to ES6
|
||||
|
||||
## 0.8.23 - 2016-11-03
|
||||
|
||||
* Fix `Links` header
|
||||
|
||||
## 0.8.22 - 2016-10-04
|
||||
|
||||
* Fix `Links` header issue when using `_page`
|
||||
* Add query params support to the route rewriter
|
||||
|
||||
## 0.8.21 - 2016-09-13
|
||||
|
||||
* Fix bodyParser issue when using custom routes
|
||||
|
||||
## 0.8.20 - 2016-09-12
|
||||
|
||||
* Fix [#355](https://github.com/typicode/json-server/issues/355)
|
||||
* Add `_page` support
|
||||
|
||||
## 0.8.19 - 2016-08-18
|
||||
|
||||
* Fix [#341](https://github.com/typicode/json-server/issues/341)
|
||||
|
||||
## 0.8.18 - 2016-08-17
|
||||
|
||||
* Add CLI option `--middlewares` and support them in `json-server.json` config file
|
||||
|
||||
## 0.8.17 - 2016-07-25
|
||||
|
||||
* Fix snapshot creation for JS files (ex: `json-server generator.js`)
|
||||
|
||||
## 0.8.16 - 2016-07-11
|
||||
|
||||
* Support `x-www-form-urlencoded`
|
||||
|
||||
## 0.8.15 - 2016-07-03
|
||||
|
||||
* Bug fix: `--watch` option on OS X
|
||||
|
||||
## 0.8.14 - 2016-05-15
|
||||
|
||||
* Bug fix: data wasn't written to file in `v0.8.13` and `v0.8.12`
|
||||
|
||||
## 0.8.13 - 2016-05-12
|
||||
|
||||
* Make `_like` operator case insensitive
|
||||
|
||||
## 0.8.12 - 2016-05-08
|
||||
|
||||
* Minor bug fix
|
||||
|
||||
## 0.8.11 - 2016-05-08
|
||||
|
||||
* Support sort by nested field (e.g. `_sort=author.name`)
|
||||
* Fix `graceful-fs` warning
|
||||
|
||||
## 0.8.10 - 2016-04-18
|
||||
|
||||
* CLI option `-ng/--no-gzip` to disable `gzip` compression
|
||||
|
||||
## 0.8.9 - 2016-03-17
|
||||
|
||||
* CLI can now read options from `json-server.json` if present
|
||||
* CLI option `-c/--config` to point to a different configuration file
|
||||
|
||||
## 0.8.8 - 2016-02-13
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix #233
|
||||
|
||||
## 0.8.7 - 2016-01-22
|
||||
|
||||
### Added
|
||||
|
||||
* `gzip` compression to improve performances
|
||||
* CLI option `-nc/--no-cors` to disable CORS
|
||||
|
||||
## 0.8.6 - 2016-01-07
|
||||
|
||||
### Added
|
||||
|
||||
* CLI option `-ro/--read-only` to allow only GET requests
|
||||
|
||||
## 0.8.5 - 2015-12-28
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix #177
|
||||
|
||||
## 0.8.4 - 2015-12-13
|
||||
|
||||
### Added
|
||||
|
||||
* Like operator `GET /posts?title_like=json` (accepts RegExp)
|
||||
|
||||
## 0.8.3 - 2015-11-25
|
||||
|
||||
### Added
|
||||
|
||||
* CLI option `-q/--quiet`
|
||||
* Nested route `POST /posts/1/comments`
|
||||
* Not equal operator `GET /posts?id_ne=1`
|
||||
|
||||
## 0.8.2 - 2015-10-15
|
||||
|
||||
### Added
|
||||
|
||||
* CLI option `-S/--snapshots` to set a custom snapshots directory.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix plural resources: `DELETE` should return `404` if resource doesn't exist.
|
||||
|
||||
## 0.8.1 - 2015-10-06
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix plural resources: `PUT` should replace resource instead of updating properties.
|
||||
* Fix singular resources: `POST`, `PUT`, `PATCH` should not convert resource properties.
|
||||
|
||||
## 0.8.0 - 2015-09-21
|
||||
|
||||
### Changed
|
||||
|
||||
* `jsonServer.defaults` is now a function and can take an object.
|
||||
If you're using the project as a module, you need to update your code:
|
||||
|
||||
```js
|
||||
// Before
|
||||
jsonServer.defaults
|
||||
// After
|
||||
jsonServer.defaults()
|
||||
jsonServer.defaults({ static: '/some/path'})
|
||||
```
|
||||
|
||||
* Automatically ignore unknown query parameters.
|
||||
|
||||
```bash
|
||||
# Before
|
||||
GET /posts?author=typicode&foo=bar # []
|
||||
# After
|
||||
GET /posts?author=typicode&foo=bar # [{...}, {...}]
|
||||
```
|
||||
|
||||
### Added
|
||||
|
||||
* CLI option for setting a custom static files directory.
|
||||
|
||||
```bash
|
||||
json-server --static some/path
|
||||
```
|
||||
|
||||
## 0.7.28 - 2015-09-09
|
||||
|
||||
```bash
|
||||
# Support range
|
||||
GET /products?price_gte=50&price_lte=100
|
||||
```
|
||||
|
||||
## 0.7.27 - 2015-09-02
|
||||
|
||||
### Added
|
||||
|
||||
```bash
|
||||
# Support OR
|
||||
GET /posts?id=1&id2
|
||||
GET /posts?category=javascript&category=html
|
||||
```
|
||||
|
||||
## 0.7.26 - 2015-09-01
|
||||
|
||||
### Added
|
||||
|
||||
```bash
|
||||
# Support embed and expand in lists
|
||||
GET /posts?embed=comments
|
||||
GET /posts?expand=user
|
||||
```
|
||||
20
node_modules/json-server/LICENSE
generated
vendored
Normal file
20
node_modules/json-server/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 typicode
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
613
node_modules/json-server/README.md
generated
vendored
Normal file
613
node_modules/json-server/README.md
generated
vendored
Normal file
@@ -0,0 +1,613 @@
|
||||
# JSON Server [](https://travis-ci.org/typicode/json-server) [](http://badge.fury.io/js/json-server)
|
||||
|
||||
Get a full fake REST API with __zero coding__ in __less than 30 seconds__ (seriously)
|
||||
|
||||
Created with <3 for front-end developers who need a quick back-end for prototyping and mocking.
|
||||
|
||||
* [Egghead.io free video tutorial - Creating demo APIs with json-server](https://egghead.io/lessons/nodejs-creating-demo-apis-with-json-server)
|
||||
* [JSONPlaceholder - Live running version](https://jsonplaceholder.typicode.com)
|
||||
* [__My JSON Server__ - no installation required, use your own data](https://my-json-server.typicode.com)
|
||||
|
||||
See also:
|
||||
* :dog: [husky - Git hooks made easy](https://github.com/typicode/husky)
|
||||
* :hotel: [hotel - developer tool with local .localhost domain and https out of the box](https://github.com/typicode/hotel)
|
||||
|
||||
<h2 align="center">Sponsors</h2>
|
||||
|
||||
<h3 align="center">Gold</h3>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://tryretool.com/?utm_source=sponsor&utm_campaign=typicode" target="_blank">
|
||||
<img src="https://i.imgur.com/IBItATn.png" height="60px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<h3 align="center">Bronze</h3>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.zinggrid.com/hello/json-server?utm_source=jsonserver&utm_medium=github&utm_campaign=sponsorship" target="_blank">
|
||||
<img src="https://i.imgur.com/3mJGTAQ.png" height="30px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<p> </p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/users/typicode/sponsorship">Become a sponsor and have your company logo here</a>
|
||||
</p>
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Getting started](#getting-started)
|
||||
- [Routes](#routes)
|
||||
* [Plural routes](#plural-routes)
|
||||
* [Singular routes](#singular-routes)
|
||||
* [Filter](#filter)
|
||||
* [Paginate](#paginate)
|
||||
* [Sort](#sort)
|
||||
* [Slice](#slice)
|
||||
* [Operators](#operators)
|
||||
* [Full-text search](#full-text-search)
|
||||
* [Relationships](#relationships)
|
||||
* [Database](#database)
|
||||
* [Homepage](#homepage)
|
||||
- [Extras](#extras)
|
||||
* [Static file server](#static-file-server)
|
||||
* [Alternative port](#alternative-port)
|
||||
* [Access from anywhere](#access-from-anywhere)
|
||||
* [Remote schema](#remote-schema)
|
||||
* [Generate random data](#generate-random-data)
|
||||
* [HTTPS](#https)
|
||||
* [Add custom routes](#add-custom-routes)
|
||||
* [Add middlewares](#add-middlewares)
|
||||
* [CLI usage](#cli-usage)
|
||||
* [Module](#module)
|
||||
+ [Simple example](#simple-example)
|
||||
+ [Custom routes example](#custom-routes-example)
|
||||
+ [Access control example](#access-control-example)
|
||||
+ [Custom output example](#custom-output-example)
|
||||
+ [Rewriter example](#rewriter-example)
|
||||
+ [Mounting JSON Server on another endpoint example](#mounting-json-server-on-another-endpoint-example)
|
||||
+ [API](#api)
|
||||
* [Deployment](#deployment)
|
||||
- [Links](#links)
|
||||
* [Video](#video)
|
||||
* [Articles](#articles)
|
||||
* [Third-party tools](#third-party-tools)
|
||||
- [License](#license)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
## Getting started
|
||||
|
||||
Install JSON Server
|
||||
|
||||
```
|
||||
npm install -g json-server
|
||||
```
|
||||
|
||||
Create a `db.json` file with some data
|
||||
|
||||
```json
|
||||
{
|
||||
"posts": [
|
||||
{ "id": 1, "title": "json-server", "author": "typicode" }
|
||||
],
|
||||
"comments": [
|
||||
{ "id": 1, "body": "some comment", "postId": 1 }
|
||||
],
|
||||
"profile": { "name": "typicode" }
|
||||
}
|
||||
```
|
||||
|
||||
Start JSON Server
|
||||
|
||||
```bash
|
||||
json-server --watch db.json
|
||||
```
|
||||
|
||||
Now if you go to [http://localhost:3000/posts/1](http://localhost:3000/posts/1), you'll get
|
||||
|
||||
```json
|
||||
{ "id": 1, "title": "json-server", "author": "typicode" }
|
||||
```
|
||||
|
||||
Also when doing requests, it's good to know that:
|
||||
|
||||
- If you make POST, PUT, PATCH or DELETE requests, changes will be automatically and safely saved to `db.json` using [lowdb](https://github.com/typicode/lowdb).
|
||||
- Your request body JSON should be object enclosed, just like the GET output. (for example `{"name": "Foobar"}`)
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
## Routes
|
||||
|
||||
Based on the previous `db.json` file, here are all the default routes. You can also add [other routes](#add-custom-routes) using `--routes`.
|
||||
|
||||
### Plural routes
|
||||
|
||||
```
|
||||
GET /posts
|
||||
GET /posts/1
|
||||
POST /posts
|
||||
PUT /posts/1
|
||||
PATCH /posts/1
|
||||
DELETE /posts/1
|
||||
```
|
||||
|
||||
### Singular routes
|
||||
|
||||
```
|
||||
GET /profile
|
||||
POST /profile
|
||||
PUT /profile
|
||||
PATCH /profile
|
||||
```
|
||||
|
||||
### Filter
|
||||
|
||||
Use `.` to access deep properties
|
||||
|
||||
```
|
||||
GET /posts?title=json-server&author=typicode
|
||||
GET /posts?id=1&id=2
|
||||
GET /comments?author.name=typicode
|
||||
```
|
||||
|
||||
### Paginate
|
||||
|
||||
Use `_page` and optionally `_limit` to paginate returned data.
|
||||
|
||||
In the `Link` header you'll get `first`, `prev`, `next` and `last` links.
|
||||
|
||||
|
||||
```
|
||||
GET /posts?_page=7
|
||||
GET /posts?_page=7&_limit=20
|
||||
```
|
||||
|
||||
_10 items are returned by default_
|
||||
|
||||
### Sort
|
||||
|
||||
Add `_sort` and `_order` (ascending order by default)
|
||||
|
||||
```
|
||||
GET /posts?_sort=views&_order=asc
|
||||
GET /posts/1/comments?_sort=votes&_order=asc
|
||||
```
|
||||
|
||||
For multiple fields, use the following format:
|
||||
|
||||
```
|
||||
GET /posts?_sort=user,views&_order=desc,asc
|
||||
```
|
||||
|
||||
### Slice
|
||||
|
||||
Add `_start` and `_end` or `_limit` (an `X-Total-Count` header is included in the response)
|
||||
|
||||
```
|
||||
GET /posts?_start=20&_end=30
|
||||
GET /posts/1/comments?_start=20&_end=30
|
||||
GET /posts/1/comments?_start=20&_limit=10
|
||||
```
|
||||
|
||||
_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)_
|
||||
|
||||
### Operators
|
||||
|
||||
Add `_gte` or `_lte` for getting a range
|
||||
|
||||
```
|
||||
GET /posts?views_gte=10&views_lte=20
|
||||
```
|
||||
|
||||
Add `_ne` to exclude a value
|
||||
|
||||
```
|
||||
GET /posts?id_ne=1
|
||||
```
|
||||
|
||||
Add `_like` to filter (RegExp supported)
|
||||
|
||||
```
|
||||
GET /posts?title_like=server
|
||||
```
|
||||
|
||||
### Full-text search
|
||||
|
||||
Add `q`
|
||||
|
||||
```
|
||||
GET /posts?q=internet
|
||||
```
|
||||
|
||||
### Relationships
|
||||
|
||||
To include children resources, add `_embed`
|
||||
|
||||
```
|
||||
GET /posts?_embed=comments
|
||||
GET /posts/1?_embed=comments
|
||||
```
|
||||
|
||||
To include parent resource, add `_expand`
|
||||
|
||||
```
|
||||
GET /comments?_expand=post
|
||||
GET /comments/1?_expand=post
|
||||
```
|
||||
|
||||
To get or create nested resources (by default one level, [add custom routes](#add-custom-routes) for more)
|
||||
|
||||
```
|
||||
GET /posts/1/comments
|
||||
POST /posts/1/comments
|
||||
```
|
||||
|
||||
### Database
|
||||
|
||||
```
|
||||
GET /db
|
||||
```
|
||||
|
||||
### Homepage
|
||||
|
||||
Returns default index file or serves `./public` directory
|
||||
|
||||
```
|
||||
GET /
|
||||
```
|
||||
|
||||
## Extras
|
||||
|
||||
### Static file server
|
||||
|
||||
You can use JSON Server to serve your HTML, JS and CSS, simply create a `./public` directory
|
||||
or use `--static` to set a different static files directory.
|
||||
|
||||
```bash
|
||||
mkdir public
|
||||
echo 'hello world' > public/index.html
|
||||
json-server db.json
|
||||
```
|
||||
|
||||
```bash
|
||||
json-server db.json --static ./some-other-dir
|
||||
```
|
||||
|
||||
### Alternative port
|
||||
|
||||
You can start JSON Server on other ports with the `--port` flag:
|
||||
|
||||
```bash
|
||||
$ json-server --watch db.json --port 3004
|
||||
```
|
||||
|
||||
### Access from anywhere
|
||||
|
||||
You can access your fake API from anywhere using CORS and JSONP.
|
||||
|
||||
### Remote schema
|
||||
|
||||
You can load remote schemas.
|
||||
|
||||
```bash
|
||||
$ json-server http://example.com/file.json
|
||||
$ json-server http://jsonplaceholder.typicode.com/db
|
||||
```
|
||||
|
||||
### Generate random data
|
||||
|
||||
Using JS instead of a JSON file, you can create data programmatically.
|
||||
|
||||
```javascript
|
||||
// index.js
|
||||
module.exports = () => {
|
||||
const data = { users: [] }
|
||||
// Create 1000 users
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
data.users.push({ id: i, name: `user${i}` })
|
||||
}
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
$ json-server index.js
|
||||
```
|
||||
|
||||
__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).
|
||||
|
||||
### HTTPS
|
||||
|
||||
There are many ways to set up SSL in development. One simple way is to use [hotel](https://github.com/typicode/hotel).
|
||||
|
||||
### Add custom routes
|
||||
|
||||
Create a `routes.json` file. Pay attention to start every route with `/`.
|
||||
|
||||
```json
|
||||
{
|
||||
"/api/*": "/$1",
|
||||
"/:resource/:id/show": "/:resource/:id",
|
||||
"/posts/:category": "/posts?category=:category",
|
||||
"/articles\\?id=:id": "/posts/:id"
|
||||
}
|
||||
```
|
||||
|
||||
Start JSON Server with `--routes` option.
|
||||
|
||||
```bash
|
||||
json-server db.json --routes routes.json
|
||||
```
|
||||
|
||||
Now you can access resources using additional routes.
|
||||
|
||||
```sh
|
||||
/api/posts # → /posts
|
||||
/api/posts/1 # → /posts/1
|
||||
/posts/1/show # → /posts/1
|
||||
/posts/javascript # → /posts?category=javascript
|
||||
/articles?id=1 # → /posts/1
|
||||
```
|
||||
|
||||
### Add middlewares
|
||||
|
||||
You can add your middlewares from the CLI using `--middlewares` option:
|
||||
|
||||
```js
|
||||
// hello.js
|
||||
module.exports = (req, res, next) => {
|
||||
res.header('X-Hello', 'World')
|
||||
next()
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
json-server db.json --middlewares ./hello.js
|
||||
json-server db.json --middlewares ./first.js ./second.js
|
||||
```
|
||||
|
||||
### CLI usage
|
||||
|
||||
```
|
||||
json-server [options] <source>
|
||||
|
||||
Options:
|
||||
--config, -c Path to config file [default: "json-server.json"]
|
||||
--port, -p Set port [default: 3000]
|
||||
--host, -H Set host [default: "localhost"]
|
||||
--watch, -w Watch file(s) [boolean]
|
||||
--routes, -r Path to routes file
|
||||
--middlewares, -m Paths to middleware files [array]
|
||||
--static, -s Set static files directory
|
||||
--read-only, --ro Allow only GET requests [boolean]
|
||||
--no-cors, --nc Disable Cross-Origin Resource Sharing [boolean]
|
||||
--no-gzip, --ng Disable GZIP Content-Encoding [boolean]
|
||||
--snapshots, -S Set snapshots directory [default: "."]
|
||||
--delay, -d Add delay to responses (ms)
|
||||
--id, -i Set database id property (e.g. _id) [default: "id"]
|
||||
--foreignKeySuffix, --fks Set foreign key suffix, (e.g. _id as in post_id)
|
||||
[default: "Id"]
|
||||
--quiet, -q Suppress log messages from output [boolean]
|
||||
--help, -h Show help [boolean]
|
||||
--version, -v Show version number [boolean]
|
||||
|
||||
Examples:
|
||||
json-server db.json
|
||||
json-server file.js
|
||||
json-server http://example.com/db.json
|
||||
|
||||
https://github.com/typicode/json-server
|
||||
```
|
||||
|
||||
You can also set options in a `json-server.json` configuration file.
|
||||
|
||||
```json
|
||||
{
|
||||
"port": 3000
|
||||
}
|
||||
```
|
||||
|
||||
### Module
|
||||
|
||||
If you need to add authentication, validation, or __any behavior__, you can use the project as a module in combination with other Express middlewares.
|
||||
|
||||
#### Simple example
|
||||
|
||||
```sh
|
||||
$ npm install json-server --save-dev
|
||||
```
|
||||
|
||||
```js
|
||||
// server.js
|
||||
const jsonServer = require('json-server')
|
||||
const server = jsonServer.create()
|
||||
const router = jsonServer.router('db.json')
|
||||
const middlewares = jsonServer.defaults()
|
||||
|
||||
server.use(middlewares)
|
||||
server.use(router)
|
||||
server.listen(3000, () => {
|
||||
console.log('JSON Server is running')
|
||||
})
|
||||
```
|
||||
|
||||
```sh
|
||||
$ node server.js
|
||||
```
|
||||
|
||||
The 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:
|
||||
|
||||
```js
|
||||
const path = require('path')
|
||||
const router = jsonServer.router(path.join(__dirname, 'db.json'))
|
||||
```
|
||||
|
||||
For an in-memory database, simply pass an object to `jsonServer.router()`.
|
||||
|
||||
Please note also that `jsonServer.router()` can be used in existing Express projects.
|
||||
|
||||
#### Custom routes example
|
||||
|
||||
Let's say you want a route that echoes query parameters and another one that set a timestamp on every resource created.
|
||||
|
||||
```js
|
||||
const jsonServer = require('json-server')
|
||||
const server = jsonServer.create()
|
||||
const router = jsonServer.router('db.json')
|
||||
const middlewares = jsonServer.defaults()
|
||||
|
||||
// Set default middlewares (logger, static, cors and no-cache)
|
||||
server.use(middlewares)
|
||||
|
||||
// Add custom routes before JSON Server router
|
||||
server.get('/echo', (req, res) => {
|
||||
res.jsonp(req.query)
|
||||
})
|
||||
|
||||
// To handle POST, PUT and PATCH you need to use a body-parser
|
||||
// You can use the one used by JSON Server
|
||||
server.use(jsonServer.bodyParser)
|
||||
server.use((req, res, next) => {
|
||||
if (req.method === 'POST') {
|
||||
req.body.createdAt = Date.now()
|
||||
}
|
||||
// Continue to JSON Server router
|
||||
next()
|
||||
})
|
||||
|
||||
// Use default router
|
||||
server.use(router)
|
||||
server.listen(3000, () => {
|
||||
console.log('JSON Server is running')
|
||||
})
|
||||
```
|
||||
|
||||
#### Access control example
|
||||
|
||||
```js
|
||||
const jsonServer = require('json-server')
|
||||
const server = jsonServer.create()
|
||||
const router = jsonServer.router('db.json')
|
||||
const middlewares = jsonServer.defaults()
|
||||
|
||||
server.use(middlewares)
|
||||
server.use((req, res, next) => {
|
||||
if (isAuthorized(req)) { // add your authorization logic here
|
||||
next() // continue to JSON Server router
|
||||
} else {
|
||||
res.sendStatus(401)
|
||||
}
|
||||
})
|
||||
server.use(router)
|
||||
server.listen(3000, () => {
|
||||
console.log('JSON Server is running')
|
||||
})
|
||||
```
|
||||
#### Custom output example
|
||||
|
||||
To modify responses, overwrite `router.render` method:
|
||||
|
||||
```javascript
|
||||
// In this example, returned resources will be wrapped in a body property
|
||||
router.render = (req, res) => {
|
||||
res.jsonp({
|
||||
body: res.locals.data
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
You can set your own status code for the response:
|
||||
|
||||
|
||||
```javascript
|
||||
// In this example we simulate a server side error response
|
||||
router.render = (req, res) => {
|
||||
res.status(500).jsonp({
|
||||
error: "error message here"
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
#### Rewriter example
|
||||
|
||||
To add rewrite rules, use `jsonServer.rewriter()`:
|
||||
|
||||
```javascript
|
||||
// Add this before server.use(router)
|
||||
server.use(jsonServer.rewriter({
|
||||
'/api/*': '/$1',
|
||||
'/blog/:resource/:id/show': '/:resource/:id'
|
||||
}))
|
||||
```
|
||||
|
||||
#### Mounting JSON Server on another endpoint example
|
||||
|
||||
Alternatively, you can also mount the router on `/api`.
|
||||
|
||||
```javascript
|
||||
server.use('/api', router)
|
||||
```
|
||||
|
||||
#### API
|
||||
|
||||
__`jsonServer.create()`__
|
||||
|
||||
Returns an Express server.
|
||||
|
||||
__`jsonServer.defaults([options])`__
|
||||
|
||||
Returns middlewares used by JSON Server.
|
||||
|
||||
* options
|
||||
* `static` path to static files
|
||||
* `logger` enable logger middleware (default: true)
|
||||
* `bodyParser` enable body-parser middleware (default: true)
|
||||
* `noCors` disable CORS (default: false)
|
||||
* `readOnly` accept only GET requests (default: false)
|
||||
|
||||
__`jsonServer.router([path|object])`__
|
||||
|
||||
Returns JSON Server router.
|
||||
|
||||
### Deployment
|
||||
|
||||
You can deploy JSON Server. For example, [JSONPlaceholder](http://jsonplaceholder.typicode.com) is an online fake API powered by JSON Server and running on Heroku.
|
||||
|
||||
## Links
|
||||
|
||||
### Video
|
||||
|
||||
* [Creating Demo APIs with json-server on egghead.io](https://egghead.io/lessons/nodejs-creating-demo-apis-with-json-server)
|
||||
|
||||
### Articles
|
||||
|
||||
* [Node Module Of The Week - json-server](http://nmotw.in/json-server/)
|
||||
* [Mock up your REST API with JSON Server](http://www.betterpixels.co.uk/projects/2015/05/09/mock-up-your-rest-api-with-json-server/)
|
||||
* [ng-admin: Add an AngularJS admin GUI to any RESTful API](http://marmelab.com/blog/2014/09/15/easy-backend-for-your-restful-api.html)
|
||||
* [Fast prototyping using Restangular and Json-server](https://glebbahmutov.com/blog/fast-prototyping-restangular-and-json-server/)
|
||||
* [Create a Mock REST API in Seconds for Prototyping your Frontend](https://coligo.io/create-mock-rest-api-with-json-server/)
|
||||
* [No API? No Problem! Rapid Development via Mock APIs](https://medium.com/@housecor/rapid-development-via-mock-apis-e559087be066#.93d7w8oro)
|
||||
* [Zero Code REST With json-server](https://dzone.com/articles/zero-code-rest-with-json-server)
|
||||
|
||||
### Third-party tools
|
||||
|
||||
* [Grunt JSON Server](https://github.com/tfiwm/grunt-json-server)
|
||||
* [Docker JSON Server](https://github.com/clue/docker-json-server)
|
||||
* [JSON Server GUI](https://github.com/naholyr/json-server-gui)
|
||||
* [JSON file generator](https://github.com/dfsq/json-server-init)
|
||||
* [JSON Server extension](https://github.com/maty21/json-server-extension)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
[Supporters](https://thanks.typicode.com) ✨
|
||||
21
node_modules/json-server/appveyor.yml
generated
vendored
Normal file
21
node_modules/json-server/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Test against this version of Node.js
|
||||
environment:
|
||||
nodejs_version: "8"
|
||||
|
||||
# Install scripts. (runs after repo cloning)
|
||||
install:
|
||||
# Get the latest stable version of Node.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# install modules
|
||||
- npm install
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
# run tests
|
||||
- npm test
|
||||
|
||||
# Don't actually build.
|
||||
build: off
|
||||
9
node_modules/json-server/db.json
generated
vendored
Normal file
9
node_modules/json-server/db.json
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"posts": [
|
||||
{ "id": 1, "title": "json-server", "author": "typicode" }
|
||||
],
|
||||
"comments": [
|
||||
{ "id": 1, "body": "some comment", "postId": 1 }
|
||||
],
|
||||
"profile": { "name": "typicode" }
|
||||
}
|
||||
BIN
node_modules/json-server/dist/favicon.ico
generated
vendored
Normal file
BIN
node_modules/json-server/dist/favicon.ico
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
82
node_modules/json-server/dist/index.html
generated
vendored
Normal file
82
node_modules/json-server/dist/index.html
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<html>
|
||||
<head>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
||||
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<title>JSON Server</title>
|
||||
<link rel="shortcut icon" href="favicon.ico"><link href="main.css" rel="stylesheet"></head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="title">
|
||||
JSON Server
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/users/typicode/sponsorship">
|
||||
<i class="fas fa-heart"></i>GitHub Sponsors
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://my-json-server.typicode.com">
|
||||
<i class="fas fa-burn"></i>My JSON Server
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://thanks.typicode.com">
|
||||
<i class="far fa-laugh"></i>Supporters
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="container">
|
||||
<h1>Congrats!</h1>
|
||||
<p>
|
||||
You're successfully running JSON Server
|
||||
<br />
|
||||
✧*。٩(ˊᗜˋ*)و✧*。
|
||||
</p>
|
||||
|
||||
<div id="resources"></div>
|
||||
|
||||
<p>
|
||||
To access and modify resources, you can use any HTTP method:
|
||||
</p>
|
||||
<p>
|
||||
<code>GET</code>
|
||||
<code>POST</code>
|
||||
<code>PUT</code>
|
||||
<code>PATCH</code>
|
||||
<code>DELETE</code>
|
||||
<code>OPTIONS</code>
|
||||
</p>
|
||||
|
||||
<div id="custom-routes"></div>
|
||||
|
||||
<h1>Documentation</h1>
|
||||
<p>
|
||||
<a href="https://github.com/typicode/json-server">
|
||||
README
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>
|
||||
To replace this page, create a
|
||||
<code>./public/index.html</code> file.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script type="text/javascript" src="main.js"></script></body>
|
||||
</html>
|
||||
114
node_modules/json-server/dist/main.css
generated
vendored
Normal file
114
node_modules/json-server/dist/main.css
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: #3b4252;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 960px;
|
||||
margin: auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
header a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
header a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
nav li.title {
|
||||
flex-grow: 5;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
font-size: 1.4rem;
|
||||
color: #3b4252;
|
||||
}
|
||||
|
||||
nav li {
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
text-align: right;
|
||||
color: #4c566a;
|
||||
}
|
||||
|
||||
.fa-heart {
|
||||
color: deeppink;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 4rem;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 4rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #5e81ac;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #81a1c1;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
border: 0;
|
||||
padding: 0 1em 0.5em 0;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.2rem;
|
||||
margin: 0rem 0.2rem;
|
||||
border-radius: 0.2rem;
|
||||
background: #e5e9f0;
|
||||
}
|
||||
|
||||
1
node_modules/json-server/dist/main.js
generated
vendored
Normal file
1
node_modules/json-server/dist/main.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
6
node_modules/json-server/lib/cli/bin.js
generated
vendored
Executable file
6
node_modules/json-server/lib/cli/bin.js
generated
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
require('please-upgrade-node')(require('../../package.json'));
|
||||
|
||||
require('./')();
|
||||
87
node_modules/json-server/lib/cli/index.js
generated
vendored
Normal file
87
node_modules/json-server/lib/cli/index.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
|
||||
const updateNotifier = require('update-notifier');
|
||||
|
||||
const yargs = require('yargs');
|
||||
|
||||
const run = require('./run');
|
||||
|
||||
const pkg = require('../../package.json');
|
||||
|
||||
module.exports = function () {
|
||||
updateNotifier({
|
||||
pkg
|
||||
}).notify();
|
||||
|
||||
const argv = yargs.config('config').usage('$0 [options] <source>').options({
|
||||
port: {
|
||||
alias: 'p',
|
||||
description: 'Set port',
|
||||
default: 3000
|
||||
},
|
||||
host: {
|
||||
alias: 'H',
|
||||
description: 'Set host',
|
||||
default: 'localhost'
|
||||
},
|
||||
watch: {
|
||||
alias: 'w',
|
||||
description: 'Watch file(s)'
|
||||
},
|
||||
routes: {
|
||||
alias: 'r',
|
||||
description: 'Path to routes file'
|
||||
},
|
||||
middlewares: {
|
||||
alias: 'm',
|
||||
array: true,
|
||||
description: 'Paths to middleware files'
|
||||
},
|
||||
static: {
|
||||
alias: 's',
|
||||
description: 'Set static files directory'
|
||||
},
|
||||
'read-only': {
|
||||
alias: 'ro',
|
||||
description: 'Allow only GET requests'
|
||||
},
|
||||
'no-cors': {
|
||||
alias: 'nc',
|
||||
description: 'Disable Cross-Origin Resource Sharing'
|
||||
},
|
||||
'no-gzip': {
|
||||
alias: 'ng',
|
||||
description: 'Disable GZIP Content-Encoding'
|
||||
},
|
||||
snapshots: {
|
||||
alias: 'S',
|
||||
description: 'Set snapshots directory',
|
||||
default: '.'
|
||||
},
|
||||
delay: {
|
||||
alias: 'd',
|
||||
description: 'Add delay to responses (ms)'
|
||||
},
|
||||
id: {
|
||||
alias: 'i',
|
||||
description: 'Set database id property (e.g. _id)',
|
||||
default: 'id'
|
||||
},
|
||||
foreignKeySuffix: {
|
||||
alias: 'fks',
|
||||
description: 'Set foreign key suffix (e.g. _id as in post_id)',
|
||||
default: 'Id'
|
||||
},
|
||||
quiet: {
|
||||
alias: 'q',
|
||||
description: 'Suppress log messages from output'
|
||||
},
|
||||
config: {
|
||||
alias: 'c',
|
||||
description: 'Path to config file',
|
||||
default: 'json-server.json'
|
||||
}
|
||||
}).boolean('watch').boolean('read-only').boolean('quiet').boolean('no-cors').boolean('no-gzip').help('help').alias('help', 'h').version(pkg.version).alias('version', 'v').example('$0 db.json', '').example('$0 file.js', '').example('$0 http://example.com/db.json', '').epilog('https://github.com/typicode/json-server').require(1, 'Missing <source> argument').argv;
|
||||
|
||||
run(argv);
|
||||
};
|
||||
233
node_modules/json-server/lib/cli/run.js
generated
vendored
Normal file
233
node_modules/json-server/lib/cli/run.js
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const jph = require('json-parse-helpfulerror');
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
const enableDestroy = require('server-destroy');
|
||||
|
||||
const pause = require('connect-pause');
|
||||
|
||||
const is = require('./utils/is');
|
||||
|
||||
const load = require('./utils/load');
|
||||
|
||||
const jsonServer = require('../server');
|
||||
|
||||
function prettyPrint(argv, object, rules) {
|
||||
const root = `http://${argv.host}:${argv.port}`;
|
||||
console.log();
|
||||
console.log(chalk.bold(' Resources'));
|
||||
|
||||
for (const prop in object) {
|
||||
console.log(` ${root}/${prop}`);
|
||||
}
|
||||
|
||||
if (rules) {
|
||||
console.log();
|
||||
console.log(chalk.bold(' Other routes'));
|
||||
|
||||
for (var rule in rules) {
|
||||
console.log(` ${rule} -> ${rules[rule]}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log();
|
||||
console.log(chalk.bold(' Home'));
|
||||
console.log(` ${root}`);
|
||||
console.log();
|
||||
}
|
||||
|
||||
function createApp(db, routes, middlewares, argv) {
|
||||
const app = jsonServer.create();
|
||||
const {
|
||||
foreignKeySuffix
|
||||
} = argv;
|
||||
const router = jsonServer.router(db, foreignKeySuffix ? {
|
||||
foreignKeySuffix
|
||||
} : undefined);
|
||||
const defaultsOpts = {
|
||||
logger: !argv.quiet,
|
||||
readOnly: argv.readOnly,
|
||||
noCors: argv.noCors,
|
||||
noGzip: argv.noGzip,
|
||||
bodyParser: true
|
||||
};
|
||||
|
||||
if (argv.static) {
|
||||
defaultsOpts.static = path.join(process.cwd(), argv.static);
|
||||
}
|
||||
|
||||
const defaults = jsonServer.defaults(defaultsOpts);
|
||||
app.use(defaults);
|
||||
|
||||
if (routes) {
|
||||
const rewriter = jsonServer.rewriter(routes);
|
||||
app.use(rewriter);
|
||||
}
|
||||
|
||||
if (middlewares) {
|
||||
app.use(middlewares);
|
||||
}
|
||||
|
||||
if (argv.delay) {
|
||||
app.use(pause(argv.delay));
|
||||
}
|
||||
|
||||
router.db._.id = argv.id;
|
||||
app.db = router.db;
|
||||
app.use(router);
|
||||
return app;
|
||||
}
|
||||
|
||||
module.exports = function (argv) {
|
||||
const source = argv._[0];
|
||||
let app;
|
||||
let server;
|
||||
|
||||
if (!fs.existsSync(argv.snapshots)) {
|
||||
console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`);
|
||||
process.exit(1);
|
||||
} // noop log fn
|
||||
|
||||
|
||||
if (argv.quiet) {
|
||||
console.log = () => {};
|
||||
}
|
||||
|
||||
console.log();
|
||||
console.log(chalk.cyan(' \\{^_^}/ hi!'));
|
||||
|
||||
function start(cb) {
|
||||
console.log();
|
||||
console.log(chalk.gray(' Loading', source));
|
||||
server = undefined; // create db and load object, JSON file, JS or HTTP database
|
||||
|
||||
return load(source).then(db => {
|
||||
// Load additional routes
|
||||
let routes;
|
||||
|
||||
if (argv.routes) {
|
||||
console.log(chalk.gray(' Loading', argv.routes));
|
||||
routes = JSON.parse(fs.readFileSync(argv.routes));
|
||||
} // Load middlewares
|
||||
|
||||
|
||||
let middlewares;
|
||||
|
||||
if (argv.middlewares) {
|
||||
middlewares = argv.middlewares.map(function (m) {
|
||||
console.log(chalk.gray(' Loading', m));
|
||||
return require(path.resolve(m));
|
||||
});
|
||||
} // Done
|
||||
|
||||
|
||||
console.log(chalk.gray(' Done')); // Create app and server
|
||||
|
||||
app = createApp(db, routes, middlewares, argv);
|
||||
server = app.listen(argv.port, argv.host); // Enhance with a destroy function
|
||||
|
||||
enableDestroy(server); // Display server informations
|
||||
|
||||
prettyPrint(argv, db.getState(), routes); // Catch and handle any error occurring in the server process
|
||||
|
||||
process.on('uncaughtException', error => {
|
||||
if (error.errno === 'EADDRINUSE') console.log(chalk.red(`Cannot bind to the port ${error.port}. Please specify another port number either through --port argument or through the json-server.json configuration file`));else console.log('Some error occurred', error);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
} // Start server
|
||||
|
||||
|
||||
start().then(() => {
|
||||
// Snapshot
|
||||
console.log(chalk.gray(' Type s + enter at any time to create a snapshot of the database')); // Support nohup
|
||||
// https://github.com/typicode/json-server/issues/221
|
||||
|
||||
process.stdin.on('error', () => {
|
||||
console.log(` Error, can't read from stdin`);
|
||||
console.log(` Creating a snapshot from the CLI won't be possible`);
|
||||
});
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', chunk => {
|
||||
if (chunk.trim().toLowerCase() === 's') {
|
||||
const filename = `db-${Date.now()}.json`;
|
||||
const file = path.join(argv.snapshots, filename);
|
||||
const state = app.db.getState();
|
||||
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8');
|
||||
console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`);
|
||||
}
|
||||
}); // Watch files
|
||||
|
||||
if (argv.watch) {
|
||||
console.log(chalk.gray(' Watching...'));
|
||||
console.log();
|
||||
const source = argv._[0]; // Can't watch URL
|
||||
|
||||
if (is.URL(source)) throw new Error("Can't watch URL"); // Watch .js or .json file
|
||||
// Since lowdb uses atomic writing, directory is watched instead of file
|
||||
|
||||
const watchedDir = path.dirname(source);
|
||||
let readError = false;
|
||||
fs.watch(watchedDir, (event, file) => {
|
||||
// https://github.com/typicode/json-server/issues/420
|
||||
// file can be null
|
||||
if (file) {
|
||||
const watchedFile = path.resolve(watchedDir, file);
|
||||
|
||||
if (watchedFile === path.resolve(source)) {
|
||||
if (is.FILE(watchedFile)) {
|
||||
let obj;
|
||||
|
||||
try {
|
||||
obj = jph.parse(fs.readFileSync(watchedFile));
|
||||
|
||||
if (readError) {
|
||||
console.log(chalk.green(` Read error has been fixed :)`));
|
||||
readError = false;
|
||||
}
|
||||
} catch (e) {
|
||||
readError = true;
|
||||
console.log(chalk.red(` Error reading ${watchedFile}`));
|
||||
console.error(e.message);
|
||||
return;
|
||||
} // Compare .json file content with in memory database
|
||||
|
||||
|
||||
const isDatabaseDifferent = !_.isEqual(obj, app.db.getState());
|
||||
|
||||
if (isDatabaseDifferent) {
|
||||
console.log(chalk.gray(` ${source} has changed, reloading...`));
|
||||
server && server.destroy(() => start());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}); // Watch routes
|
||||
|
||||
if (argv.routes) {
|
||||
const watchedDir = path.dirname(argv.routes);
|
||||
fs.watch(watchedDir, (event, file) => {
|
||||
if (file) {
|
||||
const watchedFile = path.resolve(watchedDir, file);
|
||||
|
||||
if (watchedFile === path.resolve(argv.routes)) {
|
||||
console.log(chalk.gray(` ${argv.routes} has changed, reloading...`));
|
||||
server && server.destroy(() => start());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
19
node_modules/json-server/lib/cli/utils/is.js
generated
vendored
Normal file
19
node_modules/json-server/lib/cli/utils/is.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
FILE,
|
||||
JS,
|
||||
URL
|
||||
};
|
||||
|
||||
function FILE(s) {
|
||||
return !URL(s) && /\.json$/.test(s);
|
||||
}
|
||||
|
||||
function JS(s) {
|
||||
return !URL(s) && /\.js$/.test(s);
|
||||
}
|
||||
|
||||
function URL(s) {
|
||||
return /^(http|https):/.test(s);
|
||||
}
|
||||
74
node_modules/json-server/lib/cli/utils/load.js
generated
vendored
Normal file
74
node_modules/json-server/lib/cli/utils/load.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const request = require('request');
|
||||
|
||||
const low = require('lowdb');
|
||||
|
||||
const FileAsync = require('lowdb/adapters/FileAsync');
|
||||
|
||||
const Memory = require('lowdb/adapters/Memory');
|
||||
|
||||
const is = require('./is');
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
const example = {
|
||||
posts: [{
|
||||
id: 1,
|
||||
title: 'json-server',
|
||||
author: 'typicode'
|
||||
}],
|
||||
comments: [{
|
||||
id: 1,
|
||||
body: 'some comment',
|
||||
postId: 1
|
||||
}],
|
||||
profile: {
|
||||
name: 'typicode'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function (source) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (is.FILE(source)) {
|
||||
if (!fs.existsSync(source)) {
|
||||
console.log(chalk.yellow(` Oops, ${source} doesn't seem to exist`));
|
||||
console.log(chalk.yellow(` Creating ${source} with some default data`));
|
||||
console.log();
|
||||
fs.writeFileSync(source, JSON.stringify(example, null, 2));
|
||||
}
|
||||
|
||||
resolve(low(new FileAsync(source)));
|
||||
} else if (is.URL(source)) {
|
||||
// Load remote data
|
||||
const opts = {
|
||||
url: source,
|
||||
json: true
|
||||
};
|
||||
request(opts, (err, response) => {
|
||||
if (err) return reject(err);
|
||||
resolve(low(new Memory()).setState(response.body));
|
||||
});
|
||||
} else if (is.JS(source)) {
|
||||
// Clear cache
|
||||
const filename = path.resolve(source);
|
||||
delete require.cache[filename];
|
||||
|
||||
const dataFn = require(filename);
|
||||
|
||||
if (typeof dataFn !== 'function') {
|
||||
throw new Error('The database is a JavaScript file but the export is not a function.');
|
||||
} // Run dataFn to generate data
|
||||
|
||||
|
||||
const data = dataFn();
|
||||
resolve(low(new Memory()).setState(data));
|
||||
} else {
|
||||
throw new Error(`Unsupported source ${source}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
77
node_modules/json-server/lib/front/index.js
generated
vendored
Normal file
77
node_modules/json-server/lib/front/index.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
"use strict";
|
||||
|
||||
require("promise-polyfill/src/polyfill");
|
||||
|
||||
require("whatwg-fetch");
|
||||
|
||||
require("./style.css");
|
||||
|
||||
function ResourceItem({
|
||||
name,
|
||||
length
|
||||
}) {
|
||||
return `
|
||||
<li>
|
||||
<a href="${name}">/${name}</a>
|
||||
<sup>${length ? `${length}x` : 'object'}</sup>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
|
||||
function ResourceList({
|
||||
db
|
||||
}) {
|
||||
return `
|
||||
<ul>
|
||||
${Object.keys(db).map(name => ResourceItem({
|
||||
name,
|
||||
length: Array.isArray(db[name]) && db[name].length
|
||||
})).join('')}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
|
||||
function NoResources() {
|
||||
return `<p>No resources found</p>`;
|
||||
}
|
||||
|
||||
function ResourcesBlock({
|
||||
db
|
||||
}) {
|
||||
return `
|
||||
<div>
|
||||
<h1>Resources</h1>
|
||||
${Object.keys(db).length ? ResourceList({
|
||||
db
|
||||
}) : NoResources()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
window.fetch('db').then(response => response.json()).then(db => document.getElementById('resources').innerHTML = ResourcesBlock({
|
||||
db
|
||||
}));
|
||||
|
||||
function CustomRoutesBlock({
|
||||
customRoutes
|
||||
}) {
|
||||
const rules = Object.keys(customRoutes);
|
||||
|
||||
if (rules.length) {
|
||||
return `
|
||||
<div>
|
||||
<h1>Custom Routes</h1>
|
||||
<table>
|
||||
${rules.map(rule => `<tr>
|
||||
<td>${rule}</td>
|
||||
<td><code>⇢</code> ${customRoutes[rule]}</td>
|
||||
</tr>`).join('')}
|
||||
</table>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
window.fetch('__rules').then(response => response.json()).then(customRoutes => document.getElementById('custom-routes').innerHTML = CustomRoutesBlock({
|
||||
customRoutes
|
||||
}));
|
||||
10
node_modules/json-server/lib/server/body-parser.js
generated
vendored
Normal file
10
node_modules/json-server/lib/server/body-parser.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
module.exports = [bodyParser.json({
|
||||
limit: '10mb',
|
||||
extended: false
|
||||
}), bodyParser.urlencoded({
|
||||
extended: false
|
||||
})];
|
||||
82
node_modules/json-server/lib/server/defaults.js
generated
vendored
Normal file
82
node_modules/json-server/lib/server/defaults.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const logger = require('morgan');
|
||||
|
||||
const cors = require('cors');
|
||||
|
||||
const compression = require('compression');
|
||||
|
||||
const errorhandler = require('errorhandler');
|
||||
|
||||
const objectAssign = require('object-assign');
|
||||
|
||||
const bodyParser = require('./body-parser');
|
||||
|
||||
module.exports = function (opts) {
|
||||
const userDir = path.join(process.cwd(), 'public');
|
||||
const defaultDir = path.join(__dirname, '../../dist');
|
||||
const staticDir = fs.existsSync(userDir) ? userDir : defaultDir;
|
||||
opts = objectAssign({
|
||||
logger: true,
|
||||
static: staticDir
|
||||
}, opts);
|
||||
const arr = []; // Compress all requests
|
||||
|
||||
if (!opts.noGzip) {
|
||||
arr.push(compression());
|
||||
} // Enable CORS for all the requests, including static files
|
||||
|
||||
|
||||
if (!opts.noCors) {
|
||||
arr.push(cors({
|
||||
origin: true,
|
||||
credentials: true
|
||||
}));
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// only use in development
|
||||
arr.push(errorhandler());
|
||||
} // Serve static files
|
||||
|
||||
|
||||
arr.push(express.static(opts.static)); // Logger
|
||||
|
||||
if (opts.logger) {
|
||||
arr.push(logger('dev', {
|
||||
skip: req => process.env.NODE_ENV === 'test' || req.path === '/favicon.ico'
|
||||
}));
|
||||
} // No cache for IE
|
||||
// https://support.microsoft.com/en-us/kb/234067
|
||||
|
||||
|
||||
arr.push((req, res, next) => {
|
||||
res.header('Cache-Control', 'no-cache');
|
||||
res.header('Pragma', 'no-cache');
|
||||
res.header('Expires', '-1');
|
||||
next();
|
||||
}); // Read-only
|
||||
|
||||
if (opts.readOnly) {
|
||||
arr.push((req, res, next) => {
|
||||
if (req.method === 'GET') {
|
||||
next(); // Continue
|
||||
} else {
|
||||
res.sendStatus(403); // Forbidden
|
||||
}
|
||||
});
|
||||
} // Add middlewares
|
||||
|
||||
|
||||
if (opts.bodyParser) {
|
||||
arr.push(bodyParser);
|
||||
}
|
||||
|
||||
return arr;
|
||||
};
|
||||
11
node_modules/json-server/lib/server/index.js
generated
vendored
Normal file
11
node_modules/json-server/lib/server/index.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const express = require('express');
|
||||
|
||||
module.exports = {
|
||||
create: () => express().set('json spaces', 2),
|
||||
defaults: require('./defaults'),
|
||||
router: require('./router'),
|
||||
rewriter: require('./rewriter'),
|
||||
bodyParser: require('./body-parser')
|
||||
};
|
||||
84
node_modules/json-server/lib/server/mixins.js
generated
vendored
Normal file
84
node_modules/json-server/lib/server/mixins.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
|
||||
const nanoid = require('nanoid');
|
||||
|
||||
const pluralize = require('pluralize');
|
||||
|
||||
module.exports = {
|
||||
getRemovable,
|
||||
createId,
|
||||
deepQuery // Returns document ids that have unsatisfied relations
|
||||
// Example: a comment that references a post that doesn't exist
|
||||
|
||||
};
|
||||
|
||||
function getRemovable(db, opts) {
|
||||
const _ = this;
|
||||
|
||||
const removable = [];
|
||||
|
||||
_.each(db, (coll, collName) => {
|
||||
_.each(coll, doc => {
|
||||
_.each(doc, (value, key) => {
|
||||
if (new RegExp(`${opts.foreignKeySuffix}$`).test(key)) {
|
||||
// Remove foreign key suffix and pluralize it
|
||||
// Example postId -> posts
|
||||
const refName = pluralize.plural(key.replace(new RegExp(`${opts.foreignKeySuffix}$`), '')); // Test if table exists
|
||||
|
||||
if (db[refName]) {
|
||||
// Test if references is defined in table
|
||||
const ref = _.getById(db[refName], value);
|
||||
|
||||
if (_.isUndefined(ref)) {
|
||||
removable.push({
|
||||
name: collName,
|
||||
id: doc.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return removable;
|
||||
} // Return incremented id or uuid
|
||||
// Used to override lodash-id's createId with utils.createId
|
||||
|
||||
|
||||
function createId(coll) {
|
||||
const _ = this;
|
||||
|
||||
const idProperty = _.__id();
|
||||
|
||||
if (_.isEmpty(coll)) {
|
||||
return 1;
|
||||
} else {
|
||||
let id = _(coll).maxBy(idProperty)[idProperty]; // Increment integer id or generate string id
|
||||
|
||||
|
||||
return _.isFinite(id) ? ++id : nanoid(7);
|
||||
}
|
||||
}
|
||||
|
||||
function deepQuery(value, q) {
|
||||
const _ = this;
|
||||
|
||||
if (value && q) {
|
||||
if (_.isArray(value)) {
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (_.deepQuery(value[i], q)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (_.isObject(value) && !_.isArray(value)) {
|
||||
for (const k in value) {
|
||||
if (_.deepQuery(value[k], q)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (value.toString().toLowerCase().indexOf(q) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
node_modules/json-server/lib/server/rewriter.js
generated
vendored
Normal file
16
node_modules/json-server/lib/server/rewriter.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const rewrite = require('express-urlrewrite');
|
||||
|
||||
module.exports = routes => {
|
||||
const router = express.Router();
|
||||
router.get('/__rules', (req, res) => {
|
||||
res.json(routes);
|
||||
});
|
||||
Object.keys(routes).forEach(key => {
|
||||
router.use(rewrite(key, routes[key]));
|
||||
});
|
||||
return router;
|
||||
};
|
||||
12
node_modules/json-server/lib/server/router/delay.js
generated
vendored
Normal file
12
node_modules/json-server/lib/server/router/delay.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const pause = require('connect-pause');
|
||||
|
||||
module.exports = function delay(req, res, next) {
|
||||
// NOTE: for some reason unknown to me, if the default is 0, the tests seems to add 2 seconds
|
||||
// NOTE: to each test, a default value of 1 does not seem to be effected by that issue
|
||||
const _delay = !isNaN(parseFloat(req.query._delay)) ? parseFloat(req.query._delay) : 1;
|
||||
|
||||
delete req.query._delay;
|
||||
pause(_delay)(req, res, next);
|
||||
};
|
||||
11
node_modules/json-server/lib/server/router/get-full-url.js
generated
vendored
Normal file
11
node_modules/json-server/lib/server/router/get-full-url.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const url = require('url');
|
||||
|
||||
module.exports = function getFullURL(req) {
|
||||
const root = url.format({
|
||||
protocol: req.protocol,
|
||||
host: req.get('host')
|
||||
});
|
||||
return `${root}${req.originalUrl}`;
|
||||
};
|
||||
96
node_modules/json-server/lib/server/router/index.js
generated
vendored
Normal file
96
node_modules/json-server/lib/server/router/index.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const methodOverride = require('method-override');
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const lodashId = require('lodash-id');
|
||||
|
||||
const low = require('lowdb');
|
||||
|
||||
const Memory = require('lowdb/adapters/Memory');
|
||||
|
||||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
|
||||
const bodyParser = require('../body-parser');
|
||||
|
||||
const validateData = require('./validate-data');
|
||||
|
||||
const plural = require('./plural');
|
||||
|
||||
const nested = require('./nested');
|
||||
|
||||
const singular = require('./singular');
|
||||
|
||||
const mixins = require('../mixins');
|
||||
|
||||
module.exports = (db, opts = {
|
||||
foreignKeySuffix: 'Id',
|
||||
_isFake: false
|
||||
}) => {
|
||||
if (typeof db === 'string') {
|
||||
db = low(new FileSync(db));
|
||||
} else if (!_.has(db, '__chain__') || !_.has(db, '__wrapped__')) {
|
||||
db = low(new Memory()).setState(db);
|
||||
} // Create router
|
||||
|
||||
|
||||
const router = express.Router(); // Add middlewares
|
||||
|
||||
router.use(methodOverride());
|
||||
router.use(bodyParser);
|
||||
validateData(db.getState()); // Add lodash-id methods to db
|
||||
|
||||
db._.mixin(lodashId); // Add specific mixins
|
||||
|
||||
|
||||
db._.mixin(mixins); // Expose database
|
||||
|
||||
|
||||
router.db = db; // Expose render
|
||||
|
||||
router.render = (req, res) => {
|
||||
res.jsonp(res.locals.data);
|
||||
}; // GET /db
|
||||
|
||||
|
||||
router.get('/db', (req, res) => {
|
||||
res.jsonp(db.getState());
|
||||
}); // Handle /:parent/:parentId/:resource
|
||||
|
||||
router.use(nested(opts)); // Create routes
|
||||
|
||||
db.forEach((value, key) => {
|
||||
if (_.isPlainObject(value)) {
|
||||
router.use(`/${key}`, singular(db, key, opts));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isArray(value)) {
|
||||
router.use(`/${key}`, plural(db, key, opts));
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceMessage = ''; // if (!_.isObject(source)) {
|
||||
// sourceMessage = `in ${source}`
|
||||
// }
|
||||
|
||||
const msg = `Type of "${key}" (${typeof value}) ${sourceMessage} is not supported. ` + `Use objects or arrays of objects.`;
|
||||
throw new Error(msg);
|
||||
}).value();
|
||||
router.use((req, res) => {
|
||||
if (!res.locals.data) {
|
||||
res.status(404);
|
||||
res.locals.data = {};
|
||||
}
|
||||
|
||||
router.render(req, res);
|
||||
});
|
||||
router.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).send(err.stack);
|
||||
});
|
||||
return router;
|
||||
};
|
||||
29
node_modules/json-server/lib/server/router/nested.js
generated
vendored
Normal file
29
node_modules/json-server/lib/server/router/nested.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const pluralize = require('pluralize');
|
||||
|
||||
const delay = require('./delay');
|
||||
|
||||
module.exports = opts => {
|
||||
const router = express.Router();
|
||||
router.use(delay); // Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
||||
|
||||
function get(req, res, next) {
|
||||
const prop = pluralize.singular(req.params.resource);
|
||||
req.query[`${prop}${opts.foreignKeySuffix}`] = req.params.id;
|
||||
req.url = `/${req.params.nested}`;
|
||||
next();
|
||||
} // Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
|
||||
|
||||
|
||||
function post(req, res, next) {
|
||||
const prop = pluralize.singular(req.params.resource);
|
||||
req.body[`${prop}${opts.foreignKeySuffix}`] = req.params.id;
|
||||
req.url = `/${req.params.nested}`;
|
||||
next();
|
||||
}
|
||||
|
||||
return router.get('/:resource/:id/:nested', get).post('/:resource/:id/:nested', post);
|
||||
};
|
||||
303
node_modules/json-server/lib/server/router/plural.js
generated
vendored
Normal file
303
node_modules/json-server/lib/server/router/plural.js
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
"use strict";
|
||||
|
||||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const pluralize = require('pluralize');
|
||||
|
||||
const write = require('./write');
|
||||
|
||||
const getFullURL = require('./get-full-url');
|
||||
|
||||
const utils = require('../utils');
|
||||
|
||||
const delay = require('./delay');
|
||||
|
||||
module.exports = (db, name, opts) => {
|
||||
// Create router
|
||||
const router = express.Router();
|
||||
router.use(delay); // Embed function used in GET /name and GET /name/id
|
||||
|
||||
function embed(resource, e) {
|
||||
e && [].concat(e).forEach(externalResource => {
|
||||
if (db.get(externalResource).value) {
|
||||
const query = {};
|
||||
const singularResource = pluralize.singular(name);
|
||||
query[`${singularResource}${opts.foreignKeySuffix}`] = resource.id;
|
||||
resource[externalResource] = db.get(externalResource).filter(query).value();
|
||||
}
|
||||
});
|
||||
} // Expand function used in GET /name and GET /name/id
|
||||
|
||||
|
||||
function expand(resource, e) {
|
||||
e && [].concat(e).forEach(innerResource => {
|
||||
const plural = pluralize(innerResource);
|
||||
|
||||
if (db.get(plural).value()) {
|
||||
const prop = `${innerResource}${opts.foreignKeySuffix}`;
|
||||
resource[innerResource] = db.get(plural).getById(resource[prop]).value();
|
||||
}
|
||||
});
|
||||
} // GET /name
|
||||
// GET /name?q=
|
||||
// GET /name?attr=&attr=
|
||||
// GET /name?_end=&
|
||||
// GET /name?_start=&_end=&
|
||||
// GET /name?_embed=&_expand=
|
||||
|
||||
|
||||
function list(req, res, next) {
|
||||
// Resource chain
|
||||
let chain = db.get(name); // Remove q, _start, _end, ... from req.query to avoid filtering using those
|
||||
// parameters
|
||||
|
||||
let q = req.query.q;
|
||||
let _start = req.query._start;
|
||||
let _end = req.query._end;
|
||||
let _page = req.query._page;
|
||||
const _sort = req.query._sort;
|
||||
const _order = req.query._order;
|
||||
let _limit = req.query._limit;
|
||||
const _embed = req.query._embed;
|
||||
const _expand = req.query._expand;
|
||||
delete req.query.q;
|
||||
delete req.query._start;
|
||||
delete req.query._end;
|
||||
delete req.query._sort;
|
||||
delete req.query._order;
|
||||
delete req.query._limit;
|
||||
delete req.query._embed;
|
||||
delete req.query._expand; // Automatically delete query parameters that can't be found
|
||||
// in the database
|
||||
|
||||
Object.keys(req.query).forEach(query => {
|
||||
const arr = db.get(name).value();
|
||||
|
||||
for (const i in arr) {
|
||||
if (_.has(arr[i], query) || query === 'callback' || query === '_' || /_lte$/.test(query) || /_gte$/.test(query) || /_ne$/.test(query) || /_like$/.test(query)) return;
|
||||
}
|
||||
|
||||
delete req.query[query];
|
||||
});
|
||||
|
||||
if (q) {
|
||||
// Full-text search
|
||||
if (Array.isArray(q)) {
|
||||
q = q[0];
|
||||
}
|
||||
|
||||
q = q.toLowerCase();
|
||||
chain = chain.filter(obj => {
|
||||
for (const key in obj) {
|
||||
const value = obj[key];
|
||||
|
||||
if (db._.deepQuery(value, q)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(req.query).forEach(key => {
|
||||
// Don't take into account JSONP query parameters
|
||||
// jQuery adds a '_' query parameter too
|
||||
if (key !== 'callback' && key !== '_') {
|
||||
// Always use an array, in case req.query is an array
|
||||
const arr = [].concat(req.query[key]);
|
||||
const isDifferent = /_ne$/.test(key);
|
||||
const isRange = /_lte$/.test(key) || /_gte$/.test(key);
|
||||
const isLike = /_like$/.test(key);
|
||||
const path = key.replace(/(_lte|_gte|_ne|_like)$/, '');
|
||||
chain = chain.filter(element => {
|
||||
return arr.map(function (value) {
|
||||
// get item value based on path
|
||||
// i.e post.title -> 'foo'
|
||||
const elementValue = _.get(element, path); // Prevent toString() failing on undefined or null values
|
||||
|
||||
|
||||
if (elementValue === undefined || elementValue === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRange) {
|
||||
const isLowerThan = /_gte$/.test(key);
|
||||
return isLowerThan ? value <= elementValue : value >= elementValue;
|
||||
} else if (isDifferent) {
|
||||
return value !== elementValue.toString();
|
||||
} else if (isLike) {
|
||||
return new RegExp(value, 'i').test(elementValue.toString());
|
||||
} else {
|
||||
return value === elementValue.toString();
|
||||
}
|
||||
}).reduce((a, b) => isDifferent ? a && b : a || b);
|
||||
});
|
||||
}
|
||||
}); // Sort
|
||||
|
||||
if (_sort) {
|
||||
const _sortSet = _sort.split(',');
|
||||
|
||||
const _orderSet = (_order || '').split(',').map(s => s.toLowerCase());
|
||||
|
||||
chain = chain.orderBy(_sortSet, _orderSet);
|
||||
} // Slice result
|
||||
|
||||
|
||||
if (_end || _limit || _page) {
|
||||
res.setHeader('X-Total-Count', chain.size());
|
||||
res.setHeader('Access-Control-Expose-Headers', `X-Total-Count${_page ? ', Link' : ''}`);
|
||||
}
|
||||
|
||||
if (_page) {
|
||||
_page = parseInt(_page, 10);
|
||||
_page = _page >= 1 ? _page : 1;
|
||||
_limit = parseInt(_limit, 10) || 10;
|
||||
const page = utils.getPage(chain.value(), _page, _limit);
|
||||
const links = {};
|
||||
const fullURL = getFullURL(req);
|
||||
|
||||
if (page.first) {
|
||||
links.first = fullURL.replace(`page=${page.current}`, `page=${page.first}`);
|
||||
}
|
||||
|
||||
if (page.prev) {
|
||||
links.prev = fullURL.replace(`page=${page.current}`, `page=${page.prev}`);
|
||||
}
|
||||
|
||||
if (page.next) {
|
||||
links.next = fullURL.replace(`page=${page.current}`, `page=${page.next}`);
|
||||
}
|
||||
|
||||
if (page.last) {
|
||||
links.last = fullURL.replace(`page=${page.current}`, `page=${page.last}`);
|
||||
}
|
||||
|
||||
res.links(links);
|
||||
chain = _.chain(page.items);
|
||||
} else if (_end) {
|
||||
_start = parseInt(_start, 10) || 0;
|
||||
_end = parseInt(_end, 10);
|
||||
chain = chain.slice(_start, _end);
|
||||
} else if (_limit) {
|
||||
_start = parseInt(_start, 10) || 0;
|
||||
_limit = parseInt(_limit, 10);
|
||||
chain = chain.slice(_start, _start + _limit);
|
||||
} // embed and expand
|
||||
|
||||
|
||||
chain = chain.cloneDeep().forEach(function (element) {
|
||||
embed(element, _embed);
|
||||
expand(element, _expand);
|
||||
});
|
||||
res.locals.data = chain.value();
|
||||
next();
|
||||
} // GET /name/:id
|
||||
// GET /name/:id?_embed=&_expand
|
||||
|
||||
|
||||
function show(req, res, next) {
|
||||
const _embed = req.query._embed;
|
||||
const _expand = req.query._expand;
|
||||
const resource = db.get(name).getById(req.params.id).value();
|
||||
|
||||
if (resource) {
|
||||
// Clone resource to avoid making changes to the underlying object
|
||||
const clone = _.cloneDeep(resource); // Embed other resources based on resource id
|
||||
// /posts/1?_embed=comments
|
||||
|
||||
|
||||
embed(clone, _embed); // Expand inner resources based on id
|
||||
// /posts/1?_expand=user
|
||||
|
||||
expand(clone, _expand);
|
||||
res.locals.data = clone;
|
||||
}
|
||||
|
||||
next();
|
||||
} // POST /name
|
||||
|
||||
|
||||
function create(req, res, next) {
|
||||
let resource;
|
||||
|
||||
if (opts._isFake) {
|
||||
const id = db.get(name).createId().value();
|
||||
resource = _objectSpread({}, req.body, {
|
||||
id
|
||||
});
|
||||
} else {
|
||||
resource = db.get(name).insert(req.body).value();
|
||||
}
|
||||
|
||||
res.setHeader('Access-Control-Expose-Headers', 'Location');
|
||||
res.location(`${getFullURL(req)}/${resource.id}`);
|
||||
res.status(201);
|
||||
res.locals.data = resource;
|
||||
next();
|
||||
} // PUT /name/:id
|
||||
// PATCH /name/:id
|
||||
|
||||
|
||||
function update(req, res, next) {
|
||||
const id = req.params.id;
|
||||
let resource;
|
||||
|
||||
if (opts._isFake) {
|
||||
resource = db.get(name).getById(id).value();
|
||||
|
||||
if (req.method === 'PATCH') {
|
||||
resource = _objectSpread({}, resource, {}, req.body);
|
||||
} else {
|
||||
resource = _objectSpread({}, req.body, {
|
||||
id: resource.id
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let chain = db.get(name);
|
||||
chain = req.method === 'PATCH' ? chain.updateById(id, req.body) : chain.replaceById(id, req.body);
|
||||
resource = chain.value();
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
res.locals.data = resource;
|
||||
}
|
||||
|
||||
next();
|
||||
} // DELETE /name/:id
|
||||
|
||||
|
||||
function destroy(req, res, next) {
|
||||
let resource;
|
||||
|
||||
if (opts._isFake) {
|
||||
resource = db.get(name).value();
|
||||
} else {
|
||||
resource = db.get(name).removeById(req.params.id).value(); // Remove dependents documents
|
||||
|
||||
const removable = db._.getRemovable(db.getState(), opts);
|
||||
|
||||
removable.forEach(item => {
|
||||
db.get(item.name).removeById(item.id).value();
|
||||
});
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
res.locals.data = {};
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
const w = write(db);
|
||||
router.route('/').get(list).post(create, w);
|
||||
router.route('/:id').get(show).put(update, w).patch(update, w).delete(destroy, w);
|
||||
return router;
|
||||
};
|
||||
64
node_modules/json-server/lib/server/router/singular.js
generated
vendored
Normal file
64
node_modules/json-server/lib/server/router/singular.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
|
||||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
const express = require('express');
|
||||
|
||||
const write = require('./write');
|
||||
|
||||
const getFullURL = require('./get-full-url');
|
||||
|
||||
const delay = require('./delay');
|
||||
|
||||
module.exports = (db, name, opts) => {
|
||||
const router = express.Router();
|
||||
router.use(delay);
|
||||
|
||||
function show(req, res, next) {
|
||||
res.locals.data = db.get(name).value();
|
||||
next();
|
||||
}
|
||||
|
||||
function create(req, res, next) {
|
||||
if (opts._isFake) {
|
||||
res.locals.data = req.body;
|
||||
} else {
|
||||
db.set(name, req.body).value();
|
||||
res.locals.data = db.get(name).value();
|
||||
}
|
||||
|
||||
res.setHeader('Access-Control-Expose-Headers', 'Location');
|
||||
res.location(`${getFullURL(req)}`);
|
||||
res.status(201);
|
||||
next();
|
||||
}
|
||||
|
||||
function update(req, res, next) {
|
||||
if (opts._isFake) {
|
||||
if (req.method === 'PUT') {
|
||||
res.locals.data = req.body;
|
||||
} else {
|
||||
const resource = db.get(name).value();
|
||||
res.locals.data = _objectSpread({}, resource, {}, req.body);
|
||||
}
|
||||
} else {
|
||||
if (req.method === 'PUT') {
|
||||
db.set(name, req.body).value();
|
||||
} else {
|
||||
db.get(name).assign(req.body).value();
|
||||
}
|
||||
|
||||
res.locals.data = db.get(name).value();
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
const w = write(db);
|
||||
router.route('/').get(show).post(create, w).put(update, w).patch(update, w);
|
||||
return router;
|
||||
};
|
||||
18
node_modules/json-server/lib/server/router/validate-data.js
generated
vendored
Normal file
18
node_modules/json-server/lib/server/router/validate-data.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
function validateKey(key) {
|
||||
if (key.indexOf('/') !== -1) {
|
||||
const msg = [`Oops, found / character in database property '${key}'.`, '', "/ aren't supported, if you want to tweak default routes, see", 'https://github.com/typicode/json-server/#add-custom-routes'].join('\n');
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = obj => {
|
||||
if (_.isPlainObject(obj)) {
|
||||
Object.keys(obj).forEach(validateKey);
|
||||
} else {
|
||||
throw new Error(`Data must be an object. Found ${typeof obj}.` + 'See https://github.com/typicode/json-server for example.');
|
||||
}
|
||||
};
|
||||
8
node_modules/json-server/lib/server/router/write.js
generated
vendored
Normal file
8
node_modules/json-server/lib/server/router/write.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function write(db) {
|
||||
return (req, res, next) => {
|
||||
db.write();
|
||||
next();
|
||||
};
|
||||
};
|
||||
32
node_modules/json-server/lib/server/utils.js
generated
vendored
Normal file
32
node_modules/json-server/lib/server/utils.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
getPage
|
||||
};
|
||||
|
||||
function getPage(array, page, perPage) {
|
||||
var obj = {};
|
||||
var start = (page - 1) * perPage;
|
||||
var end = page * perPage;
|
||||
obj.items = array.slice(start, end);
|
||||
|
||||
if (obj.items.length === 0) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (page > 1) {
|
||||
obj.prev = page - 1;
|
||||
}
|
||||
|
||||
if (end < array.length) {
|
||||
obj.next = page + 1;
|
||||
}
|
||||
|
||||
if (obj.items.length !== array.length) {
|
||||
obj.current = page;
|
||||
obj.first = 1;
|
||||
obj.last = Math.ceil(array.length / perPage);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
152
node_modules/json-server/package.json
generated
vendored
Normal file
152
node_modules/json-server/package.json
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"_from": "json-server",
|
||||
"_id": "json-server@0.15.1",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-6Vc6tC1uLasnMd6Ksnq+4gSQcRqLuSJ/yLoIG4fr4P8f5dAR1gbCqgaVRlk8jfRune0NXcrfDrz7liwAD2WEeQ==",
|
||||
"_location": "/json-server",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "json-server",
|
||||
"name": "json-server",
|
||||
"escapedName": "json-server",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/json-server/-/json-server-0.15.1.tgz",
|
||||
"_shasum": "5d77575f1e15db20a361e0ed0a64bfbc3df11171",
|
||||
"_spec": "json-server",
|
||||
"_where": "/Users/nate/code/pluralsight/async-programming-promises",
|
||||
"author": {
|
||||
"name": "Typicode",
|
||||
"email": "typicode@gmail.com"
|
||||
},
|
||||
"bin": {
|
||||
"json-server": "./lib/cli/bin.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/typicode/json-server/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"chalk": "^2.4.2",
|
||||
"compression": "^1.7.4",
|
||||
"connect-pause": "^0.1.1",
|
||||
"cors": "^2.8.5",
|
||||
"errorhandler": "^1.5.1",
|
||||
"express": "^4.17.1",
|
||||
"express-urlrewrite": "^1.2.0",
|
||||
"json-parse-helpfulerror": "^1.0.3",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash-id": "^0.14.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"method-override": "^3.0.0",
|
||||
"morgan": "^1.9.1",
|
||||
"nanoid": "^2.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"request": "^2.88.0",
|
||||
"server-destroy": "^1.0.1",
|
||||
"update-notifier": "^3.0.1",
|
||||
"yargs": "^14.0.0"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Serves JSON files through REST routes.",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.5.5",
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/node": "^7.5.5",
|
||||
"@babel/plugin-transform-regenerator": "^7.4.5",
|
||||
"@babel/polyfill": "^7.4.4",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/register": "^7.5.5",
|
||||
"babel-loader": "^8.0.6",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"css-loader": "^3.2.0",
|
||||
"eslint": "^6.3.0",
|
||||
"eslint-config-prettier": "^6.1.0",
|
||||
"eslint-config-standard": "^14.1.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-node": "^9.2.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"husky": "^3.0.5",
|
||||
"jest": "^24.9.0",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"os-tmpdir": "^2.0.0",
|
||||
"pkg-ok": "^2.3.1",
|
||||
"prettier": "^1.18.2",
|
||||
"promise-polyfill": "^8.1.3",
|
||||
"rimraf": "^3.0.0",
|
||||
"server-ready": "^0.3.1",
|
||||
"supertest": "^4.0.2",
|
||||
"temp-write": "^4.0.0",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-cli": "^3.3.7",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"homepage": "https://github.com/typicode/json-server",
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm test"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"testURL": "http://localhost/"
|
||||
},
|
||||
"keywords": [
|
||||
"JSON",
|
||||
"server",
|
||||
"fake",
|
||||
"REST",
|
||||
"API",
|
||||
"prototyping",
|
||||
"mock",
|
||||
"mocking",
|
||||
"test",
|
||||
"testing",
|
||||
"rest",
|
||||
"data",
|
||||
"dummy",
|
||||
"sandbox"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./lib/server/index.js",
|
||||
"name": "json-server",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/typicode/json-server.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src -d lib && webpack -p",
|
||||
"fix": "npm run lint -- --fix",
|
||||
"lint": "eslint . --ignore-path .gitignore",
|
||||
"prepublishOnly": "npm test && npm run build && pkg-ok",
|
||||
"start": "run-p start:**",
|
||||
"start:babel-node": "babel-node src/cli/bin db.json -r routes.json",
|
||||
"start:webpack": "webpack -d --watch",
|
||||
"test": "npm run build && cross-env NODE_ENV=test jest && npm run lint",
|
||||
"toc": "markdown-toc -i README.md"
|
||||
},
|
||||
"version": "0.15.1"
|
||||
}
|
||||
10
node_modules/json-server/postinstall.js
generated
vendored
Normal file
10
node_modules/json-server/postinstall.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
const chalk = require('chalk')
|
||||
|
||||
console.log(
|
||||
'Like JSON Server? You can support the project on',
|
||||
chalk.bold('GitHub Sponsors')
|
||||
)
|
||||
console.log(
|
||||
chalk.underline('https://github.com/users/typicode/sponsorship'),
|
||||
chalk.red('❤')
|
||||
)
|
||||
5
node_modules/json-server/routes.json
generated
vendored
Normal file
5
node_modules/json-server/routes.json
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"/api/": "/",
|
||||
"/blog/:resource/:id/show": "/:resource/:id",
|
||||
"/blog/:category": "/posts?category=:category"
|
||||
}
|
||||
21
node_modules/json-server/webpack.config.js
generated
vendored
Normal file
21
node_modules/json-server/webpack.config.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
|
||||
module.exports = {
|
||||
entry: './src/front/index.js',
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
|
||||
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
favicon: 'src/front/favicon.ico',
|
||||
template: 'src/front/index.html'
|
||||
}),
|
||||
new MiniCssExtractPlugin()
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user