Skip to content

Commit

Permalink
Merge pull request #806 from samchon/features/migrate
Browse files Browse the repository at this point in the history
Special case handling of `@nestia/migrate`.
  • Loading branch information
samchon authored Feb 22, 2024
2 parents 83bda5f + 60dcf12 commit 774ba32
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 51 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
name: build
on: [push, pull_request]
on:
push:
paths:
- 'src/**'
- 'test/**'
pull_request:
paths:
- 'src/**'
- 'test/**'

jobs:
Ubuntu:
Expand Down
4 changes: 2 additions & 2 deletions packages/migrate/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/migrate",
"version": "0.8.2",
"version": "0.9.0",
"description": "Migration program from swagger to NestJS",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -60,7 +60,7 @@
"prettier": "^3.2.5",
"tstl": "^2.5.13",
"typescript": "^5.3.3",
"typia": "^5.4.9"
"typia": "^5.4.11"
},
"files": [
"lib",
Expand Down
15 changes: 11 additions & 4 deletions packages/migrate/src/MigrateApplication.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import typia from "typia";
import typia, { IValidation } from "typia";

import { MigrateAnalyzer } from "./analyzers/MigrateAnalyzer";
import { NEST_TEMPLATE } from "./bundles/NEST_TEMPLATE";
Expand All @@ -12,10 +12,17 @@ import { IMigrateProgram } from "./structures/IMigrateProgram";
import { ISwagger } from "./structures/ISwagger";

export class MigrateApplication {
public readonly swagger: ISwagger;
private constructor(public readonly swagger: ISwagger) {}

public constructor(swagger: ISwagger) {
this.swagger = typia.assert(swagger);
public static create(swagger: ISwagger): IValidation<MigrateApplication> {
const result = typia.validate<ISwagger>(swagger);
if (result.success)
return {
success: true,
data: new MigrateApplication(swagger),
errors: [],
};
return result;
}

public nest(config: MigrateApplication.IConfig): MigrateApplication.IOutput {
Expand Down
33 changes: 15 additions & 18 deletions packages/migrate/src/analyzers/MigrateMethodAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ export namespace MigrateMethodAnalzyer {
failures.push(
`does not support ${endpoint.method.toUpperCase()} method.`,
);
if (failures.length) {
console.log(
`Failed to migrate ${endpoint.method.toUpperCase()} ${endpoint.path}`,
...failures.map((f) => ` - ${f}`),
);
return null;
}

const [headers, query] = ["header", "query"].map((type) => {
const parameters = (route.parameters ?? []).filter(
Expand Down Expand Up @@ -70,12 +63,12 @@ export namespace MigrateMethodAnalzyer {
SwaggerSwaggerChecker.isArray(p.schema),
);
if (objects.length === 1 && primitives.length === 0) return objects[0];
else if (objects.length > 1)
throw new Error(
`Error on nestia.migrate.RouteProgrammer.analze(): ${type} typed parameters must be only one object type - ${StringUtil.capitalize(
endpoint.method,
)} "${endpoint.path}".`,
else if (objects.length > 1) {
failures.push(
`${type} typed parameters must be only one object type`,
);
return false;
}

const dto: ISwaggerSchema.IObject | null = objects[0]
? SwaggerSwaggerChecker.isObject(objects[0])
Expand Down Expand Up @@ -156,11 +149,15 @@ export namespace MigrateMethodAnalzyer {
if (
parameterNames.length !==
(route.parameters ?? []).filter((p) => p.in === "path").length
) {
)
failures.push(
"number of path parameters are not matched with its full path.",
);

if (failures.length) {
console.log(
`Failed to migrate ${endpoint.method.toUpperCase()} ${
endpoint.path
}: number of path parameters are not matched with its full path.`,
`Failed to migrate ${endpoint.method.toUpperCase()} ${endpoint.path}`,
...failures.map((f) => ` - ${f}`),
);
return null;
}
Expand Down Expand Up @@ -201,8 +198,8 @@ export namespace MigrateMethodAnalzyer {
schema: query,
}
: null,
body: body as IMigrateRoute.IBody,
success: success as IMigrateRoute.IBody,
body: body as IMigrateRoute.IBody | null,
success: success as IMigrateRoute.IBody | null,
exceptions: Object.fromEntries(
Object.entries(route.responses ?? {})
.filter(
Expand Down
12 changes: 11 additions & 1 deletion packages/migrate/src/internal/MigrateCommander.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs";
import path from "path";
import { format } from "prettier";
import { IValidation } from "typia";

import { MigrateApplication } from "../MigrateApplication";
import { MigrateFileArchiver } from "../archivers/MigrateFileArchiver";
Expand Down Expand Up @@ -33,7 +34,16 @@ export namespace MigrateCommander {
return swagger;
})();

const app: MigrateApplication = new MigrateApplication(swagger);
const result: IValidation<MigrateApplication> =
MigrateApplication.create(swagger);
if (result.success === false) {
console.log(result.errors);
throw new Error(
`Invalid swagger file (must follow the OpenAPI 3.0 spec).`,
);
}

const app: MigrateApplication = result.data;
const { files } =
options.mode === "nest" ? app.nest(options) : app.sdk(options);
await MigrateFileArchiver.archive({
Expand Down
12 changes: 9 additions & 3 deletions packages/migrate/src/programmers/MigrateSchemaProgrammer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { TypeFactory } from "typia/lib/factories/TypeFactory";
import { FormatCheatSheet } from "typia/lib/tags/internal/FormatCheatSheet";
import { Escaper } from "typia/lib/utils/Escaper";

import { ISwaggerSchema } from "../structures/ISwaggerSchema";
import { ISwaggerComponents } from "../structures/ISwaggerComponents";
import { ISwaggerSchema } from "../structures/ISwaggerSchema";
import { FilePrinter } from "../utils/FilePrinter";
import { SwaggerSwaggerChecker } from "../utils/SwaggerTypeChecker";
import { MigrateImportProgrammer } from "./MigrateImportProgrammer";
Expand Down Expand Up @@ -232,8 +232,14 @@ export namespace MigrateSchemaProgrammer {

const writeReference =
(importer: MigrateImportProgrammer) =>
(schema: ISwaggerSchema.IReference): ts.TypeReferenceNode =>
importer.dto(schema.$ref.split("/").at(-1)!);
(
schema: ISwaggerSchema.IReference,
): ts.TypeReferenceNode | ts.KeywordTypeNode => {
const name: string = schema.$ref.split("/").at(-1)!;
return name === ""
? TypeFactory.keyword("any")
: importer.dto(schema.$ref.split("/").at(-1)!);
};

/* -----------------------------------------------------------
UNIONS
Expand Down
10 changes: 9 additions & 1 deletion packages/migrate/src/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import cp from "child_process";
import fs from "fs";
import { format } from "prettier";
import { IValidation } from "typia";

import { MigrateApplication } from "../MigrateApplication";
import { MigrateFileArchiver } from "../archivers/MigrateFileArchiver";
Expand Down Expand Up @@ -36,7 +37,14 @@ const execute =
measure(`${project}-${config.mode}-${config.simulate}-${config.e2e}`)(
async () => {
const directory = `${OUTPUT}/${project}-${config.mode}-${config.simulate}-${config.e2e}`;
const app: MigrateApplication = new MigrateApplication(swagger);
const result: IValidation<MigrateApplication> =
MigrateApplication.create(swagger);
if (result.success === false)
throw new Error(
`Invalid swagger file (must follow the OpenAPI 3.0 spec).`,
);

const app: MigrateApplication = result.data;
const { files } =
config.mode === "nest" ? app.nest(config) : app.sdk(config);

Expand Down
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@mui/icons-material": "5.15.6",
"@mui/material": "5.15.6",
"@mui/system": "5.15.6",
"@nestia/migrate": "^0.8.2",
"@nestia/migrate": "^0.9.0",
"@stackblitz/sdk": "^1.9.0",
"next": "14.1.0",
"nextra": "latest",
Expand Down
52 changes: 32 additions & 20 deletions website/src/movies/editor/EditorMovie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,47 @@ import prettierEsTreePlugin from "prettier/plugins/estree";
import prettierTsPlugin from "prettier/plugins/typescript";
import { format } from "prettier/standalone";
import { useState } from "react";
import { IValidation } from "typia";

import EditorUploader from "../../components/editor/EditorUploader";

const createFiles = async (
swagger: ISwagger,
config: MigrateApplication.IConfig,
): Promise<null | IMigrateFile[]> => {
try {
const app: MigrateApplication = new MigrateApplication(swagger);
const { files }: MigrateApplication.IOutput = app.sdk(config);
for (const f of files)
if (f.file.substring(f.file.length - 3) === ".ts")
f.content = await format(f.content, {
parser: "typescript",
plugins: [prettierEsTreePlugin, prettierTsPlugin],
});
return files;
} catch {
return null;
}
};

const EditorMovie = () => {
const [swagger, setSwagger] = useState<ISwagger | null>(null);
const [error, setError] = useState<string | null>(null);
const [simulate, setSimulate] = useState(true);
const [e2e, setE2e] = useState(true);
const [progress, setProgress] = useState(false);

const createFiles = async (
swagger: ISwagger,
config: MigrateApplication.IConfig,
): Promise<null | IMigrateFile[]> => {
try {
const result: IValidation<MigrateApplication> =
MigrateApplication.create(swagger);
if (result.success === false) {
alert(
"Invalid swagger file (must follow OpenAPI 3.0 spec).\n\n" +
JSON.stringify(result.errors, null, 2),
);
return null;
}

const app: MigrateApplication = result.data;
const { files }: MigrateApplication.IOutput = app.sdk(config);
for (const f of files)
if (f.file.substring(f.file.length - 3) === ".ts")
f.content = await format(f.content, {
parser: "typescript",
plugins: [prettierEsTreePlugin, prettierTsPlugin],
});
return files;
} catch (exp) {
alert(exp instanceof Error ? exp.message : "unkown error");
return null;
}
};

const handleSwagger = (swagger: ISwagger | null, error: string | null) => {
setSwagger(swagger);
setError(error);
Expand All @@ -56,7 +68,7 @@ const EditorMovie = () => {
});
if (files === null) {
setProgress(false);
return alert("Invalid swagger file (must follow OpenAPI 3.0 spec).");
return;
}

sdk.openProject(
Expand Down

0 comments on commit 774ba32

Please sign in to comment.