mirror of
https://github.com/typicode/json-server.git
synced 2025-07-29 13:14:12 +08:00
ES2015
This commit is contained in:
2
.babelrc
2
.babelrc
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"presets": [
|
"presets": [
|
||||||
"es2015"
|
["es2015", { "loose": true }]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
14
package.json
14
package.json
@ -39,14 +39,14 @@
|
|||||||
"os-tmpdir": "^1.0.1",
|
"os-tmpdir": "^1.0.1",
|
||||||
"rimraf": "^2.5.2",
|
"rimraf": "^2.5.2",
|
||||||
"server-ready": "^0.2.0",
|
"server-ready": "^0.2.0",
|
||||||
"standard": "^7.1.2",
|
"standard": "^8.3.0",
|
||||||
"supertest": "^1.2.0",
|
"supertest": "^1.2.0",
|
||||||
"temp-write": "^2.1.0"
|
"temp-write": "^2.1.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run test:cli && npm run test:server && standard",
|
"test": "npm run test:cli && npm run test:server && standard",
|
||||||
"test:cli": "cross-env NODE_ENV=test mocha -R spec test/cli/*.js",
|
"test:cli": "cross-env NODE_ENV=test mocha test/cli/*.js",
|
||||||
"test:server": "cross-env NODE_ENV=test mocha -R spec test/server/*.js",
|
"test:server": "cross-env NODE_ENV=test mocha test/server/*.js",
|
||||||
"start": "node bin",
|
"start": "node bin",
|
||||||
"prepush": "npm t",
|
"prepush": "npm t",
|
||||||
"build": "babel src -d lib"
|
"build": "babel src -d lib"
|
||||||
@ -76,5 +76,11 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/typicode/json-server/issues"
|
"url": "https://github.com/typicode/json-server/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/typicode/json-server"
|
"homepage": "https://github.com/typicode/json-server",
|
||||||
|
"standard": {
|
||||||
|
"fix": true,
|
||||||
|
"env": {
|
||||||
|
"mocha": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
var updateNotifier = require('update-notifier')
|
const updateNotifier = require('update-notifier')
|
||||||
var yargs = require('yargs')
|
const yargs = require('yargs')
|
||||||
var run = require('./run')
|
const run = require('./run')
|
||||||
var pkg = require('../../package.json')
|
const pkg = require('../../package.json')
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
updateNotifier({ pkg: pkg }).notify()
|
updateNotifier({ pkg }).notify()
|
||||||
|
|
||||||
var argv = yargs
|
const argv = yargs
|
||||||
.config('config')
|
.config('config')
|
||||||
.usage('$0 [options] <source>')
|
.usage('$0 [options] <source>')
|
||||||
.options({
|
.options({
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
var fs = require('fs')
|
const fs = require('fs')
|
||||||
var path = require('path')
|
const path = require('path')
|
||||||
var _ = require('lodash')
|
const _ = require('lodash')
|
||||||
var chalk = require('chalk')
|
const chalk = require('chalk')
|
||||||
var chokidar = require('chokidar')
|
const chokidar = require('chokidar')
|
||||||
var enableDestroy = require('server-destroy')
|
const enableDestroy = require('server-destroy')
|
||||||
var pause = require('connect-pause')
|
const pause = require('connect-pause')
|
||||||
var is = require('./utils/is')
|
const is = require('./utils/is')
|
||||||
var load = require('./utils/load')
|
const load = require('./utils/load')
|
||||||
var jsonServer = require('../server')
|
const jsonServer = require('../server')
|
||||||
|
|
||||||
function prettyPrint (argv, object, rules) {
|
function prettyPrint (argv, object, rules) {
|
||||||
var host = argv.host === '0.0.0.0' ? 'localhost' : argv.host
|
const host = argv.host === '0.0.0.0' ? 'localhost' : argv.host
|
||||||
var port = argv.port
|
const port = argv.port
|
||||||
var root = 'http://' + host + ':' + port
|
const root = `http://${host}:${port}`
|
||||||
|
|
||||||
console.log()
|
console.log()
|
||||||
console.log(chalk.bold(' Resources'))
|
console.log(chalk.bold(' Resources'))
|
||||||
for (var prop in object) {
|
for (let prop in object) {
|
||||||
console.log(' ' + root + '/' + prop)
|
console.log(' ' + root + '/' + prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,15 +35,15 @@ function prettyPrint (argv, object, rules) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createApp (source, object, routes, middlewares, argv) {
|
function createApp (source, object, routes, middlewares, argv) {
|
||||||
var app = jsonServer.create()
|
const app = jsonServer.create()
|
||||||
|
|
||||||
var router = jsonServer.router(
|
const router = jsonServer.router(
|
||||||
is.JSON(source)
|
is.JSON(source)
|
||||||
? source
|
? source
|
||||||
: object
|
: object
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultsOpts = {
|
const defaultsOpts = {
|
||||||
logger: !argv.quiet,
|
logger: !argv.quiet,
|
||||||
readOnly: argv.readOnly,
|
readOnly: argv.readOnly,
|
||||||
noCors: argv.noCors,
|
noCors: argv.noCors,
|
||||||
@ -54,11 +54,11 @@ function createApp (source, object, routes, middlewares, argv) {
|
|||||||
defaultsOpts.static = path.join(process.cwd(), argv.static)
|
defaultsOpts.static = path.join(process.cwd(), argv.static)
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaults = jsonServer.defaults(defaultsOpts)
|
const defaults = jsonServer.defaults(defaultsOpts)
|
||||||
app.use(defaults)
|
app.use(defaults)
|
||||||
|
|
||||||
if (routes) {
|
if (routes) {
|
||||||
var rewriter = jsonServer.rewriter(routes)
|
const rewriter = jsonServer.rewriter(routes)
|
||||||
app.use(rewriter)
|
app.use(rewriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,18 +78,18 @@ function createApp (source, object, routes, middlewares, argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function (argv) {
|
module.exports = function (argv) {
|
||||||
var source = argv._[0]
|
const source = argv._[0]
|
||||||
var app
|
let app
|
||||||
var server
|
let server
|
||||||
|
|
||||||
if (!fs.existsSync(argv.snapshots)) {
|
if (!fs.existsSync(argv.snapshots)) {
|
||||||
console.log('Error: snapshots directory ' + argv.snapshots + ' doesn\'t exist')
|
console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// noop log fn
|
// noop log fn
|
||||||
if (argv.quiet) {
|
if (argv.quiet) {
|
||||||
console.log = function () {}
|
console.log = () => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log()
|
console.log()
|
||||||
@ -100,17 +100,18 @@ module.exports = function (argv) {
|
|||||||
console.log(chalk.gray(' Loading', source))
|
console.log(chalk.gray(' Loading', source))
|
||||||
|
|
||||||
// Load JSON, JS or HTTP database
|
// Load JSON, JS or HTTP database
|
||||||
load(source, function (err, data) {
|
load(source, (err, data) => {
|
||||||
if (err) throw err
|
if (err) throw err
|
||||||
|
|
||||||
// Load additional routes
|
// Load additional routes
|
||||||
|
let routes
|
||||||
if (argv.routes) {
|
if (argv.routes) {
|
||||||
console.log(chalk.gray(' Loading', argv.routes))
|
console.log(chalk.gray(' Loading', argv.routes))
|
||||||
var routes = JSON.parse(fs.readFileSync(argv.routes))
|
routes = JSON.parse(fs.readFileSync(argv.routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load middlewares
|
// Load middlewares
|
||||||
var middlewares
|
let middlewares
|
||||||
if (argv.middlewares) {
|
if (argv.middlewares) {
|
||||||
middlewares = argv.middlewares.map(function (m) {
|
middlewares = argv.middlewares.map(function (m) {
|
||||||
console.log(chalk.gray(' Loading', m))
|
console.log(chalk.gray(' Loading', m))
|
||||||
@ -136,7 +137,7 @@ module.exports = function (argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
start(function () {
|
start(() => {
|
||||||
// Snapshot
|
// Snapshot
|
||||||
console.log(
|
console.log(
|
||||||
chalk.gray(' Type s + enter at any time to create a snapshot of the database')
|
chalk.gray(' Type s + enter at any time to create a snapshot of the database')
|
||||||
@ -144,13 +145,13 @@ module.exports = function (argv) {
|
|||||||
|
|
||||||
process.stdin.resume()
|
process.stdin.resume()
|
||||||
process.stdin.setEncoding('utf8')
|
process.stdin.setEncoding('utf8')
|
||||||
process.stdin.on('data', function (chunk) {
|
process.stdin.on('data', (chunk) => {
|
||||||
if (chunk.trim().toLowerCase() === 's') {
|
if (chunk.trim().toLowerCase() === 's') {
|
||||||
var filename = 'db-' + Date.now() + '.json'
|
const filename = 'db-' + Date.now() + '.json'
|
||||||
var file = path.join(argv.snapshots, filename)
|
const file = path.join(argv.snapshots, filename)
|
||||||
var state = app.db.getState()
|
const state = app.db.getState()
|
||||||
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
|
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
|
||||||
console.log(' Saved snapshot to ' + path.relative(process.cwd(), file) + '\n')
|
console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ module.exports = function (argv) {
|
|||||||
if (argv.watch) {
|
if (argv.watch) {
|
||||||
console.log(chalk.gray(' Watching...'))
|
console.log(chalk.gray(' Watching...'))
|
||||||
console.log()
|
console.log()
|
||||||
var source = argv._[0]
|
const source = argv._[0]
|
||||||
|
|
||||||
// Can't watch URL
|
// Can't watch URL
|
||||||
if (is.URL(source)) throw new Error('Can\'t watch URL')
|
if (is.URL(source)) throw new Error('Can\'t watch URL')
|
||||||
@ -167,19 +168,19 @@ module.exports = function (argv) {
|
|||||||
// Since lowdb uses atomic writing, directory is watched instead of file
|
// Since lowdb uses atomic writing, directory is watched instead of file
|
||||||
chokidar
|
chokidar
|
||||||
.watch(path.dirname(source))
|
.watch(path.dirname(source))
|
||||||
.on('change', function (file) {
|
.on('change', (file) => {
|
||||||
if (path.resolve(file) === path.resolve(source)) {
|
if (path.resolve(file) === path.resolve(source)) {
|
||||||
if (is.JSON(file)) {
|
if (is.JSON(file)) {
|
||||||
var obj = JSON.parse(fs.readFileSync(file))
|
var obj = JSON.parse(fs.readFileSync(file))
|
||||||
// Compare .json file content with in memory database
|
// Compare .json file content with in memory database
|
||||||
var isDatabaseDifferent = !_.isEqual(obj, app.db.getState())
|
var isDatabaseDifferent = !_.isEqual(obj, app.db.getState())
|
||||||
if (isDatabaseDifferent) {
|
if (isDatabaseDifferent) {
|
||||||
console.log(chalk.gray(' ' + file + ' has changed, reloading...'))
|
console.log(chalk.gray(` ${file} has changed, reloading...`))
|
||||||
server && server.destroy()
|
server && server.destroy()
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(chalk.gray(' ' + file + ' has changed, reloading...'))
|
console.log(chalk.gray(` ${file} has changed, reloading...`))
|
||||||
server && server.destroy()
|
server && server.destroy()
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
@ -190,8 +191,8 @@ module.exports = function (argv) {
|
|||||||
if (argv.routes) {
|
if (argv.routes) {
|
||||||
chokidar
|
chokidar
|
||||||
.watch(argv.routes)
|
.watch(argv.routes)
|
||||||
.on('change', function (file) {
|
.on('change', (file) => {
|
||||||
console.log(chalk.gray(' ' + file + ' has changed, reloading...'))
|
console.log(chalk.gray(` ${file} has changed, reloading...`))
|
||||||
server && server.destroy()
|
server && server.destroy()
|
||||||
start()
|
start()
|
||||||
})
|
})
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
JSON: isJSON,
|
JSON,
|
||||||
JS: isJS,
|
JS,
|
||||||
URL: isURL
|
URL
|
||||||
}
|
}
|
||||||
|
|
||||||
function isJSON (s) {
|
function JSON (s) {
|
||||||
return !isURL(s) && /\.json$/.test(s)
|
return !URL(s) && /\.json$/.test(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isJS (s) {
|
function JS (s) {
|
||||||
return !isURL(s) && /\.js$/.test(s)
|
return !URL(s) && /\.js$/.test(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isURL (s) {
|
function URL (s) {
|
||||||
return /^(http|https):/.test(s)
|
return /^(http|https):/.test(s)
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,37 @@
|
|||||||
var path = require('path')
|
const path = require('path')
|
||||||
var request = require('request')
|
const request = require('request')
|
||||||
var low = require('lowdb')
|
const low = require('lowdb')
|
||||||
var fileAsync = require('lowdb/lib/file-async')
|
const fileAsync = require('lowdb/lib/file-async')
|
||||||
var is = require('./is')
|
const is = require('./is')
|
||||||
|
|
||||||
module.exports = function (source, cb) {
|
module.exports = function (source, cb) {
|
||||||
var data
|
|
||||||
|
|
||||||
if (is.URL(source)) {
|
if (is.URL(source)) {
|
||||||
request({ url: source, json: true }, function (err, response) {
|
// Load remote data
|
||||||
|
const opts = {
|
||||||
|
url: source,
|
||||||
|
json: true
|
||||||
|
}
|
||||||
|
|
||||||
|
request(opts, (err, response) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
cb(null, response.body)
|
cb(null, response.body)
|
||||||
})
|
})
|
||||||
} else if (is.JS(source)) {
|
} else if (is.JS(source)) {
|
||||||
var filename = path.resolve(source)
|
// Clear cache
|
||||||
|
const filename = path.resolve(source)
|
||||||
delete require.cache[filename]
|
delete require.cache[filename]
|
||||||
var dataFn = require(filename)
|
const dataFn = require(filename)
|
||||||
|
|
||||||
if (typeof dataFn !== 'function') {
|
if (typeof dataFn !== 'function') {
|
||||||
throw new Error('The database is a JavaScript file but the export is not a function.')
|
throw new Error('The database is a JavaScript file but the export is not a function.')
|
||||||
}
|
}
|
||||||
|
|
||||||
data = dataFn()
|
// Run dataFn to generate data
|
||||||
|
const data = dataFn()
|
||||||
cb(null, data)
|
cb(null, data)
|
||||||
} else if (is.JSON(source)) {
|
} else if (is.JSON(source)) {
|
||||||
data = low(source, { storage: fileAsync }).getState()
|
// Load JSON using lowdb
|
||||||
|
const data = low(source, { storage: fileAsync }).getState()
|
||||||
cb(null, data)
|
cb(null, data)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unsupported source ' + source)
|
throw new Error('Unsupported source ' + source)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
var bodyParser = require('body-parser')
|
const bodyParser = require('body-parser')
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
bodyParser.json({limit: '10mb', extended: false}),
|
bodyParser.json({limit: '10mb', extended: false}),
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
var fs = require('fs')
|
const fs = require('fs')
|
||||||
var path = require('path')
|
const path = require('path')
|
||||||
var express = require('express')
|
const express = require('express')
|
||||||
var logger = require('morgan')
|
const logger = require('morgan')
|
||||||
var cors = require('cors')
|
const cors = require('cors')
|
||||||
var compression = require('compression')
|
const compression = require('compression')
|
||||||
var errorhandler = require('errorhandler')
|
const errorhandler = require('errorhandler')
|
||||||
var objectAssign = require('object-assign')
|
const objectAssign = require('object-assign')
|
||||||
|
|
||||||
module.exports = function (opts) {
|
module.exports = function (opts) {
|
||||||
var userDir = path.join(process.cwd(), 'public')
|
const userDir = path.join(process.cwd(), 'public')
|
||||||
var defaultDir = path.join(__dirname, 'public')
|
const defaultDir = path.join(__dirname, 'public')
|
||||||
var staticDir = fs.existsSync(userDir)
|
const staticDir = fs.existsSync(userDir)
|
||||||
? userDir
|
? userDir
|
||||||
: defaultDir
|
: defaultDir
|
||||||
|
|
||||||
opts = objectAssign({ logger: true, static: staticDir }, opts)
|
opts = objectAssign({ logger: true, static: staticDir }, opts)
|
||||||
|
|
||||||
var arr = []
|
const arr = []
|
||||||
|
|
||||||
// Compress all requests
|
// Compress all requests
|
||||||
if (!opts.noGzip) {
|
if (!opts.noGzip) {
|
||||||
@ -25,12 +25,14 @@ module.exports = function (opts) {
|
|||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
if (opts.logger) {
|
if (opts.logger) {
|
||||||
arr.push(logger('dev', {
|
arr.push(
|
||||||
skip: function (req, res) {
|
logger('dev', {
|
||||||
return process.env.NODE_ENV === 'test' ||
|
skip: (req) => (
|
||||||
|
process.env.NODE_ENV === 'test' ||
|
||||||
req.path === '/favicon.ico'
|
req.path === '/favicon.ico'
|
||||||
}
|
)
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable CORS for all the requests, including static files
|
// Enable CORS for all the requests, including static files
|
||||||
@ -48,7 +50,7 @@ module.exports = function (opts) {
|
|||||||
|
|
||||||
// No cache for IE
|
// No cache for IE
|
||||||
// https://support.microsoft.com/en-us/kb/234067
|
// https://support.microsoft.com/en-us/kb/234067
|
||||||
arr.push(function (req, res, next) {
|
arr.push((req, res, next) => {
|
||||||
res.header('Cache-Control', 'no-cache')
|
res.header('Cache-Control', 'no-cache')
|
||||||
res.header('Pragma', 'no-cache')
|
res.header('Pragma', 'no-cache')
|
||||||
res.header('Expires', '-1')
|
res.header('Expires', '-1')
|
||||||
@ -57,7 +59,7 @@ module.exports = function (opts) {
|
|||||||
|
|
||||||
// Read-only
|
// Read-only
|
||||||
if (opts.readOnly) {
|
if (opts.readOnly) {
|
||||||
arr.push(function (req, res, next) {
|
arr.push((req, res, next) => {
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
next() // Continue
|
next() // Continue
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
var express = require('express')
|
const express = require('express')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
create: function () {
|
create: () => express().set('json spaces', 2),
|
||||||
var server = express()
|
|
||||||
server.set('json spaces', 2)
|
|
||||||
return server
|
|
||||||
},
|
|
||||||
defaults: require('./defaults'),
|
defaults: require('./defaults'),
|
||||||
router: require('./router'),
|
router: require('./router'),
|
||||||
rewriter: require('./rewriter'),
|
rewriter: require('./rewriter'),
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
var uuid = require('node-uuid')
|
const uuid = require('node-uuid')
|
||||||
var pluralize = require('pluralize')
|
const pluralize = require('pluralize')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getRemovable: getRemovable,
|
getRemovable,
|
||||||
createId: createId,
|
createId,
|
||||||
deepQuery: deepQuery
|
deepQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns document ids that have unsatisfied relations
|
// Returns document ids that have unsatisfied relations
|
||||||
// Example: a comment that references a post that doesn't exist
|
// Example: a comment that references a post that doesn't exist
|
||||||
function getRemovable (db) {
|
function getRemovable (db) {
|
||||||
var _ = this
|
const _ = this
|
||||||
var removable = []
|
const removable = []
|
||||||
_.each(db, function (coll, collName) {
|
_.each(db, (coll, collName) => {
|
||||||
_.each(coll, function (doc) {
|
_.each(coll, (doc) => {
|
||||||
_.each(doc, function (value, key) {
|
_.each(doc, (value, key) => {
|
||||||
if (/Id$/.test(key)) {
|
if (/Id$/.test(key)) {
|
||||||
var refName = pluralize.plural(key.slice(0, -2))
|
const refName = pluralize.plural(key.slice(0, -2))
|
||||||
// Test if table exists
|
// Test if table exists
|
||||||
if (db[refName]) {
|
if (db[refName]) {
|
||||||
// Test if references is defined in table
|
// Test if references is defined in table
|
||||||
var ref = _.getById(db[refName], value)
|
const ref = _.getById(db[refName], value)
|
||||||
if (_.isUndefined(ref)) {
|
if (_.isUndefined(ref)) {
|
||||||
removable.push({name: collName, id: doc.id})
|
removable.push({ name: collName, id: doc.id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,36 +36,31 @@ function getRemovable (db) {
|
|||||||
// Return incremented id or uuid
|
// Return incremented id or uuid
|
||||||
// Used to override underscore-db's createId with utils.createId
|
// Used to override underscore-db's createId with utils.createId
|
||||||
function createId (coll) {
|
function createId (coll) {
|
||||||
var _ = this
|
const _ = this
|
||||||
var idProperty = _.__id()
|
const idProperty = _.__id()
|
||||||
if (_.isEmpty(coll)) {
|
if (_.isEmpty(coll)) {
|
||||||
return 1
|
return 1
|
||||||
} else {
|
} else {
|
||||||
var id = _.maxBy(coll, function (doc) {
|
let id = _(coll).maxBy(idProperty)[idProperty]
|
||||||
return doc[idProperty]
|
|
||||||
})[idProperty]
|
|
||||||
|
|
||||||
if (_.isFinite(id)) {
|
// Increment integer id or generate string id
|
||||||
// Increment integer id
|
return _.isFinite(id)
|
||||||
return ++id
|
? ++id
|
||||||
} else {
|
: uuid()
|
||||||
// Generate string id
|
|
||||||
return uuid()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deepQuery (value, q) {
|
function deepQuery (value, q) {
|
||||||
var _ = this
|
const _ = this
|
||||||
if (value && q) {
|
if (value && q) {
|
||||||
if (_.isArray(value)) {
|
if (_.isArray(value)) {
|
||||||
for (var i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
if (_.deepQuery(value[i], q)) {
|
if (_.deepQuery(value[i], q)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_.isObject(value) && !_.isArray(value)) {
|
} else if (_.isObject(value) && !_.isArray(value)) {
|
||||||
for (var k in value) {
|
for (let k in value) {
|
||||||
if (_.deepQuery(value[k], q)) {
|
if (_.deepQuery(value[k], q)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
var express = require('express')
|
const express = require('express')
|
||||||
|
|
||||||
module.exports = function (routes) {
|
module.exports = function (routes) {
|
||||||
var router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
Object.keys(routes).forEach(function (route) {
|
Object.keys(routes).forEach((route) => {
|
||||||
if (route.indexOf(':') !== -1) {
|
if (route.indexOf(':') !== -1) {
|
||||||
router.all(route, function (req, res, next) {
|
router.all(route, (req, res, next) => {
|
||||||
// Rewrite target url using params
|
// Rewrite target url using params
|
||||||
var target = routes[route]
|
let target = routes[route]
|
||||||
for (var param in req.params) {
|
for (let param in req.params) {
|
||||||
target = target.replace(':' + param, req.params[param])
|
target = target.replace(':' + param, req.params[param])
|
||||||
}
|
}
|
||||||
req.url = target
|
req.url = target
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
router.all(route + '*', function (req, res, next) {
|
router.all(route + '*', (req, res, next) => {
|
||||||
// Rewrite url by replacing prefix
|
// Rewrite url by replacing prefix
|
||||||
req.url = req.url.replace(route, routes[route])
|
req.url = req.url.replace(route, routes[route])
|
||||||
next()
|
next()
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
var express = require('express')
|
const express = require('express')
|
||||||
var methodOverride = require('method-override')
|
const methodOverride = require('method-override')
|
||||||
var _ = require('lodash')
|
const _ = require('lodash')
|
||||||
var _db = require('underscore-db')
|
const _db = require('underscore-db')
|
||||||
var low = require('lowdb')
|
const low = require('lowdb')
|
||||||
var fileAsync = require('lowdb/lib/file-async')
|
const fileAsync = require('lowdb/lib/file-async')
|
||||||
var bodyParser = require('../body-parser')
|
const bodyParser = require('../body-parser')
|
||||||
var plural = require('./plural')
|
const plural = require('./plural')
|
||||||
var nested = require('./nested')
|
const nested = require('./nested')
|
||||||
var singular = require('./singular')
|
const singular = require('./singular')
|
||||||
var mixins = require('../mixins')
|
const mixins = require('../mixins')
|
||||||
|
|
||||||
module.exports = function (source) {
|
module.exports = (source) => {
|
||||||
// Create router
|
// Create router
|
||||||
var router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
// Add middlewares
|
// Add middlewares
|
||||||
router.use(methodOverride())
|
router.use(methodOverride())
|
||||||
router.use(bodyParser)
|
router.use(bodyParser)
|
||||||
|
|
||||||
// Create database
|
// Create database
|
||||||
var db
|
let db
|
||||||
if (_.isObject(source)) {
|
if (_.isObject(source)) {
|
||||||
db = low()
|
db = low()
|
||||||
db.setState(source)
|
db.setState(source)
|
||||||
@ -37,40 +37,39 @@ module.exports = function (source) {
|
|||||||
router.db = db
|
router.db = db
|
||||||
|
|
||||||
// Expose render
|
// Expose render
|
||||||
router.render = function (req, res) {
|
router.render = (req, res) => {
|
||||||
res.jsonp(res.locals.data)
|
res.jsonp(res.locals.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /db
|
// GET /db
|
||||||
function showDatabase (req, res, next) {
|
router.get('/db', (req, res) => {
|
||||||
res.jsonp(db.getState())
|
res.jsonp(db.getState())
|
||||||
}
|
})
|
||||||
|
|
||||||
router.get('/db', showDatabase)
|
|
||||||
|
|
||||||
|
// Handle /:parent/:parentId/:resource
|
||||||
router.use(nested())
|
router.use(nested())
|
||||||
|
|
||||||
// Create routes
|
// Create routes
|
||||||
db.forEach(function (value, key) {
|
db.forEach((value, key) => {
|
||||||
if (_.isPlainObject(value)) {
|
if (_.isPlainObject(value)) {
|
||||||
router.use('/' + key, singular(db, key))
|
router.use(`/${key}`, singular(db, key))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.isArray(value)) {
|
if (_.isArray(value)) {
|
||||||
router.use('/' + key, plural(db, key))
|
router.use(`/${key}`, plural(db, key))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg =
|
const msg =
|
||||||
'Type of "' + key + '" (' + typeof value + ') ' +
|
`Type of "${key}" (${typeof value}) ` +
|
||||||
(_.isObject(source) ? '' : 'in ' + source) + ' is not supported. ' +
|
(_.isObject(source) ? '' : `in ${source}`) + ' is not supported. ' +
|
||||||
'Use objects or arrays of objects.'
|
'Use objects or arrays of objects.'
|
||||||
|
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}).value()
|
}).value()
|
||||||
|
|
||||||
router.use(function (req, res) {
|
router.use((req, res) => {
|
||||||
if (!res.locals.data) {
|
if (!res.locals.data) {
|
||||||
res.status(404)
|
res.status(404)
|
||||||
res.locals.data = {}
|
res.locals.data = {}
|
||||||
@ -79,7 +78,7 @@ module.exports = function (source) {
|
|||||||
router.render(req, res)
|
router.render(req, res)
|
||||||
})
|
})
|
||||||
|
|
||||||
router.use(function (err, req, res, next) {
|
router.use((err, req, res, next) => {
|
||||||
console.error(err.stack)
|
console.error(err.stack)
|
||||||
res.status(500).send(err.stack)
|
res.status(500).send(err.stack)
|
||||||
})
|
})
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
var express = require('express')
|
const express = require('express')
|
||||||
var pluralize = require('pluralize')
|
const pluralize = require('pluralize')
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = () => {
|
||||||
var router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
||||||
function get (req, res, next) {
|
function get (req, res, next) {
|
||||||
var prop = pluralize.singular(req.params.resource)
|
const prop = pluralize.singular(req.params.resource)
|
||||||
req.query[prop + 'Id'] = req.params.id
|
req.query[`${prop}Id`] = req.params.id
|
||||||
req.url = '/' + req.params.nested
|
req.url = `/${req.params.nested}`
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
|
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
|
||||||
function post (req, res, next) {
|
function post (req, res, next) {
|
||||||
var prop = pluralize.singular(req.params.resource)
|
const prop = pluralize.singular(req.params.resource)
|
||||||
req.body[prop + 'Id'] = req.params.id
|
req.body[`${prop}Id`] = req.params.id
|
||||||
req.url = '/' + req.params.nested
|
req.url = `/${req.params.nested}`
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
var express = require('express')
|
const url = require('url')
|
||||||
var _ = require('lodash')
|
const express = require('express')
|
||||||
var pluralize = require('pluralize')
|
const _ = require('lodash')
|
||||||
var utils = require('../utils')
|
const pluralize = require('pluralize')
|
||||||
|
const utils = require('../utils')
|
||||||
|
|
||||||
module.exports = function (db, name) {
|
module.exports = (db, name) => {
|
||||||
// Create router
|
// Create router
|
||||||
var router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
// Embed function used in GET /name and GET /name/id
|
// Embed function used in GET /name and GET /name/id
|
||||||
function embed (resource, e) {
|
function embed (resource, e) {
|
||||||
e && [].concat(e)
|
e && [].concat(e)
|
||||||
.forEach(function (externalResource) {
|
.forEach((externalResource) => {
|
||||||
if (db.get(externalResource).value) {
|
if (db.get(externalResource).value) {
|
||||||
var query = {}
|
const query = {}
|
||||||
var singularResource = pluralize.singular(name)
|
const singularResource = pluralize.singular(name)
|
||||||
query[singularResource + 'Id'] = resource.id
|
query[`${singularResource}Id`] = resource.id
|
||||||
resource[externalResource] = db.get(externalResource).filter(query).value()
|
resource[externalResource] = db.get(externalResource).filter(query).value()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -23,17 +24,22 @@ module.exports = function (db, name) {
|
|||||||
// Expand function used in GET /name and GET /name/id
|
// Expand function used in GET /name and GET /name/id
|
||||||
function expand (resource, e) {
|
function expand (resource, e) {
|
||||||
e && [].concat(e)
|
e && [].concat(e)
|
||||||
.forEach(function (innerResource) {
|
.forEach((innerResource) => {
|
||||||
var plural = pluralize(innerResource)
|
const plural = pluralize(innerResource)
|
||||||
if (db.get(plural).value()) {
|
if (db.get(plural).value()) {
|
||||||
var prop = innerResource + 'Id'
|
const prop = `${innerResource}Id`
|
||||||
resource[innerResource] = db.get(plural).getById(resource[prop]).value()
|
resource[innerResource] = db.get(plural).getById(resource[prop]).value()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFullURL (req) {
|
function getFullURL (req) {
|
||||||
return req.protocol + '://' + req.get('host') + req.originalUrl
|
const root = url.format({
|
||||||
|
protocol: req.protocol,
|
||||||
|
host: req.get('host')
|
||||||
|
})
|
||||||
|
|
||||||
|
return `${root}${req.originalUrl}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /name
|
// GET /name
|
||||||
@ -44,19 +50,19 @@ module.exports = function (db, name) {
|
|||||||
// GET /name?_embed=&_expand=
|
// GET /name?_embed=&_expand=
|
||||||
function list (req, res, next) {
|
function list (req, res, next) {
|
||||||
// Resource chain
|
// Resource chain
|
||||||
var chain = db.get(name)
|
let chain = db.get(name)
|
||||||
|
|
||||||
// Remove q, _start, _end, ... from req.query to avoid filtering using those
|
// Remove q, _start, _end, ... from req.query to avoid filtering using those
|
||||||
// parameters
|
// parameters
|
||||||
var q = req.query.q
|
let q = req.query.q
|
||||||
var _start = req.query._start
|
let _start = req.query._start
|
||||||
var _end = req.query._end
|
let _end = req.query._end
|
||||||
var _page = req.query._page
|
let _page = req.query._page
|
||||||
var _sort = req.query._sort
|
let _sort = req.query._sort
|
||||||
var _order = req.query._order
|
let _order = req.query._order
|
||||||
var _limit = req.query._limit
|
let _limit = req.query._limit
|
||||||
var _embed = req.query._embed
|
let _embed = req.query._embed
|
||||||
var _expand = req.query._expand
|
let _expand = req.query._expand
|
||||||
delete req.query.q
|
delete req.query.q
|
||||||
delete req.query._start
|
delete req.query._start
|
||||||
delete req.query._end
|
delete req.query._end
|
||||||
@ -68,9 +74,9 @@ module.exports = function (db, name) {
|
|||||||
|
|
||||||
// Automatically delete query parameters that can't be found
|
// Automatically delete query parameters that can't be found
|
||||||
// in the database
|
// in the database
|
||||||
Object.keys(req.query).forEach(function (query) {
|
Object.keys(req.query).forEach((query) => {
|
||||||
var arr = db.get(name).value()
|
const arr = db.get(name).value()
|
||||||
for (var i in arr) {
|
for (let i in arr) {
|
||||||
if (
|
if (
|
||||||
_.has(arr[i], query) ||
|
_.has(arr[i], query) ||
|
||||||
query === 'callback' ||
|
query === 'callback' ||
|
||||||
@ -88,9 +94,9 @@ module.exports = function (db, name) {
|
|||||||
// Full-text search
|
// Full-text search
|
||||||
q = q.toLowerCase()
|
q = q.toLowerCase()
|
||||||
|
|
||||||
chain = chain.filter(function (obj) {
|
chain = chain.filter((obj) => {
|
||||||
for (var key in obj) {
|
for (let key in obj) {
|
||||||
var value = obj[key]
|
const value = obj[key]
|
||||||
if (db._.deepQuery(value, q)) {
|
if (db._.deepQuery(value, q)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -98,34 +104,32 @@ module.exports = function (db, name) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(req.query).forEach(function (key) {
|
Object.keys(req.query).forEach((key) => {
|
||||||
// Don't take into account JSONP query parameters
|
// Don't take into account JSONP query parameters
|
||||||
// jQuery adds a '_' query parameter too
|
// jQuery adds a '_' query parameter too
|
||||||
if (key !== 'callback' && key !== '_') {
|
if (key !== 'callback' && key !== '_') {
|
||||||
// Always use an array, in case req.query is an array
|
// Always use an array, in case req.query is an array
|
||||||
var arr = [].concat(req.query[key])
|
const arr = [].concat(req.query[key])
|
||||||
|
|
||||||
chain = chain.filter(function (element) {
|
chain = chain.filter((element) => {
|
||||||
return arr
|
return arr
|
||||||
.map(function (value) {
|
.map(function (value) {
|
||||||
var isDifferent = key.indexOf('_ne') !== -1
|
const isDifferent = key.indexOf('_ne') !== -1
|
||||||
var isRange = key.indexOf('_lte') !== -1 || key.indexOf('_gte') !== -1
|
const isRange = key.indexOf('_lte') !== -1 || key.indexOf('_gte') !== -1
|
||||||
var isLike = key.indexOf('_like') !== -1
|
const isLike = key.indexOf('_like') !== -1
|
||||||
var path = key.replace(/(_lte|_gte|_ne|_like)$/, '')
|
const path = key.replace(/(_lte|_gte|_ne|_like)$/, '')
|
||||||
var elementValue = _.get(element, path)
|
const elementValue = _.get(element, path)
|
||||||
|
|
||||||
if (!elementValue) {
|
if (!elementValue) {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRange) {
|
if (isRange) {
|
||||||
var isLowerThan = key.indexOf('_gte') !== -1
|
const isLowerThan = key.indexOf('_gte') !== -1
|
||||||
|
|
||||||
if (isLowerThan) {
|
return isLowerThan
|
||||||
return value <= elementValue
|
? value <= elementValue
|
||||||
} else {
|
: value >= elementValue
|
||||||
return value >= elementValue
|
|
||||||
}
|
|
||||||
} else if (isDifferent) {
|
} else if (isDifferent) {
|
||||||
return value !== elementValue.toString()
|
return value !== elementValue.toString()
|
||||||
} else if (isLike) {
|
} else if (isLike) {
|
||||||
@ -133,9 +137,8 @@ module.exports = function (db, name) {
|
|||||||
} else {
|
} else {
|
||||||
return value === elementValue.toString()
|
return value === elementValue.toString()
|
||||||
}
|
}
|
||||||
}).reduce(function (a, b) {
|
|
||||||
return a || b
|
|
||||||
})
|
})
|
||||||
|
.reduce((a, b) => a || b)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -163,9 +166,9 @@ module.exports = function (db, name) {
|
|||||||
_page = parseInt(_page, 10)
|
_page = parseInt(_page, 10)
|
||||||
_page = _page >= 1 ? _page : 1
|
_page = _page >= 1 ? _page : 1
|
||||||
_limit = parseInt(_limit, 10) || 10
|
_limit = parseInt(_limit, 10) || 10
|
||||||
var page = utils.getPage(chain.value(), _page, _limit)
|
const page = utils.getPage(chain.value(), _page, _limit)
|
||||||
var links = {}
|
const links = {}
|
||||||
var fullURL = getFullURL(req)
|
const fullURL = getFullURL(req)
|
||||||
|
|
||||||
if (page.first) {
|
if (page.first) {
|
||||||
links.first = fullURL.replace('page=' + page.current, 'page=' + page.first)
|
links.first = fullURL.replace('page=' + page.current, 'page=' + page.first)
|
||||||
@ -210,23 +213,25 @@ module.exports = function (db, name) {
|
|||||||
// GET /name/:id
|
// GET /name/:id
|
||||||
// GET /name/:id?_embed=&_expand
|
// GET /name/:id?_embed=&_expand
|
||||||
function show (req, res, next) {
|
function show (req, res, next) {
|
||||||
var _embed = req.query._embed
|
const _embed = req.query._embed
|
||||||
var _expand = req.query._expand
|
const _expand = req.query._expand
|
||||||
var resource = db.get(name).getById(req.params.id).value()
|
const resource = db.get(name)
|
||||||
|
.getById(req.params.id)
|
||||||
|
.value()
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
// Clone resource to avoid making changes to the underlying object
|
// Clone resource to avoid making changes to the underlying object
|
||||||
resource = _.cloneDeep(resource)
|
const clone = _.cloneDeep(resource)
|
||||||
|
|
||||||
// Embed other resources based on resource id
|
// Embed other resources based on resource id
|
||||||
// /posts/1?_embed=comments
|
// /posts/1?_embed=comments
|
||||||
embed(resource, _embed)
|
embed(clone, _embed)
|
||||||
|
|
||||||
// Expand inner resources based on id
|
// Expand inner resources based on id
|
||||||
// /posts/1?_expand=user
|
// /posts/1?_expand=user
|
||||||
expand(resource, _expand)
|
expand(clone, _expand)
|
||||||
|
|
||||||
res.locals.data = resource
|
res.locals.data = clone
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
@ -234,7 +239,7 @@ module.exports = function (db, name) {
|
|||||||
|
|
||||||
// POST /name
|
// POST /name
|
||||||
function create (req, res, next) {
|
function create (req, res, next) {
|
||||||
var resource = db.get(name)
|
const resource = db.get(name)
|
||||||
.insert(req.body)
|
.insert(req.body)
|
||||||
.value()
|
.value()
|
||||||
|
|
||||||
@ -246,14 +251,14 @@ module.exports = function (db, name) {
|
|||||||
// PUT /name/:id
|
// PUT /name/:id
|
||||||
// PATCH /name/:id
|
// PATCH /name/:id
|
||||||
function update (req, res, next) {
|
function update (req, res, next) {
|
||||||
var id = req.params.id
|
const id = req.params.id
|
||||||
var chain = db.get(name)
|
let chain = db.get(name)
|
||||||
|
|
||||||
chain = req.method === 'PATCH'
|
chain = req.method === 'PATCH'
|
||||||
? chain.updateById(id, req.body)
|
? chain.updateById(id, req.body)
|
||||||
: chain.replaceById(id, req.body)
|
: chain.replaceById(id, req.body)
|
||||||
|
|
||||||
var resource = chain.value()
|
const resource = chain.value()
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
res.locals.data = resource
|
res.locals.data = resource
|
||||||
@ -264,13 +269,17 @@ module.exports = function (db, name) {
|
|||||||
|
|
||||||
// DELETE /name/:id
|
// DELETE /name/:id
|
||||||
function destroy (req, res, next) {
|
function destroy (req, res, next) {
|
||||||
var resource = db.get(name).removeById(req.params.id).value()
|
const resource = db.get(name)
|
||||||
|
.removeById(req.params.id)
|
||||||
|
.value()
|
||||||
|
|
||||||
// Remove dependents documents
|
// Remove dependents documents
|
||||||
var removable = db._.getRemovable(db.getState())
|
const removable = db._.getRemovable(db.getState())
|
||||||
|
|
||||||
_.each(removable, function (item) {
|
removable.forEach((item) => {
|
||||||
db.get(item.name).removeById(item.id).value()
|
db.get(item.name)
|
||||||
|
.removeById(item.id)
|
||||||
|
.value()
|
||||||
})
|
})
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
var express = require('express')
|
const express = require('express')
|
||||||
|
|
||||||
module.exports = function (db, name) {
|
module.exports = (db, name) => {
|
||||||
var router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
function show (req, res, next) {
|
function show (req, res, next) {
|
||||||
res.locals.data = db.get(name).value()
|
res.locals.data = db.get(name).value()
|
||||||
|
@ -1,27 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
toNative: toNative,
|
getPage
|
||||||
getPage: getPage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turns string to native.
|
|
||||||
// Example:
|
|
||||||
// 'true' -> true
|
|
||||||
// '1' -> 1
|
|
||||||
function toNative (value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
if (
|
|
||||||
value === '' ||
|
|
||||||
value.trim() !== value ||
|
|
||||||
(value.length > 1 && value[0] === '0')
|
|
||||||
) {
|
|
||||||
return value
|
|
||||||
} else if (value === 'true' || value === 'false') {
|
|
||||||
return value === 'true'
|
|
||||||
} else if (!isNaN(+value)) {
|
|
||||||
return +value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPage (array, page, perPage) {
|
function getPage (array, page, perPage) {
|
||||||
|
@ -1,70 +1,73 @@
|
|||||||
var fs = require('fs')
|
const fs = require('fs')
|
||||||
var path = require('path')
|
const path = require('path')
|
||||||
var cp = require('child_process')
|
const cp = require('child_process')
|
||||||
var assert = require('assert')
|
const assert = require('assert')
|
||||||
var supertest = require('supertest')
|
const supertest = require('supertest')
|
||||||
var osTmpdir = require('os-tmpdir')
|
const osTmpdir = require('os-tmpdir')
|
||||||
var tempWrite = require('temp-write')
|
const tempWrite = require('temp-write')
|
||||||
var mkdirp = require('mkdirp')
|
const mkdirp = require('mkdirp')
|
||||||
var rimraf = require('rimraf')
|
const rimraf = require('rimraf')
|
||||||
var express = require('express')
|
const express = require('express')
|
||||||
var serverReady = require('server-ready')
|
const serverReady = require('server-ready')
|
||||||
var pkg = require('../../package.json')
|
const pkg = require('../../package.json')
|
||||||
|
|
||||||
var PORT = 3100
|
let PORT = 3100
|
||||||
|
|
||||||
|
const middlewareFiles = {
|
||||||
|
en: './fixtures/middlewares/en.js',
|
||||||
|
jp: './fixtures/middlewares/jp.js'
|
||||||
|
}
|
||||||
|
|
||||||
function cli (args) {
|
function cli (args) {
|
||||||
var bin = path.join(__dirname, '../..', pkg.bin)
|
const bin = path.join(__dirname, '../..', pkg.bin)
|
||||||
return cp.spawn('node', [bin, '-p', PORT].concat(args), {
|
return cp.spawn('node', [bin, '-p', PORT].concat(args), {
|
||||||
cwd: __dirname,
|
cwd: __dirname,
|
||||||
stdio: ['pipe', process.stdout, process.stderr]
|
stdio: ['pipe', process.stdout, process.stderr]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/* global beforeEach, afterEach, describe, it */
|
describe('cli', () => {
|
||||||
|
let child
|
||||||
|
let request
|
||||||
|
let dbFile
|
||||||
|
let routesFile
|
||||||
|
|
||||||
describe('cli', function () {
|
beforeEach(() => {
|
||||||
var child
|
dbFile = tempWrite.sync(
|
||||||
var request
|
JSON.stringify({
|
||||||
var dbFile
|
|
||||||
var routesFile
|
|
||||||
var middlewareFiles = {
|
|
||||||
en: './fixtures/middlewares/en.js',
|
|
||||||
jp: './fixtures/middlewares/jp.js'
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
dbFile = tempWrite.sync(JSON.stringify({
|
|
||||||
posts: [
|
posts: [
|
||||||
{ id: 1 },
|
{ id: 1 },
|
||||||
{ _id: 2 }
|
{ _id: 2 }
|
||||||
]
|
]
|
||||||
}), 'db.json')
|
}),
|
||||||
|
'db.json'
|
||||||
|
)
|
||||||
|
|
||||||
routesFile = tempWrite.sync(JSON.stringify({
|
routesFile = tempWrite.sync(
|
||||||
'/blog/': '/'
|
JSON.stringify({ '/blog/': '/' }),
|
||||||
}), 'routes.json')
|
'routes.json'
|
||||||
|
)
|
||||||
|
|
||||||
++PORT
|
++PORT
|
||||||
request = supertest('http://localhost:' + PORT)
|
request = supertest(`http://localhost:${PORT}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
child.kill()
|
child.kill()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json', function () {
|
describe('db.json', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli([dbFile])
|
child = cli([ dbFile ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support JSON file', function (done) {
|
it('should support JSON file', (done) => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should send CORS headers', function (done) {
|
it('should send CORS headers', (done) => {
|
||||||
var origin = 'http://example.com'
|
const origin = 'http://example.com'
|
||||||
|
|
||||||
request.get('/posts')
|
request.get('/posts')
|
||||||
.set('Origin', origin)
|
.set('Origin', origin)
|
||||||
@ -72,12 +75,12 @@ describe('cli', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should update JSON file', function (done) {
|
it('should update JSON file', (done) => {
|
||||||
request.post('/posts')
|
request.post('/posts')
|
||||||
.send({ title: 'hello' })
|
.send({ title: 'hello' })
|
||||||
.end(function () {
|
.end(() => {
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
var str = fs.readFileSync(dbFile, 'utf8')
|
const str = fs.readFileSync(dbFile, 'utf8')
|
||||||
assert(str.indexOf('hello') !== -1)
|
assert(str.indexOf('hello') !== -1)
|
||||||
done()
|
done()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
@ -85,118 +88,122 @@ describe('cli', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('seed.js', function () {
|
describe('seed.js', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli(['fixtures/seed.js'])
|
child = cli([ 'fixtures/seed.js' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support JS file', function (done) {
|
it('should support JS file', (done) => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('http://localhost:8080/db', function () {
|
describe('http://localhost:8080/db', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
var fakeServer = express()
|
const fakeServer = express()
|
||||||
fakeServer.get('/db', function (req, res) {
|
fakeServer.get('/db', (req, res) => {
|
||||||
res.jsonp({ posts: [] })
|
res.jsonp({ posts: [] })
|
||||||
})
|
})
|
||||||
fakeServer.listen(8080, function () {
|
fakeServer.listen(8080, () => {
|
||||||
child = cli(['http://localhost:8080/db'])
|
child = cli([ 'http://localhost:8080/db' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support URL file', function (done) {
|
it('should support URL file', (done) => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -r routes.json -m middleware.js -i _id --read-only', function () {
|
describe('db.json -r routes.json -m middleware.js -i _id --read-only', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli([dbFile, '-r', routesFile, '-m', middlewareFiles.en, '-i', '_id', '--read-only'])
|
child = cli([ dbFile, '-r', routesFile, '-m', middlewareFiles.en, '-i', '_id', '--read-only' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use routes.json and _id as the identifier', function (done) {
|
it('should use routes.json and _id as the identifier', (done) => {
|
||||||
request.get('/blog/posts/2').expect(200, done)
|
request.get('/blog/posts/2').expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should apply middlewares', function (done) {
|
it('should apply middlewares', (done) => {
|
||||||
request.get('/blog/posts/2').expect('X-Hello', 'World', done)
|
request.get('/blog/posts/2').expect('X-Hello', 'World', done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow only GET requests', function (done) {
|
it('should allow only GET requests', (done) => {
|
||||||
request.post('/blog/posts').expect(403, done)
|
request.post('/blog/posts').expect(403, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -m first-middleware.js second-middleware.js', function () {
|
describe('db.json -m first-middleware.js second-middleware.js', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp])
|
child = cli([ dbFile, '-m', middlewareFiles.en, middlewareFiles.jp ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should apply all middlewares', function (done) {
|
it('should apply all middlewares', (done) => {
|
||||||
request.get('/posts')
|
request.get('/posts')
|
||||||
.expect('X-Hello', 'World')
|
.expect('X-Hello', 'World')
|
||||||
.expect('X-Konnichiwa', 'Sekai', done)
|
.expect('X-Konnichiwa', 'Sekai', done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -d 1000', function () {
|
describe('db.json -d 1000', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli([dbFile, '-d', 1000])
|
child = cli([ dbFile, '-d', 1000 ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should delay response', function (done) {
|
it('should delay response', (done) => {
|
||||||
var start = new Date()
|
const start = new Date()
|
||||||
request.get('/posts').expect(200, function (err) {
|
request.get('/posts').expect(200, function (err) {
|
||||||
var end = new Date()
|
const end = new Date()
|
||||||
done(end - start > 1000 ? err : new Error('Request wasn\'t delayed'))
|
done(
|
||||||
|
end - start > 1000
|
||||||
|
? err
|
||||||
|
: new Error('Request wasn\'t delayed')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -s fixtures/public -S /some/path/snapshots', function () {
|
describe('db.json -s fixtures/public -S /some/path/snapshots', () => {
|
||||||
var snapshotsDir = path.join(osTmpdir(), 'snapshots')
|
const snapshotsDir = path.join(osTmpdir(), 'snapshots')
|
||||||
var publicDir = 'fixtures/public'
|
const publicDir = 'fixtures/public'
|
||||||
|
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
rimraf.sync(snapshotsDir)
|
rimraf.sync(snapshotsDir)
|
||||||
mkdirp.sync(snapshotsDir)
|
mkdirp.sync(snapshotsDir)
|
||||||
|
|
||||||
child = cli([dbFile, '-s', publicDir, '-S', snapshotsDir])
|
child = cli([ dbFile, '-s', publicDir, '-S', snapshotsDir ])
|
||||||
serverReady(PORT, function () {
|
serverReady(PORT, () => {
|
||||||
child.stdin.write('s\n')
|
child.stdin.write('s\n')
|
||||||
setTimeout(done, 100)
|
setTimeout(done, 100)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should serve fixtures/public', function (done) {
|
it('should serve fixtures/public', (done) => {
|
||||||
request.get('/').expect(/Hello/, done)
|
request.get('/').expect(/Hello/, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should save a snapshot in snapshots dir', function () {
|
it('should save a snapshot in snapshots dir', () => {
|
||||||
assert.equal(fs.readdirSync(snapshotsDir).length, 1)
|
assert.equal(fs.readdirSync(snapshotsDir).length, 1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('fixtures/seed.json --no-cors=true', function () {
|
describe('fixtures/seed.json --no-cors=true', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli(['fixtures/seed.js', '--no-cors=true'])
|
child = cli([ 'fixtures/seed.js', '--no-cors=true' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not send Access-Control-Allow-Origin headers', function (done) {
|
it('should not send Access-Control-Allow-Origin headers', (done) => {
|
||||||
var origin = 'http://example.com'
|
const origin = 'http://example.com'
|
||||||
|
|
||||||
request.get('/posts')
|
request.get('/posts')
|
||||||
.set('Origin', origin)
|
.set('Origin', origin)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err)
|
done(err)
|
||||||
} if ('access-control-allow-origin' in res.headers) {
|
} if ('access-control-allow-origin' in res.headers) {
|
||||||
@ -208,13 +215,13 @@ describe('cli', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('fixtures/seed.json --no-gzip=true', function () {
|
describe('fixtures/seed.json --no-gzip=true', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli(['fixtures/seed.js', '--no-gzip=true'])
|
child = cli([ 'fixtures/seed.js', '--no-gzip=true' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not set Content-Encoding to gzip', function (done) {
|
it('should not set Content-Encoding to gzip', (done) => {
|
||||||
request.get('/posts')
|
request.get('/posts')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function (err, res) {
|
.end(function (err, res) {
|
||||||
@ -229,15 +236,15 @@ describe('cli', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('--watch db.json -r routes.json', function () {
|
describe('--watch db.json -r routes.json', () => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli(['--watch', dbFile, '-r', routesFile])
|
child = cli([ '--watch', dbFile, '-r', routesFile ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should watch db file', function (done) {
|
it('should watch db file', (done) => {
|
||||||
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
|
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
request.get('/foo').expect(200, done)
|
request.get('/foo').expect(200, done)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
})
|
})
|
||||||
@ -246,19 +253,19 @@ describe('cli', function () {
|
|||||||
// Can be very slow
|
// Can be very slow
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
fs.writeFileSync(routesFile, JSON.stringify({ '/api/': '/' }))
|
fs.writeFileSync(routesFile, JSON.stringify({ '/api/': '/' }))
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
request.get('/api/posts').expect(200, done)
|
request.get('/api/posts').expect(200, done)
|
||||||
}, 9000)
|
}, 9000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json --config some-config.json', function (done) {
|
describe('db.json --config some-config.json', (done) => {
|
||||||
beforeEach(function (done) {
|
beforeEach((done) => {
|
||||||
child = cli([dbFile, '--config', 'fixtures/config.json'])
|
child = cli([ dbFile, '--config', 'fixtures/config.json' ])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should apply all middlewares', function (done) {
|
it('should apply all middlewares', (done) => {
|
||||||
request.get('/posts')
|
request.get('/posts')
|
||||||
.expect('X-Hello', 'World')
|
.expect('X-Hello', 'World')
|
||||||
.expect('X-Konnichiwa', 'Sekai', done)
|
.expect('X-Konnichiwa', 'Sekai', done)
|
||||||
|
2
test/mocha.opts
Normal file
2
test/mocha.opts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
--compilers js:babel-register
|
||||||
|
--reporter spec
|
@ -1,34 +1,52 @@
|
|||||||
var assert = require('assert')
|
const assert = require('assert')
|
||||||
var _ = require('lodash')
|
const _ = require('lodash')
|
||||||
var _db = require('underscore-db')
|
const _db = require('underscore-db')
|
||||||
var mixins = require('../../src/server/mixins')
|
const mixins = require('../../src/server/mixins')
|
||||||
|
|
||||||
/* global describe, it */
|
describe('mixins', () => {
|
||||||
|
let db
|
||||||
describe('mixins', function () {
|
|
||||||
describe('getRemovable', function () {
|
|
||||||
it('should return removable documents', function () {
|
|
||||||
var db = {
|
|
||||||
posts: [
|
|
||||||
{id: 1, comment: 1}
|
|
||||||
],
|
|
||||||
comments: [
|
|
||||||
{id: 1, postId: 1},
|
|
||||||
// Comments below references a post that doesn't exist
|
|
||||||
{id: 2, postId: 2},
|
|
||||||
{id: 3, postId: 2}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
var expected = [
|
|
||||||
{name: 'comments', id: 2},
|
|
||||||
{name: 'comments', id: 3}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
before(() => {
|
||||||
_.mixin(_db)
|
_.mixin(_db)
|
||||||
_.mixin(mixins)
|
_.mixin(mixins)
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
db = {
|
||||||
|
posts: [
|
||||||
|
{ id: 1, comment: 1 }
|
||||||
|
],
|
||||||
|
comments: [
|
||||||
|
{ id: 1, postId: 1 },
|
||||||
|
// Comments below references a post that doesn't exist
|
||||||
|
{ id: 2, postId: 2 },
|
||||||
|
{ id: 3, postId: 2 }
|
||||||
|
],
|
||||||
|
photos: [
|
||||||
|
{ id: '1' },
|
||||||
|
{ id: '2' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getRemovable', () => {
|
||||||
|
it('should return removable documents', () => {
|
||||||
|
const expected = [
|
||||||
|
{ name: 'comments', id: 2 },
|
||||||
|
{ name: 'comments', id: 3 }
|
||||||
|
]
|
||||||
|
|
||||||
assert.deepEqual(_.getRemovable(db), expected)
|
assert.deepEqual(_.getRemovable(db), expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('createId', () => {
|
||||||
|
it('should return a new id', () => {
|
||||||
|
assert.equal(_.createId(db.comments), 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return a new uuid', () => {
|
||||||
|
assert.notEqual(_.createId(db.photos), 3)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,47 +1,46 @@
|
|||||||
var assert = require('assert')
|
const assert = require('assert')
|
||||||
var _ = require('lodash')
|
const _ = require('lodash')
|
||||||
var request = require('supertest')
|
const request = require('supertest')
|
||||||
var jsonServer = require('../../src/server')
|
const jsonServer = require('../../src/server')
|
||||||
|
|
||||||
/* global beforeEach, describe, it */
|
describe('Server', () => {
|
||||||
describe('Server', function () {
|
let server
|
||||||
var server
|
let router
|
||||||
var router
|
let db
|
||||||
var db
|
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(() => {
|
||||||
db = {}
|
db = {}
|
||||||
|
|
||||||
db.posts = [
|
db.posts = [
|
||||||
{id: 1, body: 'foo'},
|
{ id: 1, body: 'foo' },
|
||||||
{id: 2, body: 'bar'}
|
{ id: 2, body: 'bar' }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.tags = [
|
db.tags = [
|
||||||
{id: 1, body: 'Technology'},
|
{ id: 1, body: 'Technology' },
|
||||||
{id: 2, body: 'Photography'},
|
{ id: 2, body: 'Photography' },
|
||||||
{id: 3, body: 'photo'}
|
{ id: 3, body: 'photo' }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.users = [
|
db.users = [
|
||||||
{id: 1, username: 'Jim', tel: '0123'},
|
{ id: 1, username: 'Jim', tel: '0123' },
|
||||||
{id: 2, username: 'George', tel: '123'}
|
{ id: 2, username: 'George', tel: '123' }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.comments = [
|
db.comments = [
|
||||||
{id: 1, body: 'foo', published: true, postId: 1, userId: 1},
|
{ id: 1, body: 'foo', published: true, postId: 1, userId: 1 },
|
||||||
{id: 2, body: 'bar', published: false, postId: 1, userId: 2},
|
{ id: 2, body: 'bar', published: false, postId: 1, userId: 2 },
|
||||||
{id: 3, body: 'baz', published: false, postId: 2, userId: 1},
|
{ id: 3, body: 'baz', published: false, postId: 2, userId: 1 },
|
||||||
{id: 4, body: 'qux', published: true, postId: 2, userId: 2},
|
{ id: 4, body: 'qux', published: true, postId: 2, userId: 2 },
|
||||||
{id: 5, body: 'quux', published: false, postId: 2, userId: 1}
|
{ id: 5, body: 'quux', published: false, postId: 2, userId: 1 }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.refs = [
|
db.refs = [
|
||||||
{id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1}
|
{ id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1 }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.stringIds = [
|
db.stringIds = [
|
||||||
{id: '1234'}
|
{ id: '1234' }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.deep = [
|
db.deep = [
|
||||||
@ -50,27 +49,27 @@ describe('Server', function () {
|
|||||||
]
|
]
|
||||||
|
|
||||||
db.nested = [
|
db.nested = [
|
||||||
{resource: {name: 'dewey'}},
|
{ resource: {name: 'dewey'} },
|
||||||
{resource: {name: 'cheatem'}},
|
{ resource: {name: 'cheatem'} },
|
||||||
{resource: {name: 'howe'}}
|
{ resource: {name: 'howe'} }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.list = [
|
db.list = [
|
||||||
{id: 1},
|
{ id: 1 },
|
||||||
{id: 2},
|
{ id: 2 },
|
||||||
{id: 3},
|
{ id: 3 },
|
||||||
{id: 4},
|
{ id: 4 },
|
||||||
{id: 5},
|
{ id: 5 },
|
||||||
{id: 6},
|
{ id: 6 },
|
||||||
{id: 7},
|
{ id: 7 },
|
||||||
{id: 8},
|
{ id: 8 },
|
||||||
{id: 9},
|
{ id: 9 },
|
||||||
{id: 10},
|
{ id: 10 },
|
||||||
{id: 11},
|
{ id: 11 },
|
||||||
{id: 12},
|
{ id: 12 },
|
||||||
{id: 13},
|
{ id: 13 },
|
||||||
{id: 14},
|
{ id: 14 },
|
||||||
{id: 15}
|
{ id: 15 }
|
||||||
]
|
]
|
||||||
|
|
||||||
server = jsonServer.create()
|
server = jsonServer.create()
|
||||||
@ -83,8 +82,8 @@ describe('Server', function () {
|
|||||||
server.use(router)
|
server.use(router)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /db', function () {
|
describe('GET /db', () => {
|
||||||
it('should respond with json and full database', function (done) {
|
it('should respond with json and full database', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/db')
|
.get('/db')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -93,8 +92,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource', function () {
|
describe('GET /:resource', () => {
|
||||||
it('should respond with json and corresponding resources', function (done) {
|
it('should respond with json and corresponding resources', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts')
|
.get('/posts')
|
||||||
.set('Origin', 'http://example.com')
|
.set('Origin', 'http://example.com')
|
||||||
@ -105,47 +104,47 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', function (done) {
|
it('should respond with 404 if resource is not found', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/undefined')
|
.get('/undefined')
|
||||||
.expect(404, done)
|
.expect(404, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr=&attr=', function () {
|
describe('GET /:resource?attr=&attr=', () => {
|
||||||
it('should respond with json and filter resources', function (done) {
|
it('should respond with json and filter resources', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?postId=1&published=true')
|
.get('/comments?postId=1&published=true')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[0]])
|
.expect([ db.comments[0] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be strict', function (done) {
|
it('should be strict', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/users?tel=123')
|
.get('/users?tel=123')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.users[1]])
|
.expect([ db.users[1] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support multiple filters', function (done) {
|
it('should support multiple filters', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id=1&id=2')
|
.get('/comments?id=1&id=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[0], db.comments[1]])
|
.expect([ db.comments[0], db.comments[1] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support deep filter', function (done) {
|
it('should support deep filter', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/deep?a.b=1')
|
.get('/deep?a.b=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.deep[0]])
|
.expect([ db.deep[0] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should ignore JSONP query parameters callback and _ ', function (done) {
|
it('should ignore JSONP query parameters callback and _ ', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?callback=1&_=1')
|
.get('/comments?callback=1&_=1')
|
||||||
.expect('Content-Type', /text/)
|
.expect('Content-Type', /text/)
|
||||||
@ -153,7 +152,7 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should ignore unknown query parameters', function (done) {
|
it('should ignore unknown query parameters', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?foo=1&bar=2')
|
.get('/comments?foo=1&bar=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -162,16 +161,16 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?q=', function () {
|
describe('GET /:resource?q=', () => {
|
||||||
it('should respond with json and make a full-text search', function (done) {
|
it('should respond with json and make a full-text search', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?q=pho')
|
.get('/tags?q=pho')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[1], db.tags[2]])
|
.expect([ db.tags[1], db.tags[2] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with json and make a deep full-text search', function (done) {
|
it('should respond with json and make a deep full-text search', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/deep?q=1')
|
.get('/deep?q=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -179,25 +178,25 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an empty array when nothing is matched', function (done) {
|
it('should return an empty array when nothing is matched', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?q=nope')
|
.get('/tags?q=nope')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([])
|
.expect([ ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support other query parameters', function (done) {
|
it('should support other query parameters', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?q=qu&published=true')
|
.get('/comments?q=qu&published=true')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[3]])
|
.expect([ db.comments[3] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_end=', function () {
|
describe('GET /:resource?_end=', () => {
|
||||||
it('should respond with a sliced array', function (done) {
|
it('should respond with a sliced array', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_end=2')
|
.get('/comments?_end=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -208,24 +207,24 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_sort=', function () {
|
describe('GET /:resource?_sort=', () => {
|
||||||
it('should respond with json and sort on a field', function (done) {
|
it('should respond with json and sort on a field', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?_sort=body')
|
.get('/tags?_sort=body')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[1], db.tags[0], db.tags[2]])
|
.expect([ db.tags[1], db.tags[0], db.tags[2] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should reverse sorting with _order=DESC', function (done) {
|
it('should reverse sorting with _order=DESC', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?_sort=body&_order=DESC')
|
.get('/tags?_sort=body&_order=DESC')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[2], db.tags[0], db.tags[1]])
|
.expect([ db.tags[2], db.tags[0], db.tags[1] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should sort on numerical field', function (done) {
|
it('should sort on numerical field', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts?_sort=id&_order=DESC')
|
.get('/posts?_sort=id&_order=DESC')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -233,54 +232,54 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should sort on nested field', function (done) {
|
it('should sort on nested field', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/nested?_sort=resource.name')
|
.get('/nested?_sort=resource.name')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.nested[1], db.nested[0], db.nested[2]])
|
.expect([ db.nested[1], db.nested[0], db.nested[2] ])
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_start=&_end=', function () {
|
describe('GET /:resource?_start=&_end=', () => {
|
||||||
it('should respond with a sliced array', function (done) {
|
it('should respond with a sliced array', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_start=1&_end=2')
|
.get('/comments?_start=1&_end=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('x-total-count', db.comments.length.toString())
|
.expect('X-Total-Count', db.comments.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.comments.slice(1, 2))
|
.expect(db.comments.slice(1, 2))
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_start=&_limit=', function () {
|
describe('GET /:resource?_start=&_limit=', () => {
|
||||||
it('should respond with a limited array', function (done) {
|
it('should respond with a limited array', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_start=1&_limit=1')
|
.get('/comments?_start=1&_limit=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('x-total-count', db.comments.length.toString())
|
.expect('X-Total-Count', db.comments.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.comments.slice(1, 2))
|
.expect(db.comments.slice(1, 2))
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_page=', function () {
|
describe('GET /:resource?_page=', () => {
|
||||||
it('should paginate', function (done) {
|
it('should paginate', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/list?_page=2')
|
.get('/list?_page=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('x-total-count', db.list.length.toString())
|
.expect('X-Total-Count', db.list.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.list.slice(10, 20))
|
.expect(db.list.slice(10, 20))
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_page=&_limit=', function () {
|
describe('GET /:resource?_page=&_limit=', () => {
|
||||||
it('should paginate with a custom limit', function (done) {
|
it('should paginate with a custom limit', (done) => {
|
||||||
var link = [
|
const link = [
|
||||||
'<http://localhost/list?_page=1&_limit=1>; rel="first"',
|
'<http://localhost/list?_page=1&_limit=1>; rel="first"',
|
||||||
'<http://localhost/list?_page=1&_limit=1>; rel="prev"',
|
'<http://localhost/list?_page=1&_limit=1>; rel="prev"',
|
||||||
'<http://localhost/list?_page=3&_limit=1>; rel="next"',
|
'<http://localhost/list?_page=3&_limit=1>; rel="next"',
|
||||||
@ -298,8 +297,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_gte=&attr_lte=', function () {
|
describe('GET /:resource?attr_gte=&attr_lte=', () => {
|
||||||
it('should respond with a limited array', function (done) {
|
it('should respond with a limited array', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id_gte=2&id_lte=3')
|
.get('/comments?id_gte=2&id_lte=3')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -308,8 +307,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_ne=', function () {
|
describe('GET /:resource?attr_ne=', () => {
|
||||||
it('should respond with a limited array', function (done) {
|
it('should respond with a limited array', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id_ne=1')
|
.get('/comments?id_ne=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -318,8 +317,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_like=', function () {
|
describe('GET /:resource?attr_like=', () => {
|
||||||
it('should respond with an array that matches the like operator (case insensitive)', function (done) {
|
it('should respond with an array that matches the like operator (case insensitive)', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?body_like=photo')
|
.get('/tags?body_like=photo')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -331,8 +330,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:parent/:parentId/:resource', function () {
|
describe('GET /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and corresponding nested resources', function (done) {
|
it('should respond with json and corresponding nested resources', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1/comments')
|
.get('/posts/1/comments')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -344,8 +343,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id', function () {
|
describe('GET /:resource/:id', () => {
|
||||||
it('should respond with json and corresponding resource', function (done) {
|
it('should respond with json and corresponding resource', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -353,7 +352,7 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support string id, respond with json and corresponding resource', function (done) {
|
it('should support string id, respond with json and corresponding resource', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/refs/abcd-1234')
|
.get('/refs/abcd-1234')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -361,7 +360,7 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support integer id as string', function (done) {
|
it('should support integer id as string', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/stringIds/1234')
|
.get('/stringIds/1234')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -369,7 +368,7 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', function (done) {
|
it('should respond with 404 if resource is not found', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/9001')
|
.get('/posts/9001')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -378,11 +377,11 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_embed=', function () {
|
describe('GET /:resource?_embed=', () => {
|
||||||
it('should respond with corresponding resources and embedded resources', function (done) {
|
it('should respond with corresponding resources and embedded resources', (done) => {
|
||||||
var posts = _.cloneDeep(db.posts)
|
const posts = _.cloneDeep(db.posts)
|
||||||
posts[0].comments = [db.comments[0], db.comments[1]]
|
posts[0].comments = [ db.comments[0], db.comments[1] ]
|
||||||
posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]]
|
posts[1].comments = [ db.comments[2], db.comments[3], db.comments[4] ]
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts?_embed=comments')
|
.get('/posts?_embed=comments')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -391,12 +390,12 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_embed&_embed=', function () {
|
describe('GET /:resource?_embed&_embed=', () => {
|
||||||
it('should respond with corresponding resources and embedded resources', function (done) {
|
it('should respond with corresponding resources and embedded resources', (done) => {
|
||||||
var posts = _.cloneDeep(db.posts)
|
const posts = _.cloneDeep(db.posts)
|
||||||
posts[0].comments = [db.comments[0], db.comments[1]]
|
posts[0].comments = [ db.comments[0], db.comments[1] ]
|
||||||
posts[0].refs = [db.refs[0]]
|
posts[0].refs = [ db.refs[0] ]
|
||||||
posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]]
|
posts[1].comments = [ db.comments[2], db.comments[3], db.comments[4] ]
|
||||||
posts[1].refs = []
|
posts[1].refs = []
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts?_embed=comments&_embed=refs')
|
.get('/posts?_embed=comments&_embed=refs')
|
||||||
@ -406,10 +405,10 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id?_embed=', function () {
|
describe('GET /:resource/:id?_embed=', () => {
|
||||||
it('should respond with corresponding resources and embedded resources', function (done) {
|
it('should respond with corresponding resources and embedded resources', (done) => {
|
||||||
var post = _.cloneDeep(db.posts[0])
|
const post = _.cloneDeep(db.posts[0])
|
||||||
post.comments = [db.comments[0], db.comments[1]]
|
post.comments = [ db.comments[0], db.comments[1] ]
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1?_embed=comments')
|
.get('/posts/1?_embed=comments')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -418,10 +417,10 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id?_embed=&_embed=', function () {
|
describe('GET /:resource/:id?_embed=&_embed=', () => {
|
||||||
it('should respond with corresponding resource and embedded resources', function (done) {
|
it('should respond with corresponding resource and embedded resources', (done) => {
|
||||||
var post = _.cloneDeep(db.posts[0])
|
const post = _.cloneDeep(db.posts[0])
|
||||||
post.comments = [db.comments[0], db.comments[1]]
|
post.comments = [ db.comments[0], db.comments[1] ]
|
||||||
post.refs = [db.refs[0]]
|
post.refs = [db.refs[0]]
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1?_embed=comments&_embed=refs')
|
.get('/posts/1?_embed=comments&_embed=refs')
|
||||||
@ -431,9 +430,9 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_expand=', function () {
|
describe('GET /:resource?_expand=', () => {
|
||||||
it('should respond with corresponding resource and expanded inner resources', function (done) {
|
it('should respond with corresponding resource and expanded inner resources', (done) => {
|
||||||
var refs = _.cloneDeep(db.refs)
|
const refs = _.cloneDeep(db.refs)
|
||||||
refs[0].post = db.posts[0]
|
refs[0].post = db.posts[0]
|
||||||
request(server)
|
request(server)
|
||||||
.get('/refs?_expand=post')
|
.get('/refs?_expand=post')
|
||||||
@ -443,9 +442,9 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id?_expand=', function () {
|
describe('GET /:resource/:id?_expand=', () => {
|
||||||
it('should respond with corresponding resource and expanded inner resources', function (done) {
|
it('should respond with corresponding resource and expanded inner resources', (done) => {
|
||||||
var comment = _.cloneDeep(db.comments[0])
|
const comment = _.cloneDeep(db.comments[0])
|
||||||
comment.post = db.posts[0]
|
comment.post = db.posts[0]
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments/1?_expand=post')
|
.get('/comments/1?_expand=post')
|
||||||
@ -455,9 +454,9 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_expand=&_expand', function () {
|
describe('GET /:resource?_expand=&_expand', () => {
|
||||||
it('should respond with corresponding resource and expanded inner resources', function (done) {
|
it('should respond with corresponding resource and expanded inner resources', (done) => {
|
||||||
var refs = _.cloneDeep(db.refs)
|
const refs = _.cloneDeep(db.refs)
|
||||||
refs[0].post = db.posts[0]
|
refs[0].post = db.posts[0]
|
||||||
refs[0].user = db.users[0]
|
refs[0].user = db.users[0]
|
||||||
request(server)
|
request(server)
|
||||||
@ -468,9 +467,9 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id?_expand=&_expand=', function () {
|
describe('GET /:resource/:id?_expand=&_expand=', () => {
|
||||||
it('should respond with corresponding resource and expanded inner resources', function (done) {
|
it('should respond with corresponding resource and expanded inner resources', (done) => {
|
||||||
var comments = db.comments[0]
|
const comments = db.comments[0]
|
||||||
comments.post = db.posts[0]
|
comments.post = db.posts[0]
|
||||||
comments.user = db.users[0]
|
comments.user = db.users[0]
|
||||||
request(server)
|
request(server)
|
||||||
@ -481,16 +480,16 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('POST /:resource', function () {
|
describe('POST /:resource', () => {
|
||||||
it('should respond with json, create a resource and increment id',
|
it('should respond with json, create a resource and increment id',
|
||||||
function (done) {
|
(done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts')
|
.post('/posts')
|
||||||
.send({body: 'foo', booleanValue: true, integerValue: 1})
|
.send({body: 'foo', booleanValue: true, integerValue: 1})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({id: 3, body: 'foo', booleanValue: true, integerValue: 1})
|
.expect({id: 3, body: 'foo', booleanValue: true, integerValue: 1})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
assert.equal(db.posts.length, 3)
|
assert.equal(db.posts.length, 3)
|
||||||
done()
|
done()
|
||||||
@ -499,7 +498,7 @@ describe('Server', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
it('should support x-www-form-urlencoded',
|
it('should support x-www-form-urlencoded',
|
||||||
function (done) {
|
(done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts')
|
.post('/posts')
|
||||||
.type('form')
|
.type('form')
|
||||||
@ -508,7 +507,7 @@ describe('Server', function () {
|
|||||||
// x-www-form-urlencoded will convert to string
|
// x-www-form-urlencoded will convert to string
|
||||||
.expect({id: 3, body: 'foo', booleanValue: 'true', integerValue: '1'})
|
.expect({id: 3, body: 'foo', booleanValue: 'true', integerValue: '1'})
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
assert.equal(db.posts.length, 3)
|
assert.equal(db.posts.length, 3)
|
||||||
done()
|
done()
|
||||||
@ -517,13 +516,13 @@ describe('Server', function () {
|
|||||||
)
|
)
|
||||||
|
|
||||||
it('should respond with json, create a resource and generate string id',
|
it('should respond with json, create a resource and generate string id',
|
||||||
function (done) {
|
(done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.post('/refs')
|
.post('/refs')
|
||||||
.send({url: 'http://foo.com', postId: '1'})
|
.send({url: 'http://foo.com', postId: '1'})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(201)
|
.expect(201)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
assert.equal(db.refs.length, 2)
|
assert.equal(db.refs.length, 2)
|
||||||
done()
|
done()
|
||||||
@ -531,8 +530,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('POST /:parent/:parentId/:resource', function () {
|
describe('POST /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and set parentId', function (done) {
|
it('should respond with json and set parentId', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts/1/comments')
|
.post('/posts/1/comments')
|
||||||
.send({body: 'foo'})
|
.send({body: 'foo'})
|
||||||
@ -542,8 +541,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PUT /:resource/:id', function () {
|
describe('PUT /:resource/:id', () => {
|
||||||
it('should respond with json and replace resource', function (done) {
|
it('should respond with json and replace resource', (done) => {
|
||||||
var post = {id: 1, booleanValue: true, integerValue: 1}
|
var post = {id: 1, booleanValue: true, integerValue: 1}
|
||||||
request(server)
|
request(server)
|
||||||
.put('/posts/1')
|
.put('/posts/1')
|
||||||
@ -552,7 +551,7 @@ describe('Server', function () {
|
|||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(post)
|
.expect(post)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
// assert it was created in database too
|
// assert it was created in database too
|
||||||
assert.deepEqual(db.posts[0], post)
|
assert.deepEqual(db.posts[0], post)
|
||||||
@ -560,7 +559,7 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', function (done) {
|
it('should respond with 404 if resource is not found', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.put('/posts/9001')
|
.put('/posts/9001')
|
||||||
.send({id: 1, body: 'bar'})
|
.send({id: 1, body: 'bar'})
|
||||||
@ -570,15 +569,15 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PATCH /:resource/:id', function () {
|
describe('PATCH /:resource/:id', () => {
|
||||||
it('should respond with json and update resource', function (done) {
|
it('should respond with json and update resource', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.patch('/posts/1')
|
.patch('/posts/1')
|
||||||
.send({body: 'bar'})
|
.send({body: 'bar'})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({id: 1, body: 'bar'})
|
.expect({id: 1, body: 'bar'})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
// assert it was created in database too
|
// assert it was created in database too
|
||||||
assert.deepEqual(db.posts[0], {id: 1, body: 'bar'})
|
assert.deepEqual(db.posts[0], {id: 1, body: 'bar'})
|
||||||
@ -586,7 +585,7 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', function (done) {
|
it('should respond with 404 if resource is not found', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.patch('/posts/9001')
|
.patch('/posts/9001')
|
||||||
.send({body: 'bar'})
|
.send({body: 'bar'})
|
||||||
@ -596,13 +595,13 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('DELETE /:resource/:id', function () {
|
describe('DELETE /:resource/:id', () => {
|
||||||
it('should respond with empty data, destroy resource and dependent resources', function (done) {
|
it('should respond with empty data, destroy resource and dependent resources', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.del('/posts/1')
|
.del('/posts/1')
|
||||||
.expect({})
|
.expect({})
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function (err, res) {
|
.end((err, res) => {
|
||||||
if (err) return done(err)
|
if (err) return done(err)
|
||||||
assert.equal(db.posts.length, 1)
|
assert.equal(db.posts.length, 1)
|
||||||
assert.equal(db.comments.length, 3)
|
assert.equal(db.comments.length, 3)
|
||||||
@ -610,7 +609,7 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', function (done) {
|
it('should respond with 404 if resource is not found', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.del('/posts/9001')
|
.del('/posts/9001')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -619,9 +618,9 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Static routes', function () {
|
describe('Static routes', () => {
|
||||||
describe('GET /', function () {
|
describe('GET /', () => {
|
||||||
it('should respond with html', function (done) {
|
it('should respond with html', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/')
|
.get('/')
|
||||||
.expect(/You're successfully running JSON Server/)
|
.expect(/You're successfully running JSON Server/)
|
||||||
@ -629,8 +628,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /stylesheets/style.css', function () {
|
describe('GET /stylesheets/style.css', () => {
|
||||||
it('should respond with css', function (done) {
|
it('should respond with css', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/stylesheets/style.css')
|
.get('/stylesheets/style.css')
|
||||||
.expect('Content-Type', /css/)
|
.expect('Content-Type', /css/)
|
||||||
@ -639,14 +638,14 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Database state', function () {
|
describe('Database state', () => {
|
||||||
it('should be accessible', function () {
|
it('should be accessible', () => {
|
||||||
assert(router.db.getState())
|
assert(router.db.getState())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Responses', function () {
|
describe('Responses', () => {
|
||||||
it('should have no cache headers (for IE)', function (done) {
|
it('should have no cache headers (for IE)', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/db')
|
.get('/db')
|
||||||
.expect('Cache-Control', 'no-cache')
|
.expect('Cache-Control', 'no-cache')
|
||||||
@ -656,15 +655,15 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rewriter', function () {
|
describe('Rewriter', () => {
|
||||||
it('should rewrite using prefix', function (done) {
|
it('should rewrite using prefix', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/api/posts/1')
|
.get('/api/posts/1')
|
||||||
.expect(db.posts[0])
|
.expect(db.posts[0])
|
||||||
.end(done)
|
.end(done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should rewrite using params', function (done) {
|
it('should rewrite using params', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/blog/posts/1/show')
|
.get('/blog/posts/1/show')
|
||||||
.expect(db.posts[0])
|
.expect(db.posts[0])
|
||||||
@ -672,16 +671,16 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('router.render', function (done) {
|
describe('router.render', (done) => {
|
||||||
beforeEach(function () {
|
beforeEach(() => {
|
||||||
router.render = function (req, res) {
|
router.render = (req, res) => {
|
||||||
res.jsonp({
|
res.jsonp({
|
||||||
data: res.locals.data
|
data: res.locals.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be possible to wrap response', function (done) {
|
it('should be possible to wrap response', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -690,8 +689,8 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('router.db._.id', function (done) {
|
describe('router.db._.id', (done) => {
|
||||||
beforeEach(function () {
|
beforeEach(() => {
|
||||||
router.db.setState({
|
router.db.setState({
|
||||||
posts: [
|
posts: [
|
||||||
{ _id: 1 }
|
{ _id: 1 }
|
||||||
@ -701,7 +700,7 @@ describe('Server', function () {
|
|||||||
router.db._.id = '_id'
|
router.db._.id = '_id'
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be possible to GET using a different id property', function (done) {
|
it('should be possible to GET using a different id property', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
@ -709,12 +708,12 @@ describe('Server', function () {
|
|||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be possible to POST using a different id property', function (done) {
|
it('should be possible to POST using a different id property', (done) => {
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts')
|
.post('/posts')
|
||||||
.send({ body: 'hello' })
|
.send({ body: 'hello' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({_id: 2, body: 'hello'})
|
.expect({ _id: 2, body: 'hello' })
|
||||||
.expect(201, done)
|
.expect(201, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
var request = require('supertest')
|
const request = require('supertest')
|
||||||
var jsonServer = require('../../src/server')
|
const jsonServer = require('../../src/server')
|
||||||
|
|
||||||
/* global beforeEach, describe, it */
|
|
||||||
describe('Server', function () {
|
describe('Server', function () {
|
||||||
var server
|
let server
|
||||||
var router
|
let router
|
||||||
var db
|
let db
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
db = {}
|
db = {}
|
||||||
@ -32,7 +31,7 @@ describe('Server', function () {
|
|||||||
|
|
||||||
describe('POST /:resource', function () {
|
describe('POST /:resource', function () {
|
||||||
it('should create resource', function (done) {
|
it('should create resource', function (done) {
|
||||||
var user = { name: 'bar' }
|
const user = { name: 'bar' }
|
||||||
request(server)
|
request(server)
|
||||||
.post('/user')
|
.post('/user')
|
||||||
.send(user)
|
.send(user)
|
||||||
@ -43,7 +42,7 @@ describe('Server', function () {
|
|||||||
|
|
||||||
describe('PUT /:resource', function () {
|
describe('PUT /:resource', function () {
|
||||||
it('should update resource', function (done) {
|
it('should update resource', function (done) {
|
||||||
var user = { name: 'bar' }
|
const user = { name: 'bar' }
|
||||||
request(server)
|
request(server)
|
||||||
.put('/user')
|
.put('/user')
|
||||||
.send(user)
|
.send(user)
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
var assert = require('assert')
|
const assert = require('assert')
|
||||||
var utils = require('../../src/server/utils')
|
const utils = require('../../src/server/utils')
|
||||||
|
|
||||||
/* global describe, it */
|
|
||||||
|
|
||||||
describe('utils', function () {
|
describe('utils', function () {
|
||||||
describe('getPage', function () {
|
describe('getPage', function () {
|
||||||
var array = [1, 2, 3, 4, 5]
|
const array = [1, 2, 3, 4, 5]
|
||||||
var perPage = 2
|
const perPage = 2
|
||||||
|
|
||||||
it('should return first page', function () {
|
it('should return first page', function () {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
|
Reference in New Issue
Block a user