118 lines
2.5 KiB
TypeScript
118 lines
2.5 KiB
TypeScript
import http from 'http'
|
|
|
|
import express from 'express'
|
|
import lunr from 'lunr'
|
|
import morgan from 'morgan'
|
|
import * as z from 'zod'
|
|
|
|
import idxJson from '../build/idx.json'
|
|
import { dbPost, initDatabase } from './db'
|
|
|
|
export const SERVER_PORT = 5000
|
|
|
|
export async function runServer() {
|
|
await initDatabase()
|
|
|
|
const app = express()
|
|
app.use(morgan('common'))
|
|
|
|
const router = express.Router()
|
|
app.use('/api', router)
|
|
|
|
const idx = lunr.Index.load(idxJson)
|
|
|
|
router.get('/', (req, res) => {
|
|
const { path } = z
|
|
.object({
|
|
path: z.string(),
|
|
})
|
|
.parse(req.query)
|
|
|
|
const r = dbPost.findOne({ path })
|
|
if (!r) {
|
|
res.sendStatus(404)
|
|
return
|
|
}
|
|
|
|
res.json(r)
|
|
})
|
|
|
|
router.get('/q', (req, res) => {
|
|
const { q, tag, page: _page = '1' } = z
|
|
.object({
|
|
q: z.string().optional(),
|
|
tag: z.string().optional(),
|
|
page: z
|
|
.string()
|
|
.refine((s) => /^\d+$/.test(s))
|
|
.optional(),
|
|
})
|
|
.parse(req.query)
|
|
|
|
const perPage = 5
|
|
const offset = (parseInt(_page) - 1) * perPage
|
|
|
|
let cond = dbPost.chain().find({
|
|
date: { $exists: true } as any,
|
|
})
|
|
|
|
if (q) {
|
|
cond = cond.find({
|
|
path: { $in: idx.search(q).map(({ ref }) => ref) },
|
|
})
|
|
}
|
|
|
|
if (tag) {
|
|
cond = cond.find({
|
|
tag: { $contains: tag },
|
|
})
|
|
}
|
|
|
|
cond = cond.simplesort('date', { desc: true })
|
|
|
|
const count = cond.branch().count()
|
|
const result = cond.offset(offset).limit(5).data()
|
|
|
|
res.json({
|
|
count,
|
|
result,
|
|
})
|
|
})
|
|
|
|
app.use((err: Error, _: express.Request, res: express.Response) => {
|
|
// eslint-disable-next-line no-console
|
|
console.error(err.stack)
|
|
res.status(500).send(err)
|
|
})
|
|
|
|
await new Promise<http.Server | Error>((resolve) => {
|
|
const srv = app
|
|
.listen(SERVER_PORT, () => {
|
|
// eslint-disable-next-line no-console
|
|
console.info(
|
|
`serverMiddleware is running at http://localhost:${SERVER_PORT}`
|
|
)
|
|
resolve(srv)
|
|
})
|
|
.once('error', (e) => {
|
|
/**
|
|
* Nuxt generate will try to spawn two process on the same SERVER_PORT.
|
|
*
|
|
* One of which will inevitably fail.
|
|
*
|
|
* ! DO NOT reject()
|
|
*/
|
|
resolve(e)
|
|
})
|
|
.once('close', () => {
|
|
// eslint-disable-next-line no-console
|
|
console.info('serverMiddleware is closing')
|
|
})
|
|
})
|
|
}
|
|
|
|
if (require.main === module) {
|
|
// eslint-disable-next-line no-console
|
|
runServer().catch(console.error)
|
|
}
|