UNPKG

3.82 kBJavaScriptView Raw
1const { join } = require('path')
2const fs = require('graceful-fs').promises
3const nodeReq = require('node-req')
4const nodeRes = require('node-res')
5
6module.exports = ({ ws, database, dir, watch }) => async (req, res) => {
7 const url = decodeURI(nodeReq.url(req))
8
9 // Handle WS
10 /* istanbul ignore if */
11 if (ws && url === '/ws') {
12 return ws.serve(req, req.socket, undefined)
13 }
14
15 let params = {}
16
17 // Handle body
18 /* istanbul ignore else */
19 if (['POST', 'PUT'].includes(req.method)) {
20 // If other server middleware has already consumed stream,
21 // there is no longer body data to wait (see #292)
22 if (req.readableEnded) {
23 params = req.body
24 } else {
25 let body = ''
26 req.on('data', function (data) {
27 body += data
28 })
29 // Wait for body data
30 await new Promise(function (resolve, reject) {
31 req.on('end', resolve)
32 req.on('error', reject)
33 })
34 // Parse body
35 if (body) {
36 params = JSON.parse(body)
37 }
38 }
39 } else if (req.method === 'GET') {
40 params = nodeReq.get(req)
41 }
42
43 if (watch) {
44 const filePath = join(dir, url)
45 const stats = await fs.lstat(filePath).catch(_ => null)
46 if (req.method === 'PUT' && stats && stats.isFile()) {
47 await fs.writeFile(filePath, params.file, 'utf-8')
48
49 return nodeRes.send(req, res, {})
50 }
51
52 if (req.method === 'GET' && stats && stats.isFile()) {
53 const file = await fs.readFile(filePath, 'utf-8')
54
55 return nodeRes.send(req, res, file)
56 }
57 }
58
59 const { sortBy, skip, limit, only, without, where, search, surround, deep, text, ...other } = params
60 params.where = Object.assign({}, params.where, other)
61
62 // Build query from query / body
63 let query = database.query(url, { deep: params.deep, text: params.text })
64 if (params.sortBy) {
65 if (typeof params.sortBy === 'object') {
66 if (Array.isArray(params.sortBy)) {
67 for (const sort of params.sortBy) {
68 if (typeof sort === 'string') {
69 const [key, value] = sort.split(':')
70 query = query.sortBy(key, value)
71 } else {
72 for (const [key, value] of Object.entries(sort)) {
73 query = query.sortBy(key, value)
74 }
75 }
76 }
77 } else {
78 for (const [key, value] of Object.entries(params.sortBy)) {
79 query = query.sortBy(key, value)
80 }
81 }
82 } else {
83 const [key, value] = params.sortBy.split(':')
84 query = query.sortBy(key, value)
85 }
86 }
87 if (params.skip) {
88 query = query.skip(params.skip)
89 }
90 if (params.limit) {
91 query = query.limit(params.limit)
92 }
93 if (params.only) {
94 query = query.only(params.only)
95 }
96 if (params.without) {
97 query = query.without(params.without)
98 }
99 if (params.where) {
100 const where = {}
101
102 for (const [key, value] of Object.entries(params.where)) {
103 const [field, operator] = key.split('_')
104
105 if (operator) {
106 where[field] = {
107 [`$${operator}`]: value
108 }
109 } else {
110 where[field] = value
111 }
112 }
113 query = query.where(where)
114 }
115 if (params.search) {
116 if (typeof params.search === 'object') {
117 query = query.search(params.search.query, params.search.value)
118 } else {
119 query = query.search(params.search)
120 }
121 }
122 if (params.surround) {
123 query = query.surround(params.surround.slugOrPath, params.surround.options)
124 }
125
126 let result
127 try {
128 // Call fetch method to collect data
129 result = await query.fetch()
130 nodeRes.etag(res, JSON.stringify(result))
131 if (nodeReq.fresh(req, res)) {
132 nodeRes.status(res, 304)
133 nodeRes.end(res)
134 return
135 }
136 } catch (e) {
137 nodeRes.status(res, 404)
138 result = { message: e.message }
139 }
140 nodeRes.send(req, res, result, false) // don't regenerate etags
141}