Fixed handling of nested paths and custom routes
This commit is contained in:
parent
90a8766b15
commit
b29ab1fccb
|
@ -1,6 +1,7 @@
|
|||
import { Request, Response } from "express"
|
||||
import { resolve } from "path"
|
||||
import { readFileSync } from "fs"
|
||||
import { stringify } from "querystring"
|
||||
import jsonServer from "json-server"
|
||||
import traverse from "traverse"
|
||||
|
||||
|
@ -10,16 +11,10 @@ const definedDB: Record<string, any> = JSON.parse(readFileSync(resolve(__dirname
|
|||
encoding: "utf8"
|
||||
}))
|
||||
|
||||
const autoDB = traverse(definedDB)
|
||||
.paths()
|
||||
.map(pathArray => ({
|
||||
path: pathArray.join("."),
|
||||
data: pathArray.reduce((db, pathSegment) => db[pathSegment], definedDB)
|
||||
}))
|
||||
.map(dbEntry => (dbEntry.data = isObject(dbEntry.data) ? dbEntry.data : ["$return", dbEntry.data], dbEntry))
|
||||
.reduce((acc, dbEntry) => (acc[dbEntry.path] = dbEntry.data, acc), {} as Record<string, any>)
|
||||
const db = Object.assign({}, autoDB, definedDB)
|
||||
const dbPaths = Object.keys(db)
|
||||
const autoDB = genDB(definedDB)
|
||||
const dbPaths = Object.keys(autoDB)
|
||||
|
||||
console.log(dbPaths)
|
||||
|
||||
// TODO: Reference types do not work at the ["$return", data] level
|
||||
// A possible solution is to replace filter with map and custom behavior for get, post and put
|
||||
|
@ -37,22 +32,15 @@ const autoRoutes = dbPaths
|
|||
}))
|
||||
.reduce((acc, bind) => (acc[bind.origin] = bind.destination, acc), {} as Record<string, string>)
|
||||
const routes = Object.assign({}, autoRoutes, definedRoutes)
|
||||
|
||||
const proxyServer = jsonServer.create()
|
||||
const middlewares = jsonServer.defaults()
|
||||
const rewriter = jsonServer.rewriter(routes)
|
||||
const router = jsonServer.router(db, {
|
||||
const router = jsonServer.router(autoDB, {
|
||||
foreignKeySuffix: "Id"
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
router.render = (req: Request, res: Response) => {
|
||||
const reqPath = req.path.replace("/", "")
|
||||
const matchedPath = dbPaths
|
||||
.map(path => path.replace(/\./g, "/"))
|
||||
.find(path => path !== reqPath && reqPath.startsWith(path))
|
||||
console.log(matchedPath)
|
||||
|
||||
if (typeof res.locals.data["_comment"] === "string" && res.locals.data["_comment"].toLowerCase().includes("todo"))
|
||||
return res.sendStatus(404)
|
||||
else if (Array.isArray(res.locals.data.list))
|
||||
|
@ -79,9 +67,58 @@ proxyServer.use(jsonServer.bodyParser)
|
|||
proxyServer.use(middlewares)
|
||||
|
||||
proxyServer.use("/api", rewriter)
|
||||
proxyServer.use("/api", (req, res, next) => {
|
||||
const query = stringify(req.query as Record<string, any>)
|
||||
const dbKey = req.path
|
||||
.replace("/", "")
|
||||
.replace(/\//g, ".")
|
||||
|
||||
if (autoDB[dbKey])
|
||||
req.url = `/${dbKey}${query ? "?" : ""}${query}`
|
||||
next()
|
||||
})
|
||||
|
||||
proxyServer.use("/api", router)
|
||||
proxyServer.listen(PROXY_PORT, () => console.info(`JSON proxy is running on ${PROXY_PORT} port`))
|
||||
|
||||
function isObject(value: unknown) {
|
||||
type JSONValue = string | number | boolean | JSONObject | JSONArray
|
||||
|
||||
interface JSONObject extends Record<string, JSONValue> { }
|
||||
interface JSONArray extends Array<JSONValue> { }
|
||||
|
||||
function genDB(initialDB: JSONObject, skipRoot: boolean = true): Record<string, JSONValue> {
|
||||
return traverse(initialDB)
|
||||
.reduce(function (acc: Record<string, any>, node) {
|
||||
if (skipRoot && this.isRoot)
|
||||
return acc
|
||||
const currentPath = this.path.join(".")
|
||||
|
||||
acc[currentPath] = isObject(node) ? node : ["$return", node]
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
node
|
||||
.filter(isObject)
|
||||
.map(childNode => [
|
||||
Object.values(childNode),
|
||||
genDB(childNode, false)
|
||||
] as const)
|
||||
.forEach(([values, childNodeDB]) =>
|
||||
values
|
||||
.filter(value => !!value && typeof value === "string" && !value.includes("."))
|
||||
.forEach(value => Object.keys(childNodeDB).forEach(childNodePath =>
|
||||
acc[`${currentPath}.${value}${childNodePath && "." || ""
|
||||
}${childNodePath}`.replace(/\//g, ".")] = childNodeDB[childNodePath]
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
function isObject(value: unknown): value is Record<string, any> {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
}
|
||||
|
||||
// Проитерировать ключи обьекта
|
||||
// сделать из них путь к базовому обьекту
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"/servapps/:container/logs": "/servapps/demo/logs",
|
||||
"/volume/:name": "/volumes/Volumes?Volumes.Name=:name",
|
||||
"/volume/:name": "/volumes/Volumes?Name=:name",
|
||||
"/network/:name": "/networks?Name=:name",
|
||||
"/servapps/:id/secure/:res": "/servapps/demo/secure",
|
||||
"/servapps/:id/manage/:action": "/servapps/demo/manage",
|
||||
"/servapps/:id/networks": "/servapps/:id?_embed=NetworkSettings.Networks",
|
||||
"/servapps/:id/networks": "/test/:id/NetworkSettings",
|
||||
"/test/:id": "/servapps?Id=:id",
|
||||
"/servapps/:containerId/network/:networkId": "/servapps/:containerId/networks"
|
||||
}
|
Loading…
Reference in a new issue