Page MenuHomeSealhub

generate-routes.ts
No OneTemporary

generate-routes.ts

import { promises as fs } from "fs";
import { relative } from "path";
import _locreq from "locreq";
import { walkDir } from "./utils/walk";
import { importPath } from "./utils/import-path";
import { assertType, predicates } from "@sealcode/ts-predicates";
import { unescape_url_params } from "./utils/escape-url-params";
const target_locreq = _locreq(process.cwd());
async function extractActionName(full_file_path: string): Promise<string> {
const file_content = await fs.readFile(full_file_path, "utf-8");
const result = file_content.match(/export const actionName = "(\w+)"/);
if (result === null) {
throw new Error("Missing 'export const actionName' statement?");
}
return assertType(
result[1],
predicates.string,
"Missing export default class?"
);
}
export async function generateRoutes(): Promise<void> {
const files = await Promise.all(
(
await walkDir(target_locreq.resolve("src/back/routes"))
)
.filter(
(f) =>
f.endsWith(".page.ts") ||
f.endsWith(".form.ts") ||
f.endsWith(".list.ts")
)
.map(async (fullpath) => ({
fullpath,
actionName: await extractActionName(fullpath),
url: unescape_url_params(
"/" +
relative(
target_locreq.resolve("src/back/routes"),
fullpath
).replace(/\..+/, "") +
"/" // trailing slash is important here, as it enables to use the entire path while building relative URLs. For example, while visiting /users/123, the path ./add-photo leads to /users/add-photo. While visiting /users/123/ (note the trailing slash), the path ./add-photo leads to /users/123/add-photo
),
}))
);
await fs.writeFile(
target_locreq.resolve("src/back/routes/routes.ts"),
`// DO NOT EDIT! This file is generated automaticaly with npm run generate-routes
import Router from "@koa/router";
import { Middlewares } from "sealious";
import { Mountable } from "@sealcode/sealgen";
${files
.map(
({ actionName, fullpath }) =>
`import { default as ${actionName} } from "${importPath(
target_locreq.resolve("src/back/routes/routes.ts"),
fullpath
)}";`
)
.join("\n")}
${files
.map(({ actionName, url }) => `export const ${actionName}URL = "${url}";`)
.join("\n")}
function mount(router: Router, URL: string, mountable: Mountable) {
router.use(URL, Middlewares.extractContext(), Middlewares.parseBody());
mountable.init();
mountable.mount(router, URL);
// to automatically add trailing slashes:
router.get(URL.slice(0, -1), (ctx) => ctx.redirect(URL));
}
export default function mountAutoRoutes(router: Router) {
router.use(async (ctx, next) => {
await next();
if (ctx.body instanceof Promise) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
ctx.body = await ctx.body;
}
});
${files
.map(({ actionName }) => ` mount(router, ${actionName}URL, ${actionName});`)
.join("\n")}
}
`
);
// eslint-disable-next-line no-console
console.log("Successfuly generated new src/back/routes/routes.ts file");
}

File Metadata

Mime Type
text/x-java
Expires
Tue, Jul 8, 08:14 (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
810455
Default Alt Text
generate-routes.ts (2 KB)

Event Timeline