Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion packages/migrate/src/NestiaMigrateApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,41 @@ import { INestiaMigrateConfig } from "./structures/INestiaMigrateConfig";
import { INestiaMigrateContext } from "./structures/INestiaMigrateContext";
import { INestiaMigrateFile } from "./structures/INestiaMigrateFile";

/**
* Main application class for migrating Swagger/OpenAPI documents to NestJS applications or SDK libraries.
*
* The NestiaMigrateApplication class provides functionality to parse OpenAPI specifications
* and generate corresponding NestJS controllers, DTOs, API clients, and test files.
* It supports both NestJS backend generation and SDK library generation modes.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export class NestiaMigrateApplication {
private readonly data_: IHttpMigrateApplication;

/* -----------------------------------------------------------
CONSTRUCTORS
----------------------------------------------------------- */

/**
* Creates a new NestiaMigrateApplication instance from an OpenAPI document.
*
* @param document - The OpenAPI document to migrate from
*/
public constructor(public readonly document: OpenApi.IDocument) {
this.data_ = HttpMigration.application(document);
}

/**
* Creates a new NestiaMigrateApplication instance with assertion validation.
*
* Validates the input document using typia assertion and converts it to the
* standardized OpenAPI format before creating the application instance.
*
* @param document - The OpenAPI/Swagger document to migrate from
* @returns A new NestiaMigrateApplication instance
* @throws Will throw an error if the document validation fails
*/
public static assert(
document:
| SwaggerV2.IDocument
Expand All @@ -40,6 +65,16 @@ export class NestiaMigrateApplication {
);
}

/**
* Creates a new NestiaMigrateApplication instance with validation.
*
* Validates the input document using typia validation and converts it to the
* standardized OpenAPI format before creating the application instance.
* Returns a validation result that indicates success or failure.
*
* @param document - The OpenAPI/Swagger document to migrate from
* @returns Validation result containing either the application instance or error details
*/
public static validate(
document:
| SwaggerV2.IDocument
Expand All @@ -63,15 +98,35 @@ export class NestiaMigrateApplication {
/* -----------------------------------------------------------
ACCESSORS
----------------------------------------------------------- */

/**
* Gets the internal HTTP migration application data.
*
* @returns The parsed HTTP migration application structure
*/
public getData(): IHttpMigrateApplication {
return this.data_;
}

/** @deprecated */
/**
* Gets migration errors that occurred during document parsing.
*
* @deprecated Use getData().errors instead
* @returns Array of migration errors
*/
public getErrors(): IHttpMigrateApplication.IError[] {
return this.data_.errors;
}

/**
* Generates NestJS application files from the OpenAPI document.
*
* Creates a complete NestJS application including controllers, DTOs, services,
* and optionally test files based on the provided configuration.
*
* @param config - Configuration options for the NestJS generation
* @returns Record of file paths to file contents for the generated NestJS application
*/
public nest(config: INestiaMigrateConfig): Record<string, string> {
const context: INestiaMigrateContext = createContext(
"nest",
Expand Down Expand Up @@ -103,6 +158,15 @@ export class NestiaMigrateApplication {
return config.package ? renameSlug(config.package, files) : files;
}

/**
* Generates SDK library files from the OpenAPI document.
*
* Creates a TypeScript SDK library with API client functions, type definitions,
* and optionally test files based on the provided configuration.
*
* @param config - Configuration options for the SDK generation
* @returns Record of file paths to file contents for the generated SDK library
*/
public sdk(config: INestiaMigrateConfig): Record<string, string> {
const context: INestiaMigrateContext = createContext(
"sdk",
Expand All @@ -126,14 +190,38 @@ export class NestiaMigrateApplication {
return config.package ? renameSlug(config.package, files) : files;
}
}

/**
* Namespace containing types and interfaces related to the NestiaMigrateApplication.
*
* @deprecated This namespace may be removed in future versions
*/
export namespace MigrateApplication {
/**
* Output structure for migration operations.
*
* @deprecated Use the return types of nest() and sdk() methods directly
*/
export interface IOutput {
/** Migration context used for the operation */
context: INestiaMigrateContext;
/** Generated files from the migration */
files: INestiaMigrateFile[];
/** Errors that occurred during migration */
errors: IHttpMigrateApplication.IError[];
}
}

/**
* Creates a migration context for internal use.
*
* @param mode - The generation mode (nest or sdk)
* @param application - The HTTP migration application data
* @param config - The migration configuration
* @returns A new migration context
* @internal
*/

const createContext = (
mode: "nest" | "sdk",
application: IHttpMigrateApplication,
Expand All @@ -146,6 +234,14 @@ const createContext = (
};
};

/**
* Renames package placeholders in generated files with the specified package name.
*
* @param slug - The package name to use as replacement
* @param files - Record of file paths to file contents
* @returns Updated files with package placeholders replaced
* @internal
*/
const renameSlug = (
slug: string,
files: Record<string, string>,
Expand Down
30 changes: 30 additions & 0 deletions packages/migrate/src/analyzers/NestiaMigrateControllerAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@ import { INestiaMigrateController } from "../structures/INestiaMigrateController
import { MapUtil } from "../utils/MapUtil";
import { StringUtil } from "../utils/StringUtil";

/**
* Namespace containing functions for analyzing and organizing routes into controllers.
*
* This analyzer processes HTTP routes from OpenAPI specifications and groups them
* into logical NestJS controller structures based on their paths and operations.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace NestiaMigrateControllerAnalyzer {
/**
* Analyzes HTTP routes and groups them into controller structures.
*
* Takes an array of HTTP routes and organizes them into logical controller
* groupings based on their access patterns, paths, and custom controller
* annotations. Each controller gets a name, base path, file location, and
* collection of associated routes.
*
* @param routes - Array of HTTP routes to analyze and group
* @returns Array of controller structures with organized routes
*/
export const analyze = (
routes: IHttpMigrateRoute[],
): INestiaMigrateController[] => {
Expand Down Expand Up @@ -44,6 +63,17 @@ export namespace NestiaMigrateControllerAnalyzer {
};
}

/**
* Finds the index where two string arrays start to differ.
*
* Compares two string arrays element by element and returns the index
* of the first differing element. Used for finding common path prefixes.
*
* @param x - First string array
* @param y - Second string array
* @returns Index where arrays differ, or the length of the shorter array
* @internal
*/
const getSplitIndex = (x: string[], y: string[]) => {
const n: number = Math.min(x.length, y.length);
for (let i: number = 0; i < n; ++i) if (x[i] !== y[i]) return i;
Expand Down
21 changes: 21 additions & 0 deletions packages/migrate/src/archivers/NestiaMigrateFileArchiver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
import { VariadicSingleton } from "tstl";

/**
* Namespace containing functions for archiving generated files to the file system.
*
* This archiver handles the creation of directory structures and writing of
* generated files to disk with proper organization and error handling.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace NestiaMigrateFileArchiver {
/**
* Archives generated files to the file system.
*
* Creates the necessary directory structure and writes all generated files
* to their appropriate locations. Uses efficient directory creation with
* memoization to avoid redundant filesystem operations.
*
* @param props - Configuration object for the archiving operation
* @param props.mkdir - Function to create directories
* @param props.writeFile - Function to write file content
* @param props.root - Root directory path for the output
* @param props.files - Record of file paths to file contents to write
*/
export const archive = async (props: {
mkdir: (path: string) => Promise<void>;
writeFile: (path: string, content: string) => Promise<void>;
Expand Down
24 changes: 24 additions & 0 deletions packages/migrate/src/executable/NestiaMigrateCommander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,31 @@ import { NestiaMigrateApplication } from "../NestiaMigrateApplication";
import { NestiaMigrateFileArchiver } from "../archivers/NestiaMigrateFileArchiver";
import { NestiaMigrateInquirer } from "./NestiaMigrateInquirer";

/**
* Namespace containing the main command-line interface logic for Nestia migration.
*
* This commander handles the complete migration workflow including:
* - Parsing command-line arguments and user input
* - Validating input files and output directories
* - Reading and parsing OpenAPI/Swagger documents
* - Generating NestJS or SDK code
* - Formatting and writing output files
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace NestiaMigrateCommander {
/**
* Main entry point for the command-line migration tool.
*
* Orchestrates the complete migration process from start to finish:
* 1. Parses user input and options
* 2. Validates input files and output directories
* 3. Reads and parses the OpenAPI/Swagger document
* 4. Generates the target code (NestJS or SDK)
* 5. Formats and writes all output files
*
* @throws Will terminate the process with error code -1 on any validation or processing errors
*/
export const main = async (): Promise<void> => {
const resolve = (str: string | undefined) =>
str ? path.resolve(str).split("\\").join("/") : undefined;
Expand Down
9 changes: 9 additions & 0 deletions packages/migrate/src/executable/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
#!/usr/bin/env node

/**
* @fileoverview Command-line entry point for the @nestia/migrate package.
*
* This script serves as the main executable for the Nestia migration tool.
* It handles command-line arguments and orchestrates the migration process
* from OpenAPI/Swagger documents to NestJS applications or SDK libraries.
*/

import { NestiaMigrateCommander } from "./NestiaMigrateCommander";

NestiaMigrateCommander.main().catch((exp) => {
Expand Down
54 changes: 54 additions & 0 deletions packages/migrate/src/factories/TypeLiteralFactory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import ts from "typescript";
import { Escaper } from "typia/lib/utils/Escaper";

/**
* Namespace containing functions for generating TypeScript type literal nodes.
*
* This factory creates TypeScript AST nodes representing literal types from
* JavaScript values, useful for generating type-safe constants and literal
* type definitions in generated code.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace TypeLiteralFactory {
/**
* Generates a TypeScript type node from a JavaScript value.
*
* Converts primitive values, objects, and arrays into their corresponding
* TypeScript literal type representations. Handles nested structures
* recursively to create complex type definitions.
*
* @param value - The JavaScript value to convert to a type node
* @returns TypeScript type node representing the literal type
*/
export const generate = (value: any): ts.TypeNode =>
typeof value === "boolean"
? generateBoolean(value)
Expand All @@ -17,9 +36,21 @@ export namespace TypeLiteralFactory {
: generateObject(value)
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword);

/**
* Generates a string literal type node.
* @param str - The string value
* @returns TypeScript string literal type node
* @internal
*/
const generatestring = (str: string) =>
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(str));

/**
* Generates a number literal type node.
* @param num - The number value
* @returns TypeScript number literal type node
* @internal
*/
const generateNumber = (num: number) =>
ts.factory.createLiteralTypeNode(
num < 0
Expand All @@ -30,17 +61,40 @@ export namespace TypeLiteralFactory {
: ts.factory.createNumericLiteral(num),
);

/**
* Generates a boolean literal type node.
* @param bool - The boolean value
* @returns TypeScript boolean literal type node
* @internal
*/
const generateBoolean = (bool: boolean) =>
ts.factory.createLiteralTypeNode(
bool ? ts.factory.createTrue() : ts.factory.createFalse(),
);

/**
* Generates a null literal type node.
* @returns TypeScript null literal type node
* @internal
*/
const generateNull = () =>
ts.factory.createLiteralTypeNode(ts.factory.createNull());

/**
* Generates a tuple type node from an array.
* @param items - Array of values to convert to tuple elements
* @returns TypeScript tuple type node
* @internal
*/
const generateTuple = (items: any[]) =>
ts.factory.createTupleTypeNode(items.map(generate));

/**
* Generates an object literal type node.
* @param obj - Object to convert to type literal
* @returns TypeScript object literal type node
* @internal
*/
const generateObject = (obj: object) =>
ts.factory.createTypeLiteralNode(
Object.entries(obj).map(([key, value]) =>
Expand Down
8 changes: 8 additions & 0 deletions packages/migrate/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* @fileoverview Main entry point for the @nestia/migrate package.
*
* This package provides functionality to migrate from Swagger/OpenAPI documents
* to NestJS applications or SDK libraries. It analyzes OpenAPI specifications
* and generates corresponding NestJS controllers, DTOs, and API clients.
*/

import * as migrate from "./module";

export default migrate;
Expand Down
6 changes: 6 additions & 0 deletions packages/migrate/src/module.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
/**
* @fileoverview Core module exports for the @nestia/migrate package.
*
* Exports the main NestiaMigrateApplication class and core migration context interface.
*/

export * from "./NestiaMigrateApplication";
export * from "./structures/INestiaMigrateContext";
Loading