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() if (process.env.NODE_ENV === 'development') { 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((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) }