This commit is contained in:
typicode
2020-11-15 23:50:27 +01:00
parent 8928b6af34
commit f1621c38fe
31 changed files with 481 additions and 557 deletions

View File

@ -8,7 +8,7 @@ module.exports = {
singleQuote: true,
semi: false,
},
]
],
},
env: { jest: true }
env: { jest: true },
}

View File

@ -5,33 +5,33 @@ module.exports = function() {
{
id: 1,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
{
id: 2,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
{
id: 3,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
{
id: 4,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
{
id: 5,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
{
id: 6,
content:
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
}
]
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!",
},
],
}
}

View File

@ -14,7 +14,7 @@ let PORT = 3100
const middlewareFiles = {
en: './../../__fixtures__/middlewares/en.js',
jp: './../../__fixtures__/middlewares/jp.js',
postbody: './../../__fixtures__/middlewares/postbody.js'
postbody: './../../__fixtures__/middlewares/postbody.js',
}
const bin = path.join(__dirname, '../../lib/cli/bin')
@ -22,7 +22,7 @@ const bin = path.join(__dirname, '../../lib/cli/bin')
function cli(args) {
return cp.spawn('node', ['--', bin, '-p', PORT].concat(args), {
cwd: __dirname,
stdio: ['pipe', process.stdout, process.stderr]
stdio: ['pipe', process.stdout, process.stderr],
})
}
@ -36,7 +36,7 @@ describe('cli', () => {
dbFile = tempWrite.sync(
JSON.stringify({
posts: [{ id: 1 }, { _id: 2 }],
comments: [{ id: 1, post_id: 1 }]
comments: [{ id: 1, post_id: 1 }],
}),
'db.json'
)
@ -55,16 +55,16 @@ describe('cli', () => {
})
describe('db.json', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([dbFile])
serverReady(PORT, done)
})
test('should support JSON file', done => {
test('should support JSON file', (done) => {
request.get('/posts').expect(200, done)
})
test('should send CORS headers', done => {
test('should send CORS headers', (done) => {
const origin = 'http://example.com'
request
@ -74,7 +74,7 @@ describe('cli', () => {
.expect(200, done)
})
test('should update JSON file', done => {
test('should update JSON file', (done) => {
request
.post('/posts')
.send({ title: 'hello' })
@ -89,29 +89,29 @@ describe('cli', () => {
})
describe('seed.js', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli(['../../__fixtures__/seed.js'])
serverReady(PORT, done)
})
test('should support JS file', done => {
test('should support JS file', (done) => {
request.get('/posts').expect(200, done)
})
})
describe('remote db', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli(['https://jsonplaceholder.typicode.com/db'])
serverReady(PORT, done)
})
test('should support URL file', done => {
test('should support URL file', (done) => {
request.get('/posts').expect(200, done)
})
})
describe('db.json -r routes.json -m middleware.js -i _id --foreignKeySuffix _id --read-only', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([
dbFile,
'-r',
@ -122,12 +122,12 @@ describe('cli', () => {
'_id',
'--read-only',
'--foreignKeySuffix',
'_id'
'_id',
])
serverReady(PORT, done)
})
test('should use routes.json and _id as the identifier', done => {
test('should use routes.json and _id as the identifier', (done) => {
request.get('/blog/posts/2').expect(200, done)
})
@ -136,22 +136,22 @@ describe('cli', () => {
assert.strictEqual(response.body.length, 1)
})
test('should apply middlewares', done => {
test('should apply middlewares', (done) => {
request.get('/blog/posts/2').expect('X-Hello', 'World', done)
})
test('should allow only GET requests', done => {
test('should allow only GET requests', (done) => {
request.post('/blog/posts').expect(403, done)
})
})
describe('db.json -m first-middleware.js second-middleware.js', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp])
serverReady(PORT, done)
})
test('should apply all middlewares', done => {
test('should apply all middlewares', (done) => {
request
.get('/posts')
.expect('X-Hello', 'World')
@ -160,26 +160,23 @@ describe('cli', () => {
})
describe('db.json -m postbody-middleware.js', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([dbFile, '-m', middlewareFiles.postbody])
serverReady(PORT, done)
})
test('should have post body in middleware', done => {
request
.post('/posts')
.send({ name: 'test' })
.expect('name', 'test', done)
test('should have post body in middleware', (done) => {
request.post('/posts').send({ name: 'test' }).expect('name', 'test', done)
})
})
describe('db.json -d 1000', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([dbFile, '-d', 1000])
serverReady(PORT, done)
})
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request.get('/posts').expect(200, function (err) {
const end = new Date()
@ -192,7 +189,7 @@ describe('cli', () => {
const snapshotsDir = path.join(osTmpdir(), 'snapshots')
const publicDir = '../../__fixtures__/public'
beforeEach(done => {
beforeEach((done) => {
rimraf.sync(snapshotsDir)
mkdirp.sync(snapshotsDir)
@ -203,7 +200,7 @@ describe('cli', () => {
})
})
test('should serve ../../__fixtures__/public', done => {
test('should serve ../../__fixtures__/public', (done) => {
request.get('/').expect(/Hello/, done)
})
@ -213,12 +210,12 @@ describe('cli', () => {
})
describe('../../__fixtures__/seed.json --no-cors=true', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli(['../../__fixtures__/seed.js', '--no-cors=true'])
serverReady(PORT, done)
})
test('should not send Access-Control-Allow-Origin headers', done => {
test('should not send Access-Control-Allow-Origin headers', (done) => {
const origin = 'http://example.com'
request
@ -239,12 +236,12 @@ describe('cli', () => {
})
describe('../../__fixtures__/seed.json --no-gzip=true', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli(['../../__fixtures__/seed.js', '--no-gzip=true'])
serverReady(PORT, done)
})
test('should not set Content-Encoding to gzip', done => {
test('should not set Content-Encoding to gzip', (done) => {
request
.get('/posts')
.expect(200)
@ -261,19 +258,19 @@ describe('cli', () => {
})
describe('--watch db.json -r routes.json', () => {
beforeEach(done => {
beforeEach((done) => {
child = cli([dbFile, '-r', routesFile, '--watch'])
serverReady(PORT, done)
})
test('should watch db file', done => {
test('should watch db file', (done) => {
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
setTimeout(() => {
request.get('/foo').expect(200, done)
}, 1000)
})
test('should watch routes file', done => {
test('should watch routes file', (done) => {
fs.writeFileSync(routesFile, JSON.stringify({ '/api/*': '/$1' }))
setTimeout(() => {
request.get('/api/posts').expect(200, done)
@ -282,13 +279,13 @@ describe('cli', () => {
})
describe('non existent db.json', () => {
beforeEach(done => {
beforeEach((done) => {
fs.unlinkSync(dbFile)
child = cli([dbFile])
serverReady(PORT, done)
})
test("should create JSON file if it doesn't exist", done => {
test("should create JSON file if it doesn't exist", (done) => {
request.get('/posts').expect(200, done)
})
})
@ -298,9 +295,9 @@ describe('cli', () => {
dbFile = tempWrite.sync(JSON.stringify({ 'a/b': [] }), 'db-error.json')
})
test('should exit with an error', done => {
test('should exit with an error', (done) => {
child = cli([dbFile])
child.on('exit', code => {
child.on('exit', (code) => {
if (code === 1) {
return done()
}

View File

@ -18,9 +18,9 @@ describe('mixins', () => {
{ id: 1, postId: 1 },
// Comments below references a post that doesn't exist
{ id: 2, postId: 2 },
{ id: 3, postId: 2 }
{ id: 3, postId: 2 },
],
photos: [{ id: '1' }, { id: '2' }]
photos: [{ id: '1' }, { id: '2' }],
}
})
@ -28,7 +28,7 @@ describe('mixins', () => {
test('should return removable documents', () => {
const expected = [
{ name: 'comments', id: 2 },
{ name: 'comments', id: 3 }
{ name: 'comments', id: 3 },
]
assert.deepStrictEqual(
@ -40,7 +40,7 @@ describe('mixins', () => {
test('should support custom foreignKeySuffix', () => {
const expected = [
{ name: 'comments', id: 2 },
{ name: 'comments', id: 3 }
{ name: 'comments', id: 3 },
]
assert.deepStrictEqual(

View File

@ -12,7 +12,7 @@ describe('Fake server', () => {
db.posts = [
{ id: 1, body: 'foo' },
{ id: 2, body: 'bar' }
{ id: 2, body: 'bar' },
]
db.comments = [
@ -20,7 +20,7 @@ describe('Fake server', () => {
{ id: 2, body: 'bar', published: false, postId: 1, userId: 2 },
{ id: 3, body: 'baz', published: false, postId: 2, userId: 1 },
{ 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 },
]
server = jsonServer.create()
@ -87,10 +87,7 @@ describe('Fake server', () => {
describe('DELETE /:resource/:id', () => {
test('should not destroy resource', async () => {
await request(server)
.del('/posts/1')
.expect({})
.expect(200)
await request(server).del('/posts/1').expect({}).expect(200)
assert.strictEqual(db.posts.length, 2)
})
})

View File

@ -13,13 +13,13 @@ describe('Server with custom foreign key', () => {
db.posts = [
{ id: 1, body: 'foo' },
{ id: 2, body: 'bar' }
{ id: 2, body: 'bar' },
]
db.comments = [
{ id: 1, post_id: 1 },
{ id: 2, post_id: 1 },
{ id: 3, post_id: 2 }
{ id: 3, post_id: 2 },
]
server = jsonServer.create()
@ -109,10 +109,7 @@ describe('Server with custom foreign key', () => {
describe('DELETE /:resource/:id', () => {
test('should respond with empty data, destroy resource and dependent resources', async () => {
await request(server)
.del('/posts/1')
.expect({})
.expect(200)
await request(server).del('/posts/1').expect({}).expect(200)
assert.strictEqual(db.posts.length, 1)
assert.strictEqual(db.comments.length, 1)
})

View File

@ -12,7 +12,7 @@ describe('Server', () => {
'/blog/posts/:id/show': '/posts/:id',
'/comments/special/:userId-:body': '/comments/?userId=:userId&body=:body',
'/firstpostwithcomments': '/posts/1?_embed=comments',
'/articles\\?_id=:id': '/posts/:id'
'/articles\\?_id=:id': '/posts/:id',
}
beforeEach(() => {
@ -20,18 +20,18 @@ describe('Server', () => {
db.posts = [
{ id: 1, body: 'foo' },
{ id: 2, body: 'bar' }
{ id: 2, body: 'bar' },
]
db.tags = [
{ id: 1, body: 'Technology' },
{ id: 2, body: 'Photography' },
{ id: 3, body: 'photo' }
{ id: 3, body: 'photo' },
]
db.users = [
{ id: 1, username: 'Jim', tel: '0123' },
{ id: 2, username: 'George', tel: '123' }
{ id: 2, username: 'George', tel: '123' },
]
db.comments = [
@ -39,7 +39,7 @@ describe('Server', () => {
{ id: 2, body: 'bar', published: false, postId: 1, userId: 2 },
{ id: 3, body: 'baz', published: false, postId: 2, userId: 1 },
{ 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.buyers = [
@ -51,11 +51,11 @@ describe('Server', () => {
{ id: 6, name: 'Frank', country: 'Belize', total: 10 },
{ id: 7, name: 'Grace', country: 'Argentina', total: 1 },
{ id: 8, name: 'Henry', country: 'Argentina', total: 2 },
{ id: 9, name: 'Isabelle', country: 'Argentina', total: 3 }
{ id: 9, name: 'Isabelle', country: 'Argentina', total: 3 },
]
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 = [{ id: '1234' }]
@ -65,7 +65,7 @@ describe('Server', () => {
db.nested = [
{ resource: { name: 'dewey' } },
{ resource: { name: 'cheatem' } },
{ resource: { name: 'howe' } }
{ resource: { name: 'howe' } },
]
db.list = [
@ -83,7 +83,7 @@ describe('Server', () => {
{ id: 12 },
{ id: 13 },
{ id: 14 },
{ id: 15 }
{ id: 15 },
]
server = jsonServer.create()
@ -114,9 +114,7 @@ describe('Server', () => {
.expect(200))
test('should respond with 404 if resource is not found', () =>
request(server)
.get('/undefined')
.expect(404))
request(server).get('/undefined').expect(404))
})
describe('GET /:resource?attr=&attr=', () => {
@ -277,7 +275,7 @@ describe('Server', () => {
db.buyers[5],
db.buyers[2],
db.buyers[1],
db.buyers[0]
db.buyers[0],
])
.expect(200))
})
@ -321,7 +319,7 @@ describe('Server', () => {
'<http://localhost/list?_page=1&_limit=1>; rel="first"',
'<http://localhost/list?_page=1&_limit=1>; rel="prev"',
'<http://localhost/list?_page=3&_limit=1>; rel="next"',
'<http://localhost/list?_page=15&_limit=1>; rel="last"'
'<http://localhost/list?_page=15&_limit=1>; rel="last"',
].join(', ')
return request(server)
.get('/list?_page=2&_limit=1')
@ -518,7 +516,7 @@ describe('Server', () => {
})
describe('GET /:resource>_delay=', () => {
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request(server)
.get('/posts?_delay=1100')
@ -575,7 +573,7 @@ describe('Server', () => {
})
describe('POST /:resource?_delay=', () => {
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request(server)
.post('/posts?_delay=1100')
@ -615,7 +613,7 @@ describe('Server', () => {
})
describe('PUT /:resource:id?_delay=', () => {
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request(server)
.put('/posts/1?_delay=1100')
@ -653,7 +651,7 @@ describe('Server', () => {
})
describe('PATCH /:resource:id?_delay=', () => {
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request(server)
.patch('/posts/1?_delay=1100')
@ -668,10 +666,7 @@ describe('Server', () => {
describe('DELETE /:resource/:id', () => {
test('should respond with empty data, destroy resource and dependent resources', async () => {
await request(server)
.del('/posts/1')
.expect({})
.expect(200)
await request(server).del('/posts/1').expect({}).expect(200)
assert.strictEqual(db.posts.length, 1)
assert.strictEqual(db.comments.length, 3)
})
@ -685,7 +680,7 @@ describe('Server', () => {
})
describe('DELETE /:resource:id?_delay=', () => {
test('should delay response', done => {
test('should delay response', (done) => {
const start = new Date()
request(server)
.del('/posts/1?_delay=1100')
@ -740,37 +735,25 @@ describe('Server', () => {
describe('Rewriter', () => {
test('should rewrite using prefix', () =>
request(server)
.get('/api/posts/1')
.expect(db.posts[0]))
request(server).get('/api/posts/1').expect(db.posts[0]))
test('should rewrite using params', () =>
request(server)
.get('/blog/posts/1/show')
.expect(db.posts[0]))
request(server).get('/blog/posts/1/show').expect(db.posts[0]))
test('should rewrite using query without params', () => {
const expectedPost = _.cloneDeep(db.posts[0])
expectedPost.comments = [db.comments[0], db.comments[1]]
return request(server)
.get('/firstpostwithcomments')
.expect(expectedPost)
return request(server).get('/firstpostwithcomments').expect(expectedPost)
})
test('should rewrite using params and query', () =>
request(server)
.get('/comments/special/1-quux')
.expect([db.comments[4]]))
request(server).get('/comments/special/1-quux').expect([db.comments[4]]))
test('should rewrite query params', () =>
request(server)
.get('/articles?_id=1')
.expect(db.posts[0]))
request(server).get('/articles?_id=1').expect(db.posts[0]))
test('should expose routes', () =>
request(server)
.get('/__rules')
.expect(rewriterRules))
request(server).get('/__rules').expect(rewriterRules))
})
describe('router.render', () => {
@ -791,7 +774,7 @@ describe('Server', () => {
describe('router.db._.id', () => {
beforeEach(() => {
router.db.setState({
posts: [{ _id: 1 }]
posts: [{ _id: 1 }],
})
router.db._.id = '_id'

View File

@ -12,7 +12,7 @@ describe('Fake server', () => {
db.user = {
name: 'foo',
email: 'foo@example.com'
email: 'foo@example.com',
}
server = jsonServer.create()
@ -24,11 +24,7 @@ describe('Fake server', () => {
describe('POST /:resource', () => {
test('should not create resource', async () => {
const user = { name: 'bar' }
await request(server)
.post('/user')
.send(user)
.expect(user)
.expect(201)
await request(server).post('/user').send(user).expect(user).expect(201)
assert.notDeepStrictEqual(db.user, user)
})
})
@ -36,11 +32,7 @@ describe('Fake server', () => {
describe('PUT /:resource', () => {
test('should not update resource', async () => {
const user = { name: 'bar' }
await request(server)
.put('/user')
.send(user)
.expect(user)
.expect(200)
await request(server).put('/user').send(user).expect(user).expect(200)
assert.notDeepStrictEqual(db.user, user)
})
})

View File

@ -11,7 +11,7 @@ describe('Server', () => {
db.user = {
name: 'foo',
email: 'foo@example.com'
email: 'foo@example.com',
}
server = jsonServer.create()
@ -22,31 +22,20 @@ describe('Server', () => {
describe('GET /:resource', () => {
test('should respond with corresponding resource', () =>
request(server)
.get('/user')
.expect(db.user)
.expect(200))
request(server).get('/user').expect(db.user).expect(200))
})
describe('POST /:resource', () => {
test('should create resource', () => {
const user = { name: 'bar' }
return request(server)
.post('/user')
.send(user)
.expect(user)
.expect(201)
return request(server).post('/user').send(user).expect(user).expect(201)
})
})
describe('PUT /:resource', () => {
test('should update resource', () => {
const user = { name: 'bar' }
return request(server)
.put('/user')
.send(user)
.expect(user)
.expect(200)
return request(server).put('/user').send(user).expect(user).expect(200)
})
})

View File

@ -12,7 +12,7 @@ describe('utils', () => {
current: 1,
first: 1,
next: 2,
last: 3
last: 3,
})
})
@ -23,7 +23,7 @@ describe('utils', () => {
first: 1,
prev: 1,
next: 3,
last: 3
last: 3,
})
})
@ -33,25 +33,25 @@ describe('utils', () => {
current: 3,
first: 1,
prev: 2,
last: 3
last: 3,
})
})
test('should return an empty array if page is greater than the last page', () => {
assert.deepStrictEqual(utils.getPage(array, 99, perPage), {
items: []
items: [],
})
})
test('should return the array if perPage is greater than the array size', () => {
assert.deepStrictEqual(utils.getPage(array, 1, 99), {
items: array
items: array,
})
})
test('should return an empty array if the array is empty', () => {
assert.deepStrictEqual(utils.getPage([], 1, 1), {
items: []
items: [],
})
})
})

View File

@ -22,52 +22,52 @@
},
"dependencies": {
"body-parser": "^1.19.0",
"chalk": "^3.0.0",
"chalk": "^4.1.0",
"compression": "^1.7.4",
"connect-pause": "^0.1.1",
"cors": "^2.8.5",
"errorhandler": "^1.5.1",
"express": "^4.17.1",
"express-urlrewrite": "^1.2.0",
"express-urlrewrite": "^1.3.0",
"json-parse-helpfulerror": "^1.0.3",
"lodash": "^4.17.15",
"lodash": "^4.17.20",
"lodash-id": "^0.14.0",
"lowdb": "^1.0.0",
"method-override": "^3.0.0",
"morgan": "^1.9.1",
"nanoid": "^2.1.11",
"morgan": "^1.10.0",
"nanoid": "^3.1.16",
"please-upgrade-node": "^3.2.0",
"pluralize": "^8.0.0",
"server-destroy": "^1.0.1",
"update-notifier": "^4.0.0",
"yargs": "^15.1.0"
"update-notifier": "^5.0.1",
"yargs": "^16.1.1"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
"@babel/node": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"cross-env": "^7.0.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-prettier": "^3.1.2",
"@babel/cli": "^7.12.1",
"@babel/core": "^7.12.3",
"@babel/node": "^7.12.6",
"@babel/preset-env": "^7.12.1",
"cross-env": "^7.0.2",
"eslint": "^7.13.0",
"eslint-config-prettier": "^6.15.0",
"eslint-config-standard": "^16.0.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-standard": "^4.1.0",
"husky": "^5.0.0-beta.0",
"jest": "^25.1.0",
"jest": "^26.6.3",
"markdown-toc": "^1.2.0",
"mkdirp": "^1.0.3",
"mkdirp": "^1.0.4",
"npm-run-all": "^4.1.5",
"os-tmpdir": "^2.0.0",
"pinst": "^2.1.1",
"pkg-ok": "^2.3.1",
"prettier": "^1.19.1",
"prettier": "^2.1.2",
"rimraf": "^3.0.2",
"server-ready": "^0.3.1",
"supertest": "^4.0.2",
"supertest": "^6.0.1",
"temp-write": "^4.0.0"
},
"repository": {

View File

@ -11,10 +11,10 @@ function ResourceList({ db }) {
return `
<ul>
${Object.keys(db)
.map(name =>
.map((name) =>
ResourceItem({
name,
length: Array.isArray(db[name]) && db[name].length
length: Array.isArray(db[name]) && db[name].length,
})
)
.join('')}
@ -37,9 +37,9 @@ function ResourcesBlock({ db }) {
window
.fetch('db')
.then(response => response.json())
.then((response) => response.json())
.then(
db =>
(db) =>
(document.getElementById('resources').innerHTML = ResourcesBlock({ db }))
)
@ -52,7 +52,7 @@ function CustomRoutesBlock({ customRoutes }) {
<table>
${rules
.map(
rule =>
(rule) =>
`<tr>
<td>${rule}</td>
<td><code>⇢</code> ${customRoutes[rule]}</td>
@ -67,10 +67,10 @@ function CustomRoutesBlock({ customRoutes }) {
window
.fetch('__rules')
.then(response => response.json())
.then((response) => response.json())
.then(
customRoutes =>
(customRoutes) =>
(document.getElementById('custom-routes').innerHTML = CustomRoutesBlock({
customRoutes
customRoutes,
}))
)

View File

@ -13,70 +13,70 @@ module.exports = function() {
port: {
alias: 'p',
description: 'Set port',
default: 3000
default: 3000,
},
host: {
alias: 'H',
description: 'Set host',
default: 'localhost'
default: 'localhost',
},
watch: {
alias: 'w',
description: 'Watch file(s)'
description: 'Watch file(s)',
},
routes: {
alias: 'r',
description: 'Path to routes file'
description: 'Path to routes file',
},
middlewares: {
alias: 'm',
array: true,
description: 'Paths to middleware files'
description: 'Paths to middleware files',
},
static: {
alias: 's',
description: 'Set static files directory'
description: 'Set static files directory',
},
'read-only': {
alias: 'ro',
description: 'Allow only GET requests'
description: 'Allow only GET requests',
},
'no-cors': {
alias: 'nc',
description: 'Disable Cross-Origin Resource Sharing'
description: 'Disable Cross-Origin Resource Sharing',
},
'no-gzip': {
alias: 'ng',
description: 'Disable GZIP Content-Encoding'
description: 'Disable GZIP Content-Encoding',
},
snapshots: {
alias: 'S',
description: 'Set snapshots directory',
default: '.'
default: '.',
},
delay: {
alias: 'd',
description: 'Add delay to responses (ms)'
description: 'Add delay to responses (ms)',
},
id: {
alias: 'i',
description: 'Set database id property (e.g. _id)',
default: 'id'
default: 'id',
},
foreignKeySuffix: {
alias: 'fks',
description: 'Set foreign key suffix (e.g. _id as in post_id)',
default: 'Id'
default: 'Id',
},
quiet: {
alias: 'q',
description: 'Suppress log messages from output'
description: 'Suppress log messages from output',
},
config: {
alias: 'c',
description: 'Path to config file',
default: 'json-server.json'
}
default: 'json-server.json',
},
})
.boolean('watch')
.boolean('read-only')

View File

@ -21,7 +21,7 @@ function prettyPrint(argv, object, rules) {
if (rules) {
console.log()
console.log(chalk.bold(' Other routes'))
for (var rule in rules) {
for (const rule in rules) {
console.log(` ${rule} -> ${rules[rule]}`)
}
}
@ -47,7 +47,7 @@ function createApp(db, routes, middlewares, argv) {
readOnly: argv.readOnly,
noCors: argv.noCors,
noGzip: argv.noGzip,
bodyParser: true
bodyParser: true,
}
if (argv.static) {
@ -103,7 +103,7 @@ module.exports = function(argv) {
server = undefined
// create db and load object, JSON file, JS or HTTP database
return load(source).then(db => {
return load(source).then((db) => {
// Load additional routes
let routes
if (argv.routes) {
@ -134,7 +134,7 @@ module.exports = function(argv) {
prettyPrint(argv, db.getState(), routes)
// Catch and handle any error occurring in the server process
process.on('uncaughtException', error => {
process.on('uncaughtException', (error) => {
if (error.errno === 'EADDRINUSE')
console.log(
chalk.red(
@ -164,7 +164,7 @@ module.exports = function(argv) {
console.log(` Creating a snapshot from the CLI won't be possible`)
})
process.stdin.setEncoding('utf8')
process.stdin.on('data', chunk => {
process.stdin.on('data', (chunk) => {
if (chunk.trim().toLowerCase() === 's') {
const filename = `db-${Date.now()}.json`
const file = path.join(argv.snapshots, filename)
@ -240,7 +240,7 @@ module.exports = function(argv) {
}
}
})
.catch(err => {
.catch((err) => {
console.log(err)
process.exit(1)
})

View File

@ -1,7 +1,7 @@
module.exports = {
FILE,
JS,
URL
URL,
}
function FILE(s) {

View File

@ -11,7 +11,7 @@ const chalk = require('chalk')
const example = {
posts: [{ id: 1, title: 'json-server', author: 'typicode' }],
comments: [{ id: 1, body: 'some comment', postId: 1 }],
profile: { name: 'typicode' }
profile: { name: 'typicode' },
}
module.exports = function (source) {
@ -32,9 +32,9 @@ module.exports = function(source) {
const client = sourceUrl.protocol === 'https:' ? https : http
client
.get(sourceUrl, res => {
.get(sourceUrl, (res) => {
let dbData = ''
res.on('data', data => {
res.on('data', (data) => {
dbData += data
})
@ -42,7 +42,7 @@ module.exports = function(source) {
resolve(low(new Memory()).setState(JSON.parse(dbData)))
})
})
.on('error', error => {
.on('error', (error) => {
return reject(error)
})
} else if (is.JS(source)) {

View File

@ -2,5 +2,5 @@ const bodyParser = require('body-parser')
module.exports = [
bodyParser.json({ limit: '10mb', extended: false }),
bodyParser.urlencoded({ extended: false })
bodyParser.urlencoded({ extended: false }),
]

View File

@ -38,8 +38,8 @@ module.exports = function(opts) {
if (opts.logger) {
arr.push(
logger('dev', {
skip: req =>
process.env.NODE_ENV === 'test' || req.path === '/favicon.ico'
skip: (req) =>
process.env.NODE_ENV === 'test' || req.path === '/favicon.ico',
})
)
}

View File

@ -5,5 +5,5 @@ module.exports = {
defaults: require('./defaults'),
router: require('./router'),
rewriter: require('./rewriter'),
bodyParser: require('./body-parser')
bodyParser: require('./body-parser'),
}

View File

@ -1,10 +1,10 @@
const nanoid = require('nanoid')
const { nanoid } = require('nanoid')
const pluralize = require('pluralize')
module.exports = {
getRemovable,
createId,
deepQuery
deepQuery,
}
// Returns document ids that have unsatisfied relations
@ -13,7 +13,7 @@ function getRemovable(db, opts) {
const _ = this
const removable = []
_.each(db, (coll, collName) => {
_.each(coll, doc => {
_.each(coll, (doc) => {
_.each(doc, (value, key) => {
if (new RegExp(`${opts.foreignKeySuffix}$`).test(key)) {
// Remove foreign key suffix and pluralize it
@ -67,12 +67,7 @@ function deepQuery(value, q) {
return true
}
}
} else if (
value
.toString()
.toLowerCase()
.indexOf(q) !== -1
) {
} else if (value.toString().toLowerCase().indexOf(q) !== -1) {
return true
}
}

View File

@ -1,14 +1,14 @@
const express = require('express')
const rewrite = require('express-urlrewrite')
module.exports = routes => {
module.exports = (routes) => {
const router = express.Router()
router.get('/__rules', (req, res) => {
res.json(routes)
})
Object.keys(routes).forEach(key => {
Object.keys(routes).forEach((key) => {
router.use(rewrite(key, routes[key]))
})

View File

@ -3,7 +3,7 @@ const url = require('url')
module.exports = function getFullURL(req) {
const root = url.format({
protocol: req.protocol,
host: req.get('host')
host: req.get('host'),
})
return `${root}${req.originalUrl}`

View File

@ -64,7 +64,7 @@ module.exports = (db, opts) => {
return
}
var sourceMessage = ''
const sourceMessage = ''
// if (!_.isObject(source)) {
// sourceMessage = `in ${source}`
// }

View File

@ -2,7 +2,7 @@ const express = require('express')
const pluralize = require('pluralize')
const delay = require('./delay')
module.exports = opts => {
module.exports = (opts) => {
const router = express.Router()
router.use(delay)

View File

@ -14,7 +14,7 @@ module.exports = (db, name, opts) => {
// Embed function used in GET /name and GET /name/id
function embed(resource, e) {
e &&
[].concat(e).forEach(externalResource => {
[].concat(e).forEach((externalResource) => {
if (db.get(externalResource).value) {
const query = {}
const singularResource = pluralize.singular(name)
@ -30,7 +30,7 @@ module.exports = (db, name, opts) => {
// Expand function used in GET /name and GET /name/id
function expand(resource, e) {
e &&
[].concat(e).forEach(innerResource => {
[].concat(e).forEach((innerResource) => {
const plural = pluralize(innerResource)
if (db.get(plural).value()) {
const prop = `${innerResource}${opts.foreignKeySuffix}`
@ -74,7 +74,7 @@ module.exports = (db, name, opts) => {
// Automatically delete query parameters that can't be found
// in the database
Object.keys(req.query).forEach(query => {
Object.keys(req.query).forEach((query) => {
const arr = db.get(name).value()
for (const i in arr) {
if (
@ -99,17 +99,18 @@ module.exports = (db, name, opts) => {
q = q.toLowerCase()
chain = chain.filter(obj => {
chain = chain.filter((obj) => {
for (const key in obj) {
const value = obj[key]
if (db._.deepQuery(value, q)) {
return true
}
}
return false
})
}
Object.keys(req.query).forEach(key => {
Object.keys(req.query).forEach((key) => {
// Don't take into account JSONP query parameters
// jQuery adds a '_' query parameter too
if (key !== 'callback' && key !== '_') {
@ -121,7 +122,7 @@ module.exports = (db, name, opts) => {
const isLike = /_like$/.test(key)
const path = key.replace(/(_lte|_gte|_ne|_like)$/, '')
chain = chain.filter(element => {
chain = chain.filter((element) => {
return arr
.map(function (value) {
// get item value based on path
@ -130,7 +131,7 @@ module.exports = (db, name, opts) => {
// Prevent toString() failing on undefined or null values
if (elementValue === undefined || elementValue === null) {
return
return undefined
}
if (isRange) {
@ -155,7 +156,7 @@ module.exports = (db, name, opts) => {
// Sort
if (_sort) {
const _sortSet = _sort.split(',')
const _orderSet = (_order || '').split(',').map(s => s.toLowerCase())
const _orderSet = (_order || '').split(',').map((s) => s.toLowerCase())
chain = chain.orderBy(_sortSet, _orderSet)
}
@ -231,10 +232,7 @@ module.exports = (db, name, opts) => {
function show(req, res, next) {
const _embed = req.query._embed
const _expand = req.query._expand
const resource = db
.get(name)
.getById(req.params.id)
.value()
const resource = db.get(name).getById(req.params.id).value()
if (resource) {
// Clone resource to avoid making changes to the underlying object
@ -258,16 +256,10 @@ module.exports = (db, name, opts) => {
function create(req, res, next) {
let resource
if (opts._isFake) {
const id = db
.get(name)
.createId()
.value()
const id = db.get(name).createId().value()
resource = { ...req.body, id }
} else {
resource = db
.get(name)
.insert(req.body)
.value()
resource = db.get(name).insert(req.body).value()
}
res.setHeader('Access-Control-Expose-Headers', 'Location')
@ -286,10 +278,7 @@ module.exports = (db, name, opts) => {
let resource
if (opts._isFake) {
resource = db
.get(name)
.getById(id)
.value()
resource = db.get(name).getById(id).value()
if (req.method === 'PATCH') {
resource = { ...resource, ...req.body }
@ -321,17 +310,12 @@ module.exports = (db, name, opts) => {
if (opts._isFake) {
resource = db.get(name).value()
} else {
resource = db
.get(name)
.removeById(req.params.id)
.value()
resource = db.get(name).removeById(req.params.id).value()
// Remove dependents documents
const removable = db._.getRemovable(db.getState(), opts)
removable.forEach(item => {
db.get(item.name)
.removeById(item.id)
.value()
removable.forEach((item) => {
db.get(item.name).removeById(item.id).value()
})
}
@ -344,10 +328,7 @@ module.exports = (db, name, opts) => {
const w = write(db)
router
.route('/')
.get(list)
.post(create, w)
router.route('/').get(list).post(create, w)
router
.route('/:id')

View File

@ -39,9 +39,7 @@ module.exports = (db, name, opts) => {
if (req.method === 'PUT') {
db.set(name, req.body).value()
} else {
db.get(name)
.assign(req.body)
.value()
db.get(name).assign(req.body).value()
}
res.locals.data = db.get(name).value()
@ -52,12 +50,7 @@ module.exports = (db, name, opts) => {
const w = write(db)
router
.route('/')
.get(show)
.post(create, w)
.put(update, w)
.patch(update, w)
router.route('/').get(show).post(create, w).put(update, w).patch(update, w)
return router
}

View File

@ -6,13 +6,13 @@ function validateKey(key) {
`Oops, found / character in database property '${key}'.`,
'',
"/ aren't supported, if you want to tweak default routes, see",
'https://github.com/typicode/json-server/#add-custom-routes'
'https://github.com/typicode/json-server/#add-custom-routes',
].join('\n')
throw new Error(msg)
}
}
module.exports = obj => {
module.exports = (obj) => {
if (_.isPlainObject(obj)) {
Object.keys(obj).forEach(validateKey)
} else {

View File

@ -1,11 +1,11 @@
module.exports = {
getPage
getPage,
}
function getPage(array, page, perPage) {
var obj = {}
var start = (page - 1) * perPage
var end = page * perPage
const obj = {}
const start = (page - 1) * perPage
const end = page * perPage
obj.items = array.slice(start, end)
if (obj.items.length === 0) {