Skip to content

Commit 5ce24d3

Browse files
authored
feat: provide a convenient experimental API for code extension (#35)
* refactor: change interface name * feat: add additional comment option * test: udpate option * feat: providing experimental APIs * test: add generator params test
1 parent 1c8dc40 commit 5ce24d3

30 files changed

+466
-64
lines changed

scripts/build.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import "./clean";
22

3+
import { cherryPick } from "./tools/cherry-pick";
34
import { copyPackageSet } from "./tools/copyPackageSet";
45
import { generateExportsField } from "./tools/dualPackageSupport";
56
import { shell } from "./tools/shell";
6-
import { cherryPick } from "./tools/cherry-pick";
77

88
const main = async () => {
99
await Promise.all([

scripts/testCodeGen.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as fs from "fs";
22
import { posix as path } from "path";
33

4-
import { CodeGenerator, GeneratorTemplate } from "../lib";
4+
import { CodeGenerator, CustomCodeGenerator } from "../lib";
55
import * as Templates from "../lib/templates";
66

77
const writeText = (filename: string, text: string): void => {
@@ -34,7 +34,7 @@ const generateTemplateCodeOnly = (
3434
});
3535
}
3636

37-
const apiClientGeneratorTemplate: GeneratorTemplate<Templates.ApiClient.Option> = {
37+
const apiClientGeneratorTemplate: CustomCodeGenerator<Templates.ApiClient.Option> = {
3838
generator: Templates.ApiClient.generator,
3939
option: option,
4040
};
@@ -58,11 +58,7 @@ const generateTypedefWithTemplateCode = (
5858
}
5959

6060
const code = codeGenerator.generateTypeDefinition([
61-
{
62-
generator: () => {
63-
return codeGenerator.getAdditionalTypeStatements();
64-
},
65-
},
61+
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
6662
{
6763
generator: Templates.ApiClient.generator,
6864
option: option,
@@ -75,9 +71,9 @@ const generateTypedefWithTemplateCode = (
7571
const generateSplitCode = (inputFilename: string, outputDir: string) => {
7672
const codeGenerator = new CodeGenerator(inputFilename);
7773

78-
const apiClientGeneratorTemplate: GeneratorTemplate<Templates.ApiClient.Option> = {
74+
const apiClientGeneratorTemplate: CustomCodeGenerator<Templates.ApiClient.Option> = {
7975
generator: Templates.ApiClient.generator,
80-
option: { sync: false },
76+
option: { sync: false, additionalMethodComment: true },
8177
};
8278

8379
const typeDefCode = codeGenerator.generateTypeDefinition();
@@ -87,18 +83,19 @@ const generateSplitCode = (inputFilename: string, outputDir: string) => {
8783
return [`import { Schemas } from "./types";`];
8884
},
8985
},
90-
{
91-
generator: () => {
92-
return codeGenerator.getAdditionalTypeStatements();
93-
},
94-
},
86+
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
9587
apiClientGeneratorTemplate,
9688
]);
9789

9890
writeText(path.join(outputDir, "types.ts"), typeDefCode);
9991
writeText(path.join(outputDir, "apiClient.ts"), apiClientCode);
10092
};
10193

94+
const generateParameter = (inputFilename: string, outputFilename: string) => {
95+
const codeGenerator = new CodeGenerator(inputFilename);
96+
writeText(outputFilename, JSON.stringify(codeGenerator.getCodeGeneratorParamsArray(), null, 2));
97+
};
98+
10299
const main = () => {
103100
generateTypedefCodeOnly("test/api.test.domain/index.yml", "test/code/typedef-only/api.test.domain.ts", true);
104101
generateTypedefCodeOnly("test/infer.domain/index.yml", "test/code/typedef-only/infer.domain.ts", false);
@@ -116,6 +113,9 @@ const main = () => {
116113
generateTypedefWithTemplateCode("test/infer.domain/index.yml", "test/code/typedef-with-template/infer.domain.ts", false, { sync: false });
117114

118115
generateSplitCode("test/api.test.domain/index.yml", "test/code/split");
116+
117+
generateParameter("test/api.test.domain/index.yml", "test/code/parameter/api.test.domain.json");
118+
generateParameter("test/infer.domain/index.yml", "test/code/parameter/infer.domain.json");
119119
};
120120

121121
main();

src/api.ts

-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ export * as OpenApiTools from "./internal/OpenApiTools";
33
export { FileSystem } from "./internal/FileSystem";
44
export * as ResolveReference from "./internal/ResolveReference";
55
export * as Validator from "./internal/Validator";
6-

src/code-templates/api-client/ApiClientClass/ApiClientInterface.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ts from "typescript";
22

33
import type { TsGenerator } from "../../../api";
44
import type { CodeGenerator } from "../../../types";
5+
import type { Option } from "../types";
56

67
const httpMethodList: string[] = ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"];
78

@@ -104,7 +105,7 @@ const createObjectLikeInterface = (factory: TsGenerator.Factory.Type) => {
104105
});
105106
};
106107

107-
export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Params[], option: { sync?: boolean }): ts.Statement[] => {
108+
export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Params[], option: Option): ts.Statement[] => {
108109
const objectLikeOrAnyType = factory.UnionTypeNode.create({
109110
typeNodes: [
110111
factory.TypeReferenceNode.create({

src/code-templates/api-client/ApiClientClass/Method.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { EOL } from "os";
2+
13
import ts from "typescript";
24

35
import type { TsGenerator } from "../../../api";
46
import type { CodeGenerator } from "../../../types";
7+
import type { Option } from "../types";
58
import * as MethodBody from "./MethodBody";
69

710
export { MethodBody };
@@ -36,7 +39,7 @@ const generateResponseReturnType = (
3639
factory: TsGenerator.Factory.Type,
3740
successResponseNameList: string[],
3841
successResponseContentTypeList: string[],
39-
option: { sync?: boolean },
42+
option: Option,
4043
) => {
4144
let objectType: ts.TypeNode = factory.TypeNode.create({
4245
type: "void",
@@ -121,7 +124,7 @@ const methodTypeParameters = (factory: TsGenerator.Factory.Type, params: CodeGen
121124
*
122125
* }
123126
*/
124-
export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.Params, option: { sync?: boolean }): ts.MethodDeclaration => {
127+
export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.Params, option: Option): ts.MethodDeclaration => {
125128
const typeParameters: ts.TypeParameterDeclaration[] = methodTypeParameters(factory, params);
126129
const methodArguments: ts.ParameterDeclaration[] = [];
127130
const hasParamsArguments =
@@ -148,7 +151,9 @@ export const create = (factory: TsGenerator.Factory.Type, params: CodeGenerator.
148151
name: params.functionName,
149152
async: !option.sync,
150153
parameters: methodArguments,
151-
comment: params.comment,
154+
comment: option.additionalMethodComment
155+
? [params.comment, `operationId: ${params.operationId}`, `Request URI: ${params.rawRequestUri}`].filter(t => !!t).join(EOL)
156+
: params.comment,
152157
deprecated: params.deprecated,
153158
type: returnType,
154159
typeParameters: typeParameters,

src/code-templates/api-client/ApiClientClass/MethodBody/PathParameter.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ export const isPathParameter = (params: any): params is CodeGenerator.PickedPara
1111
/**
1212
* const url = this.baseUrl + `[head]${params.parameter.[parameterName]}`;
1313
*/
14-
const generateUrlVariableStatement = (factory: TsGenerator.Factory.Type, urlTemplate: Utils.Params$TemplateExpression): ts.VariableStatement => {
14+
const generateUrlVariableStatement = (
15+
factory: TsGenerator.Factory.Type,
16+
urlTemplate: Utils.Params$TemplateExpression,
17+
): ts.VariableStatement => {
1518
return factory.VariableStatement.create({
1619
declarationList: factory.VariableDeclarationList.create({
1720
declarations: [
@@ -93,7 +96,11 @@ export const generateUrlTemplateExpression = (
9396
return urlTemplate;
9497
};
9598

96-
export const create = (factory: TsGenerator.Factory.Type, requestUri: string, pathParameters: CodeGenerator.PickedParameter[]): ts.VariableStatement => {
99+
export const create = (
100+
factory: TsGenerator.Factory.Type,
101+
requestUri: string,
102+
pathParameters: CodeGenerator.PickedParameter[],
103+
): ts.VariableStatement => {
97104
if (pathParameters.length > 0) {
98105
const urlTemplate = generateUrlTemplateExpression(factory, requestUri, pathParameters);
99106
return generateUrlVariableStatement(factory, urlTemplate);

src/code-templates/api-client/ApiClientClass/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import ts from "typescript";
22

33
import type { TsGenerator } from "../../../api";
44
import type { CodeGenerator } from "../../../types";
5+
import type { Option } from "../types";
56
import * as ApiClientInterface from "./ApiClientInterface";
67
import * as Class from "./Class";
78
import * as Constructor from "./Constructor";
89
import * as Method from "./Method";
910

1011
export { Method };
1112

12-
export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Params[], option: { sync?: boolean }): ts.Statement[] => {
13+
export const create = (factory: TsGenerator.Factory.Type, list: CodeGenerator.Params[], option: Option): ts.Statement[] => {
1314
const methodList = list.map(params => {
1415
return Method.create(factory, params, option);
1516
});

src/code-templates/api-client/index.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import { TsGenerator } from "../../api";
44
import type { CodeGenerator } from "../../types";
55
import * as ApiClientArgument from "./ApiClientArgument";
66
import * as ApiClientClass from "./ApiClientClass";
7+
import type { Option } from "./types";
78

8-
export interface Option {
9-
sync?: boolean;
10-
}
9+
export { Option };
1110

1211
export const generator: CodeGenerator.GenerateFunction<Option> = (
1312
codeGeneratorParamsList: CodeGenerator.Params[],
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface Option {
2+
/** default false */
3+
sync?: boolean;
4+
/** default false */
5+
additionalMethodComment?: boolean;
6+
}

src/index.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { EOL } from "os";
22

3-
import ts from "typescript";
4-
53
import * as Api from "./api";
64
import type * as Types from "./types";
75

8-
export interface GeneratorTemplate<T> {
6+
export interface CustomCodeGenerator<T> {
97
generator: Types.CodeGenerator.GenerateFunction<T>;
108
option?: T;
119
}
@@ -43,7 +41,7 @@ export class CodeGenerator {
4341
* @param generatorTemplate Template for when you want to change the code following a type definition
4442
* @returns String of generated code
4543
*/
46-
public generateTypeDefinition(generatorTemplates?: GeneratorTemplate<any>[]): string {
44+
public generateTypeDefinition(generatorTemplates?: CustomCodeGenerator<any>[]): string {
4745
const create = () => {
4846
const statements = this.parser.getOpenApiTypeDefinitionStatements();
4947
generatorTemplates?.forEach(generatorTemplate => {
@@ -62,7 +60,7 @@ export class CodeGenerator {
6260
* @param generatorTemplate
6361
* @returns String of generated code
6462
*/
65-
public generateCode(generatorTemplates: GeneratorTemplate<any>[]): string {
63+
public generateCode(generatorTemplates: CustomCodeGenerator<any>[]): string {
6664
const payload = this.parser.getCodeGeneratorParamsArray();
6765
const create = () => {
6866
return generatorTemplates
@@ -81,7 +79,14 @@ export class CodeGenerator {
8179
return this.parser.getCodeGeneratorParamsArray();
8280
}
8381

84-
public getAdditionalTypeStatements(): ts.Statement[] {
85-
return this.parser.getAdditionalTypeStatements();
82+
/**
83+
* Provides types for parameters for Templates.ApiClient.
84+
*
85+
* This API will be moved to Templates in the future.
86+
*/
87+
public getAdditionalTypeDefinitionCustomCodeGenerator(): CustomCodeGenerator<undefined> {
88+
return {
89+
generator: () => this.parser.getAdditionalTypeStatements(),
90+
};
8691
}
8792
}

src/internal/FileSystem/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface Type {
1313

1414
export class FileSystem {
1515
private static FRAGMENT = "#/";
16-
private static internalLoadJsonOrYaml (filename: string): any {
16+
private static internalLoadJsonOrYaml(filename: string): any {
1717
const ext = path.extname(filename);
1818
const data = fs.readFileSync(filename, { encoding: "utf-8" });
1919
switch (ext) {
@@ -25,7 +25,7 @@ export class FileSystem {
2525
default:
2626
throw new UnSupportError(`Not support file: ${filename}`);
2727
}
28-
};
28+
}
2929

3030
public static existSync(entryPoint: string): boolean {
3131
return !!(fs.existsSync(entryPoint) && fs.statSync(entryPoint).isFile());
@@ -39,5 +39,5 @@ export class FileSystem {
3939
return Dot.get(data, fragment.replace(/\//g, "."));
4040
}
4141
return this.internalLoadJsonOrYaml(entryPoint);
42-
};
42+
}
4343
}

src/internal/OpenApiTools/Extractor.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CodeGenerator, OpenApi } from "../../types";
1+
import type { CodeGenerator, OpenApi, Experimental } from "../../types";
22
import * as ConverterContext from "./ConverterContext";
33
import { Store } from "./store";
44

@@ -111,7 +111,8 @@ export const generateCodeGeneratorParamsArray = (
111111
//
112112
hasAdditionalHeaders: hasOver2RequestContentTypes || hasOver2SuccessNames,
113113
hasQueryParameters: hasQueryParameters(item.parameters),
114-
// Response Success Name
114+
115+
experimentalOpenApiOperation: item,
115116
};
116117
params.push(formatParams);
117118
});

src/internal/OpenApiTools/TypeNodeContext.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import * as Path from "path";
22

33
import ts from "typescript";
44

5-
import * as TypeScriptCodeGenerator from "../TsGenerator";
65
import { DevelopmentError } from "../Exception";
6+
import * as TypeScriptCodeGenerator from "../TsGenerator";
77
import * as ConverterContext from "./ConverterContext";
88
import { Store } from "./store";
99
import * as ToTypeNode from "./toTypeNode";

src/internal/OpenApiTools/components/Headers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenApi } from "../../../types";
2-
import { Factory } from "../../TsGenerator";
32
import { UndefinedComponent } from "../../Exception";
3+
import { Factory } from "../../TsGenerator";
44
import * as ConverterContext from "../ConverterContext";
55
import * as Guard from "../Guard";
66
import * as Name from "../Name";

src/internal/OpenApiTools/components/Parameters.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenApi } from "../../../types";
2-
import { Factory } from "../../TsGenerator";
32
import { UnSupportError } from "../../Exception";
3+
import { Factory } from "../../TsGenerator";
44
import * as ConverterContext from "../ConverterContext";
55
import * as Guard from "../Guard";
66
import * as Name from "../Name";

src/internal/OpenApiTools/components/PathItems.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenApi } from "../../../types";
2-
import { Factory } from "../../TsGenerator";
32
import { FeatureDevelopmentError, UnSupportError } from "../../Exception";
3+
import { Factory } from "../../TsGenerator";
44
import * as ConverterContext from "../ConverterContext";
55
import * as Guard from "../Guard";
66
import * as Name from "../Name";

src/internal/OpenApiTools/components/Responses.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import * as path from "path";
33
import ts from "typescript";
44

55
import type { OpenApi } from "../../../types";
6-
import { Factory } from "../../TsGenerator";
76
import { UndefinedComponent } from "../../Exception";
7+
import { Factory } from "../../TsGenerator";
88
import * as ConverterContext from "../ConverterContext";
99
import * as Guard from "../Guard";
1010
import * as Name from "../Name";

src/internal/OpenApiTools/components/Schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import ts from "typescript";
22

33
import type { OpenApi } from "../../../types";
4-
import { Factory } from "../../TsGenerator";
54
import { FeatureDevelopmentError } from "../../Exception";
5+
import { Factory } from "../../TsGenerator";
66
import * as ConvertContext from "../ConverterContext";
77
import * as Guard from "../Guard";
88
import { Store } from "../store";

src/internal/OpenApiTools/components/Schemas.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenApi } from "../../../types";
2-
import { Factory } from "../../TsGenerator";
32
import { UnSupportError } from "../../Exception";
3+
import { Factory } from "../../TsGenerator";
44
import * as ConverterContext from "../ConverterContext";
55
import * as Guard from "../Guard";
66
import * as InferredType from "../InferredType";

src/internal/OpenApiTools/components/SecuritySchemas.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OpenApi } from "../../../types";
2-
import { Factory } from "../../TsGenerator";
32
import { UndefinedComponent } from "../../Exception";
3+
import { Factory } from "../../TsGenerator";
44
import * as Guard from "../Guard";
55
import * as Name from "../Name";
66
import { Store } from "../store";

0 commit comments

Comments
 (0)