Skip to content

Commit 913473f

Browse files
committed
Use latest lowdb
1 parent 0241ad5 commit 913473f

File tree

5 files changed

+157
-163
lines changed

5 files changed

+157
-163
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"json-parse-helpfulerror": "^1.0.3",
3434
"lodash": "^4.17.10",
3535
"lodash-id": "^0.14.0",
36-
"lowdb": "^0.15.0",
36+
"lowdb": "^1.0.0",
3737
"method-override": "^2.3.10",
3838
"morgan": "^1.9.0",
3939
"nanoid": "^1.0.2",

src/cli/run.js

Lines changed: 96 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ const is = require('./utils/is')
99
const load = require('./utils/load')
1010
const jsonServer = require('../server')
1111

12-
const example = {
13-
posts: [{ id: 1, title: 'json-server', author: 'typicode' }],
14-
comments: [{ id: 1, body: 'some comment', postId: 1 }],
15-
profile: { name: 'typicode' }
16-
}
17-
1812
function prettyPrint(argv, object, rules) {
1913
const host = argv.host === '0.0.0.0' ? 'localhost' : argv.host
2014
const port = argv.port
@@ -40,22 +34,15 @@ function prettyPrint(argv, object, rules) {
4034
console.log()
4135
}
4236

43-
function createApp(source, object, routes, middlewares, argv) {
37+
function createApp(db, routes, middlewares, argv) {
4438
const app = jsonServer.create()
4539

46-
let router
47-
4840
const { foreignKeySuffix } = argv
49-
try {
50-
router = jsonServer.router(
51-
is.JSON(source) ? source : object,
52-
foreignKeySuffix ? { foreignKeySuffix } : undefined
53-
)
54-
} catch (e) {
55-
console.log()
56-
console.error(chalk.red(e.message.replace(/^/gm, ' ')))
57-
process.exit(1)
58-
}
41+
42+
let router = jsonServer.router(
43+
db,
44+
foreignKeySuffix ? { foreignKeySuffix } : undefined
45+
)
5946

6047
const defaultsOpts = {
6148
logger: !argv.quiet,
@@ -113,20 +100,10 @@ module.exports = function(argv) {
113100
function start(cb) {
114101
console.log()
115102

116-
// Be nice and create a default db.json if it doesn't exist
117-
if (is.JSON(source) && !fs.existsSync(source)) {
118-
console.log(chalk.yellow(` Oops, ${source} doesn't seem to exist`))
119-
console.log(chalk.yellow(` Creating ${source} with some default data`))
120-
console.log()
121-
fs.writeFileSync(source, JSON.stringify(example, null, 2))
122-
}
123-
124103
console.log(chalk.gray(' Loading', source))
125104

126-
// Load JSON, JS or HTTP database
127-
load(source, (err, data) => {
128-
if (err) throw err
129-
105+
// create db and load object, JSON file, JS or HTTP database
106+
return load(source).then(db => {
130107
// Load additional routes
131108
let routes
132109
if (argv.routes) {
@@ -147,109 +124,114 @@ module.exports = function(argv) {
147124
console.log(chalk.gray(' Done'))
148125

149126
// Create app and server
150-
app = createApp(source, data, routes, middlewares, argv)
127+
app = createApp(db, routes, middlewares, argv)
151128
server = app.listen(argv.port, argv.host)
152129

153130
// Enhance with a destroy function
154131
enableDestroy(server)
155132

156133
// Display server informations
157-
prettyPrint(argv, data, routes)
158-
159-
cb && cb()
134+
prettyPrint(argv, db.getState(), routes)
160135
})
161136
}
162137

163138
// Start server
164-
start(() => {
165-
// Snapshot
166-
console.log(
167-
chalk.gray(
168-
' Type s + enter at any time to create a snapshot of the database'
169-
)
170-
)
171-
172-
// Support nohup
173-
// https://github.com/typicode/json-server/issues/221
174-
process.stdin.on('error', () => {
175-
console.log(` Error, can't read from stdin`)
176-
console.log(` Creating a snapshot from the CLI won't be possible`)
177-
})
178-
process.stdin.setEncoding('utf8')
179-
process.stdin.on('data', chunk => {
180-
if (chunk.trim().toLowerCase() === 's') {
181-
const filename = `db-${Date.now()}.json`
182-
const file = path.join(argv.snapshots, filename)
183-
const state = app.db.getState()
184-
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
185-
console.log(
186-
` Saved snapshot to ${path.relative(process.cwd(), file)}\n`
139+
start()
140+
.then(() => {
141+
// Snapshot
142+
console.log(
143+
chalk.gray(
144+
' Type s + enter at any time to create a snapshot of the database'
187145
)
188-
}
189-
})
190-
191-
// Watch files
192-
if (argv.watch) {
193-
console.log(chalk.gray(' Watching...'))
194-
console.log()
195-
const source = argv._[0]
196-
197-
// Can't watch URL
198-
if (is.URL(source)) throw new Error("Can't watch URL")
199-
200-
// Watch .js or .json file
201-
// Since lowdb uses atomic writing, directory is watched instead of file
202-
const watchedDir = path.dirname(source)
203-
let readError = false
204-
fs.watch(watchedDir, (event, file) => {
205-
// https://github.com/typicode/json-server/issues/420
206-
// file can be null
207-
if (file) {
208-
const watchedFile = path.resolve(watchedDir, file)
209-
if (watchedFile === path.resolve(source)) {
210-
if (is.JSON(watchedFile)) {
211-
let obj
212-
try {
213-
obj = jph.parse(fs.readFileSync(watchedFile))
214-
if (readError) {
215-
console.log(chalk.green(` Read error has been fixed :)`))
216-
readError = false
217-
}
218-
} catch (e) {
219-
readError = true
220-
console.log(chalk.red(` Error reading ${watchedFile}`))
221-
console.error(e.message)
222-
return
223-
}
146+
)
224147

225-
// Compare .json file content with in memory database
226-
const isDatabaseDifferent = !_.isEqual(obj, app.db.getState())
227-
if (isDatabaseDifferent) {
228-
console.log(chalk.gray(` ${source} has changed, reloading...`))
229-
server && server.destroy()
230-
start()
231-
}
232-
}
233-
}
148+
// Support nohup
149+
// https://github.com/typicode/json-server/issues/221
150+
process.stdin.on('error', () => {
151+
console.log(` Error, can't read from stdin`)
152+
console.log(` Creating a snapshot from the CLI won't be possible`)
153+
})
154+
process.stdin.setEncoding('utf8')
155+
process.stdin.on('data', chunk => {
156+
if (chunk.trim().toLowerCase() === 's') {
157+
const filename = `db-${Date.now()}.json`
158+
const file = path.join(argv.snapshots, filename)
159+
const state = app.db.getState()
160+
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
161+
console.log(
162+
` Saved snapshot to ${path.relative(process.cwd(), file)}\n`
163+
)
234164
}
235165
})
236166

237-
// Watch routes
238-
if (argv.routes) {
239-
const watchedDir = path.dirname(argv.routes)
167+
// Watch files
168+
if (argv.watch) {
169+
console.log(chalk.gray(' Watching...'))
170+
console.log()
171+
const source = argv._[0]
172+
173+
// Can't watch URL
174+
if (is.URL(source)) throw new Error("Can't watch URL")
175+
176+
// Watch .js or .json file
177+
// Since lowdb uses atomic writing, directory is watched instead of file
178+
const watchedDir = path.dirname(source)
179+
let readError = false
240180
fs.watch(watchedDir, (event, file) => {
181+
// https://github.com/typicode/json-server/issues/420
182+
// file can be null
241183
if (file) {
242184
const watchedFile = path.resolve(watchedDir, file)
243-
if (watchedFile === path.resolve(argv.routes)) {
244-
console.log(
245-
chalk.gray(` ${argv.routes} has changed, reloading...`)
246-
)
247-
server && server.destroy()
248-
start()
185+
if (watchedFile === path.resolve(source)) {
186+
if (is.FILE(watchedFile)) {
187+
let obj
188+
try {
189+
obj = jph.parse(fs.readFileSync(watchedFile))
190+
if (readError) {
191+
console.log(chalk.green(` Read error has been fixed :)`))
192+
readError = false
193+
}
194+
} catch (e) {
195+
readError = true
196+
console.log(chalk.red(` Error reading ${watchedFile}`))
197+
console.error(e.message)
198+
return
199+
}
200+
201+
// Compare .json file content with in memory database
202+
const isDatabaseDifferent = !_.isEqual(obj, app.db.getState())
203+
if (isDatabaseDifferent) {
204+
console.log(
205+
chalk.gray(` ${source} has changed, reloading...`)
206+
)
207+
server && server.destroy()
208+
start()
209+
}
210+
}
249211
}
250212
}
251213
})
214+
215+
// Watch routes
216+
if (argv.routes) {
217+
const watchedDir = path.dirname(argv.routes)
218+
fs.watch(watchedDir, (event, file) => {
219+
if (file) {
220+
const watchedFile = path.resolve(watchedDir, file)
221+
if (watchedFile === path.resolve(argv.routes)) {
222+
console.log(
223+
chalk.gray(` ${argv.routes} has changed, reloading...`)
224+
)
225+
server && server.destroy()
226+
start()
227+
}
228+
}
229+
})
230+
}
252231
}
253-
}
254-
})
232+
})
233+
.catch(err => {
234+
console.log(err)
235+
process.exit(1)
236+
})
255237
}

src/cli/utils/is.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module.exports = {
2-
JSON,
2+
FILE,
33
JS,
44
URL
55
}
66

7-
function JSON(s) {
7+
function FILE(s) {
88
return !URL(s) && /\.json$/.test(s)
99
}
1010

src/cli/utils/load.js

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,57 @@
1+
const fs = require('fs')
12
const path = require('path')
23
const request = require('request')
34
const low = require('lowdb')
4-
const fileAsync = require('lowdb/lib/storages/file-async')
5+
const FileAsync = require('lowdb/adapters/FileAsync')
6+
const Memory = require('lowdb/adapters/Memory')
57
const is = require('./is')
8+
const chalk = require('chalk')
69

7-
module.exports = function(source, cb) {
8-
if (is.URL(source)) {
9-
// Load remote data
10-
const opts = {
11-
url: source,
12-
json: true
13-
}
10+
const example = {
11+
posts: [{ id: 1, title: 'json-server', author: 'typicode' }],
12+
comments: [{ id: 1, body: 'some comment', postId: 1 }],
13+
profile: { name: 'typicode' }
14+
}
1415

15-
request(opts, (err, response) => {
16-
if (err) return cb(err)
17-
cb(null, response.body)
18-
})
19-
} else if (is.JS(source)) {
20-
// Clear cache
21-
const filename = path.resolve(source)
22-
delete require.cache[filename]
23-
const dataFn = require(filename)
16+
module.exports = function(source) {
17+
return new Promise((resolve, reject) => {
18+
if (is.FILE(source)) {
19+
if (!fs.existsSync(source)) {
20+
console.log(chalk.yellow(` Oops, ${source} doesn't seem to exist`))
21+
console.log(chalk.yellow(` Creating ${source} with some default data`))
22+
console.log()
23+
fs.writeFileSync(source, JSON.stringify(example, null, 2))
24+
}
2425

25-
if (typeof dataFn !== 'function') {
26-
throw new Error(
27-
'The database is a JavaScript file but the export is not a function.'
28-
)
29-
}
26+
resolve(low(new FileAsync(source)))
27+
} else if (is.URL(source)) {
28+
// Load remote data
29+
const opts = {
30+
url: source,
31+
json: true
32+
}
3033

31-
// Run dataFn to generate data
32-
const data = dataFn()
33-
cb(null, data)
34-
} else if (is.JSON(source)) {
35-
// Load JSON using lowdb
36-
const data = low(source, { storage: fileAsync }).getState()
37-
cb(null, data)
38-
} else {
39-
throw new Error(`Unsupported source ${source}`)
40-
}
34+
request(opts, (err, response) => {
35+
if (err) return reject(err)
36+
resolve(low(new Memory()).setState(response.body))
37+
})
38+
} else if (is.JS(source)) {
39+
// Clear cache
40+
const filename = path.resolve(source)
41+
delete require.cache[filename]
42+
const dataFn = require(filename)
43+
44+
if (typeof dataFn !== 'function') {
45+
throw new Error(
46+
'The database is a JavaScript file but the export is not a function.'
47+
)
48+
}
49+
50+
// Run dataFn to generate data
51+
const data = dataFn()
52+
resolve(low(new Memory()).setState(data))
53+
} else {
54+
throw new Error(`Unsupported source ${source}`)
55+
}
56+
})
4157
}

0 commit comments

Comments
 (0)