Files
http-server-drf/build-helpers.ts
2025-03-11 08:16:29 -04:00

171 lines
4.8 KiB
TypeScript

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/* eslint no-console: "off" */
import fs from "node:fs/promises";
import path from "node:path";
const HELPER_DECLARATION_PATH = path.resolve("generated-defs", "helpers");
const HELPER_SRC_PATH = path.resolve("src", "helpers");
console.log("Building JS server generator helpers.");
async function* visitAllFiles(base: string): AsyncIterable<string> {
const contents = await fs.readdir(base, { withFileTypes: true });
for (const entry of contents) {
if (entry.isDirectory()) {
yield* visitAllFiles(path.join(base, entry.name));
} else if (entry.isFile()) {
yield path.join(base, entry.name);
}
}
}
async function main() {
const allFiles: string[] = [];
const indices = new Map<string, string[]>();
const ctxPath = path.resolve("src", "ctx.js");
await fs.rm(HELPER_DECLARATION_PATH, { recursive: true, force: true });
function addIndex(dir: string, file: string) {
const index = indices.get(dir);
if (index) {
index.push(file);
} else {
indices.set(dir, [file]);
}
}
for await (const file of visitAllFiles(HELPER_SRC_PATH)) {
allFiles.push(file);
addIndex(path.dirname(file), file);
}
for (const file of allFiles) {
if (!file.endsWith(".ts")) {
continue;
}
const relativePath = path.relative(HELPER_SRC_PATH, file);
console.log("Building helper:", relativePath);
const targetPath = path.resolve(HELPER_DECLARATION_PATH, relativePath);
const targetDir = path.dirname(targetPath);
const targetFileBase = path.basename(targetPath, ".ts");
const isIndex = targetFileBase === "index";
const targetBase = isIndex ? path.basename(targetDir) : targetFileBase;
await fs.mkdir(targetDir, { recursive: true });
const childModules = isIndex ? indices.get(path.dirname(file)) : [];
if (isIndex) {
indices.delete(path.dirname(file));
}
const contents = await fs.readFile(file, "utf-8");
let childModuleLines =
childModules
?.filter((m) => path.basename(m, ".ts") !== "index")
.map((child) => {
const childBase = path.basename(child, ".ts");
return ` await import("./${childBase}.js").then((m) => m.createModule(module));`;
}) ?? [];
if (childModuleLines.length > 0) {
childModuleLines = [" // Child modules", ...childModuleLines, ""];
}
const transformed = [
"// Copyright (c) Microsoft Corporation",
"// Licensed under the MIT license.",
"",
`import { Module } from "${path.relative(targetDir, ctxPath).replace(/\\/g, "/")}";`,
"",
"export let module: Module = undefined as any;",
"",
"// prettier-ignore",
"const lines = [",
...contents.split(/\r?\n/).map((line) => " " + JSON.stringify(line) + ","),
"];",
"",
"export async function createModule(parent: Module): Promise<Module> {",
" if (module) return module;",
"",
" module = {",
` name: ${JSON.stringify(targetBase)},`,
` cursor: parent.cursor.enter(${JSON.stringify(targetBase)}),`,
" imports: [],",
" declarations: [],",
" };",
"",
...childModuleLines,
" module.declarations.push(lines);",
"",
" parent.declarations.push(module);",
"",
" return module;",
"}",
"",
].join("\n");
await fs.writeFile(targetPath, transformed);
}
console.log("Building index files.");
for (const [dir, files] of indices.entries()) {
console.log("Building index:", dir);
const relativePath = path.relative(HELPER_SRC_PATH, dir);
const targetPath = path.resolve(HELPER_DECLARATION_PATH, relativePath, "index.ts");
const children = files.map((file) => {
return ` await import("./${path.basename(file, ".ts")}.js").then((m) => m.createModule(module));`;
});
const transformed = [
"// Copyright (c) Microsoft Corporation",
"// Licensed under the MIT license.",
"",
`import { Module } from "${path.relative(path.dirname(targetPath), ctxPath).replace(/\\/g, "/")}";`,
"",
"export let module: Module = undefined as any;",
"",
"export async function createModule(parent: Module): Promise<Module> {",
" if (module) return module;",
"",
" module = {",
` name: ${JSON.stringify(path.basename(dir))},`,
` cursor: parent.cursor.enter(${JSON.stringify(path.basename(dir))}),`,
" imports: [],",
" declarations: [],",
" };",
"",
" // Child modules",
...children,
"",
" parent.declarations.push(module);",
"",
" return module;",
"}",
"",
].join("\n");
await fs.writeFile(targetPath, transformed);
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});