@nestia/sdk
Version:
Nestia SDK and Swagger generator
117 lines (107 loc) • 4.15 kB
text/typescript
import fs from "fs";
import ts from "typescript";
import { INestiaProject } from "../../structures/INestiaProject";
import { ITypedApplication } from "../../structures/ITypedApplication";
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
import { ITypedWebSocketRoute } from "../../structures/ITypedWebSocketRoute";
import { MapUtil } from "../../utils/MapUtil";
import { FilePrinter } from "./FilePrinter";
import { ImportDictionary } from "./ImportDictionary";
import { SdkHttpRouteProgrammer } from "./SdkHttpRouteProgrammer";
import { SdkRouteDirectory } from "./SdkRouteDirectory";
import { SdkWebSocketRouteProgrammer } from "./SdkWebSocketRouteProgrammer";
export namespace SdkFileProgrammer {
/* ---------------------------------------------------------
CONSTRUCTOR
--------------------------------------------------------- */
export const generate = async (app: ITypedApplication): Promise<void> => {
// CONSTRUCT FOLDER TREE
const root: SdkRouteDirectory = new SdkRouteDirectory(null, "functional");
for (const route of app.routes) emplace(root)(route);
// ITERATE FILES
await iterate(app.project)(root)(`${app.project.config.output}/functional`);
};
const emplace =
(directory: SdkRouteDirectory) =>
(route: ITypedHttpRoute | ITypedWebSocketRoute): void => {
// OPEN DIRECTORIES
for (const key of route.accessor.slice(0, -1)) {
directory = MapUtil.take(
directory.children,
key,
() => new SdkRouteDirectory(directory, key),
);
}
// ADD ROUTE
directory.routes.push(route);
};
/* ---------------------------------------------------------
FILE ITERATOR
--------------------------------------------------------- */
const iterate =
(project: INestiaProject) =>
(directory: SdkRouteDirectory) =>
async (outDir: string): Promise<void> => {
// CREATE A NEW DIRECTORY
try {
await fs.promises.mkdir(outDir);
} catch {}
// ITERATE CHILDREN
const statements: ts.Statement[] = [];
for (const [key, value] of directory.children) {
await iterate(project)(value)(`${outDir}/${key}`);
statements.push(
ts.factory.createExportDeclaration(
undefined,
false,
ts.factory.createNamespaceExport(ts.factory.createIdentifier(key)),
ts.factory.createStringLiteral(`./${key}`),
undefined,
),
);
}
if (statements.length && directory.routes.length)
statements.push(FilePrinter.enter());
// ITERATE ROUTES
const importer: ImportDictionary = new ImportDictionary(
`${outDir}/index.ts`,
);
directory.routes.forEach((route, i) => {
if (!(project.config.clone === true && route.protocol === "http"))
for (const tuple of route.imports)
for (const instance of tuple.instances)
importer.internal({
file: tuple.file,
instance,
type: true,
});
statements.push(
...(route.protocol === "http"
? SdkHttpRouteProgrammer.write(project)(importer)(route)
: SdkWebSocketRouteProgrammer.write(importer)(route)),
);
if (i !== directory.routes.length - 1)
statements.push(FilePrinter.enter());
});
// FINALIZE THE CONTENT
if (directory.routes.length !== 0)
statements.push(
...importer.toStatements(outDir),
...(!importer.empty() && statements.length
? [FilePrinter.enter()]
: []),
...statements.splice(0, statements.length),
);
await FilePrinter.write({
location: importer.file,
statements,
top:
"/**\n" +
" * @packageDocumentation\n" +
` * @module ${directory.module}\n` +
" * @nestia Generated by Nestia - https://github.com/samchon/nestia \n" +
" */\n" +
"//================================================================\n",
});
};
}