Roughing out the demo app

This commit is contained in:
Nate Taylor
2019-10-23 07:41:03 -05:00
parent 5bc58a2d40
commit 94be06d3c4
2841 changed files with 274065 additions and 2 deletions

6
node_modules/json-server/lib/cli/bin.js generated vendored Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
};

View 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
View 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
View 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
View 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
View 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;
};

View 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
View 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
View 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;
}