@opengis/fastify-table
Version:
core-plugins
208 lines (207 loc) • 8.6 kB
JavaScript
import fp from "fastify-plugin";
import path from "node:path";
import { fileURLToPath } from "node:url";
import proxy from "@fastify/http-proxy";
import addTemplateDir from "./server/plugins/table/funcs/addTemplateDir.js";
const filename = fileURLToPath(import.meta.url);
const cwd = path.dirname(filename);
// core templates && cls
config.templates?.forEach((el) => addTemplateDir(el));
addTemplateDir(path.join(cwd, "module/core"));
import config from "./config.js";
import { preForm, afterInsert, afterTable, afterTemplate, afterUpdate, preTemplate, onReady, onListen1, onListen2, } from "./functions.js";
import addHook from "./server/plugins/hook/addHook.js";
const { maxFileSize = 512 } = config;
const { name: execName } = path.parse(process.argv0);
const routes = [];
const policyCls = {
public: "Public", // old policy support
user: "User", // old policy support
site: "Public", // old policy support
L0: "Public",
L1: "User",
L2: "User",
L3: "User",
};
// helpers
// import helperPlugin from './server/helpers/index.js';
// plugins
import cronPlugin from "./server/plugins/cron/index.js";
import pgPlugin from "./server/plugins/pg/index.js";
import sqlitePlugin from "./server/plugins/sqlite/index.js";
import policyPlugin from "./server/plugins/policy/index.js";
import metricPlugin from "./server/plugins/metric/index.js";
import redisPlugin from "./server/plugins/redis/index.js";
import loggerPlugin from "./server/plugins/logger/index.js";
import authPlugin from "./server/plugins/auth/index.js";
// utils
import execMigrations from "./server/plugins/migration/exec.migrations.js";
import pgClients from "./server/plugins/pg/pgClients.js";
// routes
import cronRoutes from "./server/routes/cron/index.js";
import crudRoutes from "./server/routes/crud/index.js";
import loggerRoutes from "./server/routes/logger/index.js";
import propertiesRoutes from "./server/routes/properties/index.js";
import tableRoutes from "./server/routes/table/index.js";
import utilRoutes from "./server/routes/util/index.js";
import accessRoutes from "./server/routes/access/index.js";
import dblistRoutes from "./server/routes/dblist/index.js";
import menuRoutes from "./server/routes/menu/index.js";
import templatesRoutes from "./server/routes/templates/index.js";
import widgetRoutes from "./server/routes/widget/index.js";
import authRoutes from "./server/routes/auth/index.js";
import fileRoutes from "./server/routes/file/index.js";
import uploadChunkRoutes from "./server/routes/upload/index.js";
import grpcRoutes from "./server/routes/grpc/index.js";
import notificationsRoutes from "./server/routes/notifications/index.js";
import userClsRoutes from "./server/routes/usercls/index.js";
addHook("preForm", preForm);
addHook("afterTable", afterTable);
addHook("preTemplate", preTemplate);
addHook("afterTemplate", afterTemplate);
addHook("afterUpdate", afterUpdate);
addHook("afterInsert", afterInsert);
function plugin(fastify) {
const opt = { prefix: "/api" };
if (config.disableCors) {
fastify.addHook("onSend", async (request, reply) => {
reply.header("Access-Control-Allow-Origin", "*");
});
}
if (!fastify.hasRoute({ method: "GET", url: "/api/list" })) {
fastify.get(`${opt.prefix}/list`, { config: { role: "admin" } }, ({ query }) => {
const { package: packageName, subdir } = query;
if (packageName) {
return { rows: routes.filter((r) => r.package === packageName) };
}
if (subdir) {
return { rows: routes.filter((r) => r.subdir === subdir) };
}
return { rows: routes };
});
}
fastify.addHook("onRoute", (r) => {
if (r.method === "HEAD")
return;
const method = Array.isArray(r.method) ? "ALL" : r.method;
const query = r.schema?.querystring
? Object.keys(r.schema?.querystring?.properties || {}).reduce((acc, curr) => ({
...acc,
[curr]: r.schema?.querystring?.properties?.[curr]?.type,
}), {})
: undefined;
r.config = r.config || {};
r.config.package = r.config.package || "fastify-table";
routes.push({
method,
route: r.url,
subdir: r.config?.subdir,
package: r.config?.package,
description: r.config?.description,
query,
roles: r.config?.role?.split?.("|"),
policy: (Array.isArray(r.config?.policy)
? r.config?.policy
: r.config?.policy?.split?.(","))?.map?.((name) => policyCls[name] || name),
});
});
fastify.addHook("onListen", onListen1);
fastify.addHook("onListen", onListen2);
fastify.addHook("onReady", onReady);
// core migrations (second argument for core only)
execMigrations(path.join(cwd, "server/migrations"), pgClients.client, true).catch((err) => console.warn(err.toString()));
// plugins / utils / funcs
policyPlugin(fastify);
authPlugin(fastify); // fastify-auth api + hooks integrated to core
metricPlugin();
redisPlugin(fastify);
pgPlugin(fastify);
sqlitePlugin(fastify);
cronPlugin();
loggerPlugin(fastify);
if (config.rateLimit !== false) {
fastify.register(import("@fastify/rate-limit"), {
max: parseInt(config.rateLimit?.max || 100),
timeWindow: config.rateLimit?.timeWindow || 60000,
hook: "preHandler",
global: true,
keyGenerator: (req) => `${req.ip}-${req.raw.url.split("?")[0]}`,
});
}
else {
console.log("⚠️ rate limit is disabled");
}
// add multipart parser before any route registration
fastify.register(import("@fastify/multipart"), {
limits: {
fileSize: maxFileSize * 1024 * 1024,
},
});
if (config.dblist) {
fastify.register(dblistRoutes, opt);
}
// routes / api
fastify.register(cronRoutes, opt);
fastify.register(crudRoutes, opt);
fastify.register(loggerRoutes);
fastify.register(propertiesRoutes, opt);
fastify.register(tableRoutes, opt);
fastify.register(utilRoutes, opt);
fastify.register(accessRoutes, opt);
fastify.register(widgetRoutes, opt);
fastify.register(menuRoutes, opt);
fastify.register(templatesRoutes, opt);
fastify.register(authRoutes); // from fastify-auth
// from fastify-file
fastify.register(fileRoutes);
fastify.register(uploadChunkRoutes);
fastify.register(grpcRoutes, opt);
// from admin
fastify.register(notificationsRoutes, opt);
fastify.register(userClsRoutes, opt);
config.proxy?.forEach?.((el) => {
if (execName === "bun") {
fastify.all(`${el.source}/*`, async (req, reply) => {
const url = el.target.replace(/\/$/, "") +
req.raw.url.replace(new RegExp(`^${el.source}`), "");
const res = await fetch(url, {
method: req.method,
headers: {
// ...req.headers,
uid: req.user?.uid,
...(el.headers || {}),
},
body: ["PUT", "POST"].includes(req.method) ? req.raw : undefined,
});
reply.headers(Object.fromEntries(res.headers));
reply.status(res.status);
if (res.headers.get("content-type")?.startsWith?.("text/")) {
const resp = await res.text();
// reply.send(resp);
return resp;
}
if (res.headers.get("content-type")?.includes?.("/json")) {
const resp = await res.json();
// reply.send(resp);
return resp;
}
const blob = await res.blob();
const arrayBuffer = await blob.arrayBuffer();
const fileBuffer = Buffer.from(arrayBuffer);
return fileBuffer;
});
}
else {
fastify.register(proxy, {
upstream: el.target,
prefix: el.source,
http2: false,
preHandler: async (req) => {
req.headers.uid = req.session?.passport?.user?.uid;
Object.keys(el.headers || {})?.forEach((item) => (req.headers[item] = el.headers[item]));
},
});
}
});
}
export default fp(plugin);