diff --git a/client/demo/proxy.ts b/client/demo/proxy.ts index 51a7a40..8169939 100644 --- a/client/demo/proxy.ts +++ b/client/demo/proxy.ts @@ -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 = 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) -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) 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) + 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 { } +interface JSONArray extends Array { } + +function genDB(initialDB: JSONObject, skipRoot: boolean = true): Record { + return traverse(initialDB) + .reduce(function (acc: Record, 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 { return typeof value === 'object' && value !== null -} \ No newline at end of file +} + +// Проитерировать ключи обьекта +// сделать из них путь к базовому обьекту \ No newline at end of file diff --git a/client/demo/routes.json b/client/demo/routes.json index b96ce94..6929477 100644 --- a/client/demo/routes.json +++ b/client/demo/routes.json @@ -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" } \ No newline at end of file