diff --git a/scripts/testCodeGen.ts b/scripts/testCodeGen.ts
index 85254fd2..4c60c037 100644
--- a/scripts/testCodeGen.ts
+++ b/scripts/testCodeGen.ts
@@ -3,39 +3,57 @@ import * as fs from "fs";
 import * as CodeGenerator from "../lib";
 
 const gen = (name: string, enableValidate = true): void => {
-  const params: CodeGenerator.Params = {
+  const params: CodeGenerator.OpenApiTsCodeGen.Configuration = {
     entryPoint: `test/${name}/index.yml`,
-    enableValidate,
-    log: {
-      validator: {
+    codeGenerator: {
+      templates: {
+        Default: CodeGenerator.DefaultCodeTemplate.makeApiClient,
+      },
+    },
+    typeDefinitionGenerator: {
+      additional: {
+        template: "Default",
+      },
+    },
+    validator: {
+      openapiSchema: enableValidate,
+      logger: {
         displayLogLines: 1,
       },
     },
   };
   fs.mkdirSync("test/code", { recursive: true });
-  const code = CodeGenerator.generateTypeScriptCode(params);
-  fs.writeFileSync(`test/code/${name}.ts`, code, { encoding: "utf-8" });
+  const output = CodeGenerator.make(params);
+  fs.writeFileSync(`test/code/${name}.ts`, output.typeDefinition.value, { encoding: "utf-8" });
   console.log(`Generate Code : test/code/${name}.ts`);
 };
 
 const genSyncMode = (name: string, enableValidate = true): void => {
-  const params: CodeGenerator.Params = {
+  const params: CodeGenerator.OpenApiTsCodeGen.Configuration = {
     entryPoint: `test/${name}/index.yml`,
-    enableValidate,
-    option: {
-      codeGenerator: {
-        sync: true,
+    codeGenerator: {
+      templates: {
+        Default: CodeGenerator.DefaultCodeTemplate.makeApiClient,
+      },
+    },
+    typeDefinitionGenerator: {
+      additional: {
+        template: "Default",
+        option: {
+          sync: true,
+        },
       },
     },
-    log: {
-      validator: {
+    validator: {
+      openapiSchema: enableValidate,
+      logger: {
         displayLogLines: 1,
       },
     },
   };
   fs.mkdirSync("test/code", { recursive: true });
-  const code = CodeGenerator.generateTypeScriptCode(params);
-  fs.writeFileSync(`test/code/sync-${name}.ts`, code, { encoding: "utf-8" });
+  const code = CodeGenerator.make(params);
+  fs.writeFileSync(`test/code/sync-${name}.ts`, code.typeDefinition.value, { encoding: "utf-8" });
   console.log(`Generate Code : test/code/sync-${name}.ts`);
 };
 
diff --git a/src/CodeGenerator/index.ts b/src/CodeGenerator/index.ts
index e1fda15c..04b3fa32 100644
--- a/src/CodeGenerator/index.ts
+++ b/src/CodeGenerator/index.ts
@@ -4,6 +4,8 @@ import { DevelopmentError } from "../Exception";
 import * as Factory from "./factory";
 import { CreateFunction, traverse } from "./traverse";
 
+export * as Utils from "./utils";
+
 export { CreateFunction, Factory };
 
 export type TransformerFactory<T extends ts.Node> = ts.TransformerFactory<T>;
diff --git a/src/CodeGenerator/utils.ts b/src/CodeGenerator/utils.ts
new file mode 100644
index 00000000..62dfbff0
--- /dev/null
+++ b/src/CodeGenerator/utils.ts
@@ -0,0 +1,17 @@
+import ts from "typescript";
+
+import type { CodeGenerator } from "../types";
+
+export const stringToStatements = (code: string): ts.Statement[] => {
+  const source = ts.createSourceFile("", code, ts.ScriptTarget.ESNext, false, ts.ScriptKind.TS);
+  return Array.from(source.statements);
+};
+
+export const convertIntermediateCodes = (intermediateCodes: CodeGenerator.IntermediateCode[]): ts.Statement[] => {
+  return intermediateCodes.reduce<ts.Statement[]>((result, intermediateCode) => {
+    if (typeof intermediateCode === "string") {
+      return [...result, ...stringToStatements(intermediateCode)];
+    }
+    return result.concat(intermediateCode);
+  }, []);
+};
diff --git a/src/Converter/CodeGenerator.ts b/src/Converter/CodeGenerator.ts
index 75123c6a..f8481aac 100644
--- a/src/Converter/CodeGenerator.ts
+++ b/src/Converter/CodeGenerator.ts
@@ -2,7 +2,8 @@ import ts from "typescript";
 
 import * as ConverterContext from "./ConverterContext";
 import { Store } from "./store";
-import { CodeGeneratorParams, OpenApi, PickedParameter } from "./types";
+import type { CodeGeneratorParams, OpenApi, PickedParameter } from "./types";
+import type { CodeGenerator } from "../types";
 
 const extractPickedParameter = (parameter: OpenApi.Parameter): PickedParameter => {
   return {
@@ -57,7 +58,7 @@ const hasQueryParameters = (parameters?: OpenApi.Parameter[]): boolean => {
   return parameters.filter(parameter => parameter.in === "query").length > 0;
 };
 
-const generateCodeGeneratorParamsList = (
+export const generateCodeGeneratorParamsList = (
   store: Store.Type,
   converterContext: ConverterContext.Types,
   allowOperationIds: string[] | undefined,
@@ -120,25 +121,3 @@ const generateCodeGeneratorParamsList = (
 
   return params;
 };
-
-export interface Option {
-  sync: boolean;
-}
-
-export type RewriteCodeAfterTypeDeclaration = (
-  context: ts.TransformationContext,
-  codeGeneratorParamsList: CodeGeneratorParams[],
-  codeGenerateOption: Option,
-) => ts.Statement[];
-
-export const generateApiClientCode = (
-  store: Store.Type,
-  context: ts.TransformationContext,
-  converterContext: ConverterContext.Types,
-  rewriteCodeAfterTypeDeclaration: RewriteCodeAfterTypeDeclaration,
-  allowOperationIds: string[] | undefined,
-  option: Option,
-): void => {
-  const codeGeneratorParamsList = generateCodeGeneratorParamsList(store, converterContext, allowOperationIds);
-  store.addAdditionalStatement(rewriteCodeAfterTypeDeclaration(context, codeGeneratorParamsList, option));
-};
diff --git a/src/Converter/InferredType.ts b/src/Converter/InferredType.ts
index 07570f88..052c7690 100644
--- a/src/Converter/InferredType.ts
+++ b/src/Converter/InferredType.ts
@@ -1,6 +1,6 @@
-import * as Types from "./types";
+import type { OpenApi } from "./types";
 
-export const getInferredType = (schema: Types.OpenApi.Schema): Types.OpenApi.Schema | undefined => {
+export const getInferredType = (schema: OpenApi.Schema): OpenApi.Schema | undefined => {
   if (schema.type || schema.oneOf || schema.allOf || schema.anyOf) {
     return schema;
   }
diff --git a/src/Converter/index.ts b/src/Converter/index.ts
index ce83a5a1..15372bd7 100644
--- a/src/Converter/index.ts
+++ b/src/Converter/index.ts
@@ -1,6 +1,7 @@
 import ts from "typescript";
 
 import * as TypeScriptCodeGenerator from "../CodeGenerator";
+import { CodeGenerator as CodeGenerator2 } from "../types";
 import * as CodeGenerator from "./CodeGenerator";
 import * as Comment from "./Comment";
 import * as Headers from "./components/Headers";
@@ -21,22 +22,18 @@ export { OpenApi, CodeGenerator, CodeGeneratorParams, PickedParameter, Name };
 export interface Type {
   generateLeadingComment: () => string;
   createFunction: TypeScriptCodeGenerator.CreateFunction;
-  codeGeneratorOption: CodeGenerator.Option;
+  codeGeneratorOption: CodeGenerator2.Option;
 }
 
 export interface Option {
-  /**
-   * It is possible to rewrite the implementation after the type declaration.
-   */
-  rewriteCodeAfterTypeDeclaration: CodeGenerator.RewriteCodeAfterTypeDeclaration;
-  /**
-   *
-   */
-  codeGeneratorOption: CodeGenerator.Option;
   /**
    * List of operationId to be used
    */
   allowOperationIds?: string[];
+
+  generateCodeAfterGeneratedTypeDefinition?: CodeGenerator2.GenerateFunction;
+
+  codeGeneratorOption: CodeGenerator2.Option;
 }
 
 export const create = (entryPoint: string, rootSchema: OpenApi.Document, noReferenceOpenApiSchema: OpenApi.Document, option: Option): Type => {
@@ -47,6 +44,7 @@ export const create = (entryPoint: string, rootSchema: OpenApi.Document, noRefer
     const factory = TypeScriptCodeGenerator.Factory.create(context);
     const store = Store.create(factory, noReferenceOpenApiSchema);
     const toTypeNodeContext = TypeNodeContext.create(entryPoint, store, factory, converterContext);
+    let extraStatements: ts.Statement[] = [];
 
     if (rootSchema.components) {
       if (rootSchema.components.schemas) {
@@ -106,16 +104,12 @@ export const create = (entryPoint: string, rootSchema: OpenApi.Document, noRefer
     }
     if (rootSchema.paths) {
       Paths.generateStatements(entryPoint, currentPoint, store, factory, rootSchema.paths, toTypeNodeContext, converterContext);
-      CodeGenerator.generateApiClientCode(
-        store,
-        context,
-        converterContext,
-        option.rewriteCodeAfterTypeDeclaration,
-        option.allowOperationIds,
-        option.codeGeneratorOption,
-      );
+
+      const codeGeneratorParamsList = CodeGenerator.generateCodeGeneratorParamsList(store, converterContext, option.allowOperationIds);
+      const extraStatements2 = option.generateCodeAfterGeneratedTypeDefinition?.(context, codeGeneratorParamsList, option.codeGeneratorOption) || [];
+      extraStatements = extraStatements.concat(TypeScriptCodeGenerator.Utils.convertIntermediateCodes(extraStatements2));
     }
-    return store.getRootStatements();
+    return store.getRootStatements().concat(extraStatements);
   };
 
   return {
diff --git a/src/Converter/types/index.ts b/src/Converter/types/index.ts
index ece0ca07..fdb5acac 100644
--- a/src/Converter/types/index.ts
+++ b/src/Converter/types/index.ts
@@ -1,5 +1,5 @@
-import { CodeGeneratorParams, PickedParameter } from "./CodeGeneratorParams";
-import * as OpenApi from "./OpenApiSchemaV3";
+import { CodeGeneratorParams, PickedParameter } from "../../types/extractSchema";
+import * as OpenApi from "../../types/OpenApi";
 
 export { OpenApi, CodeGeneratorParams, PickedParameter };
 
diff --git a/src/DefaultCodeTemplate/ApiClientClass/ApiClientInterface.ts b/src/DefaultCodeTemplate/ApiClientClass/ApiClientInterface.ts
index 236ddd26..21b9a6f1 100644
--- a/src/DefaultCodeTemplate/ApiClientClass/ApiClientInterface.ts
+++ b/src/DefaultCodeTemplate/ApiClientClass/ApiClientInterface.ts
@@ -1,7 +1,8 @@
 import ts from "typescript";
 
 import { Factory } from "../../CodeGenerator";
-import type { CodeGenerator, CodeGeneratorParams } from "../../Converter";
+import type { CodeGenerator } from "../../types";
+import type { CodeGeneratorParams } from "../../types/extractSchema";
 
 const httpMethodList: string[] = ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"];
 
diff --git a/src/DefaultCodeTemplate/ApiClientClass/Method.ts b/src/DefaultCodeTemplate/ApiClientClass/Method.ts
index 144d4242..03d319cf 100644
--- a/src/DefaultCodeTemplate/ApiClientClass/Method.ts
+++ b/src/DefaultCodeTemplate/ApiClientClass/Method.ts
@@ -1,7 +1,8 @@
 import ts from "typescript";
 
 import { Factory } from "../../CodeGenerator";
-import type { CodeGenerator, CodeGeneratorParams } from "../../Converter";
+import type { CodeGenerator } from "../../types";
+import type { CodeGeneratorParams } from "../../types/extractSchema";
 import * as MethodBody from "./MethodBody";
 
 export { MethodBody };
diff --git a/src/DefaultCodeTemplate/ApiClientClass/index.ts b/src/DefaultCodeTemplate/ApiClientClass/index.ts
index 892a76a2..9504f6f0 100644
--- a/src/DefaultCodeTemplate/ApiClientClass/index.ts
+++ b/src/DefaultCodeTemplate/ApiClientClass/index.ts
@@ -1,7 +1,8 @@
 import ts from "typescript";
 
 import { Factory } from "../../CodeGenerator";
-import type { CodeGenerator, CodeGeneratorParams } from "../../Converter";
+import type { CodeGenerator } from "../../types";
+import type { CodeGeneratorParams } from "../../types/extractSchema";
 import * as ApiClientInterface from "./ApiClientInterface";
 import * as Class from "./Class";
 import * as Constructor from "./Constructor";
diff --git a/src/DefaultCodeTemplate/index.ts b/src/DefaultCodeTemplate/index.ts
index 7201cd02..148826fb 100644
--- a/src/DefaultCodeTemplate/index.ts
+++ b/src/DefaultCodeTemplate/index.ts
@@ -1,14 +1,15 @@
 import ts from "typescript";
 
 import * as TypeScriptCodeGenerator from "../CodeGenerator";
-import type * as Converter from "../Converter";
+import type { CodeGenerator } from "../types";
+import type { CodeGeneratorParams } from "../types/extractSchema";
 import * as ApiClientArgument from "./ApiClientArgument";
 import * as ApiClientClass from "./ApiClientClass";
 
-export const rewriteCodeAfterTypeDeclaration: Converter.CodeGenerator.RewriteCodeAfterTypeDeclaration = (
+export const makeApiClient: CodeGenerator.GenerateFunction = (
   context: ts.TransformationContext,
-  codeGeneratorParamsList: Converter.CodeGeneratorParams[],
-  option: Converter.CodeGenerator.Option,
+  codeGeneratorParamsList: CodeGeneratorParams[],
+  option: CodeGenerator.Option,
 ): ts.Statement[] => {
   const statements: ts.Statement[] = [];
   const factory = TypeScriptCodeGenerator.Factory.create(context);
diff --git a/src/Validator/index.ts b/src/Validator/index.ts
index 4bda68b7..91efb504 100644
--- a/src/Validator/index.ts
+++ b/src/Validator/index.ts
@@ -6,18 +6,11 @@ import * as Ajv from "ajv";
 
 import type { OpenApi } from "../Converter/types";
 import openapiSchema from "./openapi.json";
+import type { Validator } from "../types";
 
-export interface LogOption {
-  /**
-   * default: undefined (all logs)
-   * Number of lines displayed in the latest log
-   */
-  displayLogLines?: number;
-}
-
-const showLogs = (logs: any[], option?: LogOption) => {
-  if (option && option.displayLogLines && option.displayLogLines > 0) {
-    const latestLogs = logs.slice(0, option.displayLogLines);
+const showLogs = (logs: any[], logger?: Validator.Logger) => {
+  if (logger && logger.displayLogLines && logger.displayLogLines > 0) {
+    const latestLogs = logs.slice(0, logger.displayLogLines);
     const moreLogNum = logs.length - latestLogs.length;
     console.error("Correct the validation error before generating the code.");
     console.error(`There are a total of ${logs.length} errors below.`);
@@ -37,12 +30,12 @@ const showLogs = (logs: any[], option?: LogOption) => {
   }
 };
 
-export const validate = (openapiDoc: OpenApi.Document, option?: LogOption): void => {
+export const validate = (openapiDoc: OpenApi.Document, logger?: Validator.Logger): void => {
   const ajv = new Ajv.default({ allErrors: true });
   const validate = ajv.compile(openapiSchema);
   validate(openapiDoc);
   if (validate.errors) {
-    showLogs(validate.errors, option);
+    showLogs(validate.errors, logger);
     throw new Error("Validation Error");
   }
 };
diff --git a/src/index.ts b/src/index.ts
index c5a744c2..592888e1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,67 +1,39 @@
 import { EOL } from "os";
 
-import * as TypeScriptCodeGenerator from "./CodeGenerator";
-import * as Converter from "./Converter";
-import * as DefaultCodeTemplate from "./DefaultCodeTemplate";
+import * as TsGenerator from "./CodeGenerator";
+import * as Transformer from "./Converter";
 import { fileSystem } from "./FileSystem";
 import * as ResolveReference from "./ResolveReference";
+import type { OpenApiTsCodeGen } from "./types";
 import * as Validator from "./Validator";
+import * as DefaultCodeTemplate from "./DefaultCodeTemplate";
 
-export { Converter };
+export { Transformer, OpenApiTsCodeGen, DefaultCodeTemplate };
 
-export interface Params {
-  entryPoint: string;
-  option?: {
-    rewriteCodeAfterTypeDeclaration?: Converter.CodeGenerator.RewriteCodeAfterTypeDeclaration;
-    codeGenerator?: {
-      /** default false */
-      sync?: boolean;
-    };
-  };
-  /** default: true */
-  enableValidate?: boolean;
-  log?: {
-    validator?: {
-      /**
-       * default: undefined (all logs)
-       * Number of lines displayed in the latest log
-       */
-      displayLogLines?: number;
-    };
-  };
-  filter?: {
-    allowOperationIds?: string[];
-  };
-}
+export const make = (config: OpenApiTsCodeGen.Configuration): OpenApiTsCodeGen.Output => {
+  const schema = fileSystem.loadJsonOrYaml(config.entryPoint);
+  const resolvedReferenceDocument = ResolveReference.resolve(config.entryPoint, config.entryPoint, JSON.parse(JSON.stringify(schema)));
 
-const generateConvertOption = (filter: Params["filter"] = {}, option?: Params["option"]): Converter.Option => {
-  if (option) {
-    return {
-      rewriteCodeAfterTypeDeclaration: option.rewriteCodeAfterTypeDeclaration || DefaultCodeTemplate.rewriteCodeAfterTypeDeclaration,
-      allowOperationIds: filter.allowOperationIds,
-      codeGeneratorOption: {
-        sync: option.codeGenerator ? !!option.codeGenerator.sync : false,
-      },
-    };
+  if (!config.validator) {
+    Validator.validate(resolvedReferenceDocument);
+  } else {
+    if (config.validator.openapiSchema) {
+      Validator.validate(resolvedReferenceDocument, config.validator.logger);
+    }
   }
-  return {
-    rewriteCodeAfterTypeDeclaration: DefaultCodeTemplate.rewriteCodeAfterTypeDeclaration,
-    allowOperationIds: filter.allowOperationIds,
-    codeGeneratorOption: {
-      sync: false,
-    },
-  };
-};
 
-export const generateTypeScriptCode = ({ entryPoint, option, enableValidate = true, log, filter = {} }: Params): string => {
-  const schema = fileSystem.loadJsonOrYaml(entryPoint);
-  const resolvedReferenceDocument = ResolveReference.resolve(entryPoint, entryPoint, JSON.parse(JSON.stringify(schema)));
+  const templateName = config.typeDefinitionGenerator?.additional?.template;
 
-  if (enableValidate) {
-    Validator.validate(resolvedReferenceDocument, log && log.validator);
-  }
+  const { createFunction, generateLeadingComment } = Transformer.create(config.entryPoint, schema, resolvedReferenceDocument, {
+    allowOperationIds: config.openApiSchemaParser?.allowOperationIds,
+    codeGeneratorOption: config.typeDefinitionGenerator?.additional?.option || {},
+    generateCodeAfterGeneratedTypeDefinition: templateName ? config.codeGenerator?.templates?.[templateName] : undefined
+  });
 
-  const convertOption = generateConvertOption(filter, option);
-  const { createFunction, generateLeadingComment } = Converter.create(entryPoint, schema, resolvedReferenceDocument, convertOption);
-  return [generateLeadingComment(), TypeScriptCodeGenerator.generate(createFunction)].join(EOL + EOL + EOL);
+  return {
+    typeDefinition: {
+      value: [generateLeadingComment(), TsGenerator.generate(createFunction)].join(EOL + EOL + EOL),
+    },
+    additionalCodes: {},
+  };
 };
diff --git a/src/Converter/types/OpenApiSchemaV3.ts b/src/types/OpenApi.ts
similarity index 100%
rename from src/Converter/types/OpenApiSchemaV3.ts
rename to src/types/OpenApi.ts
diff --git a/src/Converter/types/CodeGeneratorParams.ts b/src/types/extractSchema.ts
similarity index 97%
rename from src/Converter/types/CodeGeneratorParams.ts
rename to src/types/extractSchema.ts
index 09b68dba..59acf585 100644
--- a/src/Converter/types/CodeGeneratorParams.ts
+++ b/src/types/extractSchema.ts
@@ -1,4 +1,4 @@
-import * as OpenApi from "./OpenApiSchemaV3";
+import type * as OpenApi from "./OpenApi";
 
 export type PickedParameter = Pick<OpenApi.Parameter, "name" | "in" | "required" | "style" | "explode">;
 
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 00000000..cbc0489b
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,90 @@
+import type ts from "typescript";
+
+import type { CodeGeneratorParams } from "./extractSchema";
+
+export namespace Validator {
+  export interface Logger {
+    /**
+     * default: undefined (all logs)
+     * Number of lines displayed in the latest log
+     */
+    displayLogLines?: number;
+  }
+  export interface Configuration {
+    openapiSchema?: boolean;
+    logger?: Logger;
+  }
+}
+
+export namespace OpenApiSchemaParser {
+  export interface Configuration {
+    allowOperationIds?: string[];
+  }
+}
+
+export namespace CodeGenerator {
+  /**
+   * The parameters specified here will be passed directly to the Code Generate function.
+   */
+  export interface Option {
+    sync?: boolean;
+  }
+
+  /**
+   * Used to further transform the code created by the specified Generator Template.
+   */
+  export type IntermediateCode = string | ts.Statement;
+
+  export type GenerateFunction = (context: ts.TransformationContext, payload: CodeGeneratorParams[], option: Option) => IntermediateCode[];
+
+  export interface OutputConfiguration {
+    /**
+     * Template Name
+     */
+    template: string;
+    /**
+     * Code generatorOption
+     */
+    option?: Option;
+    /**
+     *
+     */
+    transform?: (params: IntermediateCode) => IntermediateCode[];
+  }
+
+  export interface Configuration {
+    /**
+     * Output files
+     */
+    outputs?: Record<string, OutputConfiguration>;
+    /**
+     * Register template
+     */
+    templates?: Record<string, GenerateFunction>;
+  }
+}
+
+export namespace TypeDefinitionGenerator {
+  export interface Configuration {
+    additional?: CodeGenerator.OutputConfiguration;
+  }
+}
+
+export namespace OpenApiTsCodeGen {
+  export interface Configuration {
+    entryPoint: string;
+    typeDefinitionGenerator?: TypeDefinitionGenerator.Configuration;
+    validator?: Validator.Configuration;
+    openApiSchemaParser?: OpenApiSchemaParser.Configuration;
+    codeGenerator?: CodeGenerator.Configuration;
+  }
+
+  export interface GeneratedCode {
+    value: string;
+  }
+
+  export interface Output {
+    typeDefinition: GeneratedCode;
+    additionalCodes: Record<string, GeneratedCode>;
+  }
+}
diff --git a/tsconfig.json b/tsconfig.json
index 2927f0f8..64fdcb81 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,13 +5,13 @@
     "esModuleInterop": true,
     "forceConsistentCasingInFileNames": true,
     "jsx": "react",
-    "module": "esnext",
+    "module": "commonjs",
     "moduleResolution": "node",
     "noFallthroughCasesInSwitch": true,
     "noUnusedParameters": false,
     "skipLibCheck": true,
     "sourceMap": true,
-    "target": "esnext",
+    "target": "es2019",
     "lib": ["dom", "es2019"],
     "rootDir": ".",
     "outDir": "lib",