Skip to content

Commit 24c7bd2

Browse files
authored
feat: Support for schema containing format (#63)
1 parent bb80cbd commit 24c7bd2

File tree

14 files changed

+543
-125
lines changed

14 files changed

+543
-125
lines changed

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,72 @@ const customGenerator: Types.CodeGenerator.CustomGenerator<Option> = {
176176
}
177177
```
178178

179+
### Define any Data Types Format
180+
181+
Convert a Data Type with the following `format` to any type definition.
182+
183+
```yaml
184+
components:
185+
schemas:
186+
Binary:
187+
type: string
188+
format: binary
189+
IntOrString:
190+
type: string
191+
format: int-or-string
192+
AandB:
193+
type: string
194+
format: A-and-B
195+
```
196+
197+
The option to convert the Data Type Format to an arbitrary type definition is defined as follows.
198+
199+
```ts
200+
import { CodeGenerator, Option } from "@himenon/openapi-typescript-code-generator";
201+
const option: Option = {
202+
convertOption: {
203+
formatConversions: [
204+
{
205+
selector: {
206+
format: "binary",
207+
},
208+
output: {
209+
type: ["Blob"],
210+
},
211+
},
212+
{
213+
selector: {
214+
format: "int-or-string",
215+
},
216+
output: {
217+
type: ["number", "string"],
218+
},
219+
},
220+
{
221+
selector: {
222+
format: "A-and-B",
223+
},
224+
output: {
225+
type: ["A", "B"],
226+
multiType: "allOf",
227+
},
228+
},
229+
],
230+
},
231+
};
232+
const codeGenerator = new CodeGenerator(inputFilename, option);
233+
```
234+
235+
The typedef generated by this will look like this
236+
237+
```ts
238+
export namespace Schemas {
239+
export type Binary = Blob;
240+
export type IntOrString = number | string;
241+
export type AandB = A & B;
242+
}
243+
```
244+
179245
### Define a code template with TypeScript AST
180246

181247
You can extend your code using the API of TypeScript AST.

docs/ja/README-ja.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,72 @@ const customGenerator: Types.CodeGenerator.CustomGenerator<Option> = {
174174
}
175175
```
176176

177+
### 任意の Data Types Format を定義する
178+
179+
以下のような`format`が指定された Data Type を任意の型定義に変換します。
180+
181+
```yaml
182+
components:
183+
schemas:
184+
Binary:
185+
type: string
186+
format: binary
187+
IntOrString:
188+
type: string
189+
format: int-or-string
190+
AandB:
191+
type: string
192+
format: A-and-B
193+
```
194+
195+
Data Type Formatを任意の型定義に変換するオプションは次のように定義します。
196+
197+
```ts
198+
import { CodeGenerator, Option } from "@himenon/openapi-typescript-code-generator";
199+
const option: Option = {
200+
convertOption: {
201+
formatConversions: [
202+
{
203+
selector: {
204+
format: "binary",
205+
},
206+
output: {
207+
type: ["Blob"],
208+
},
209+
},
210+
{
211+
selector: {
212+
format: "int-or-string",
213+
},
214+
output: {
215+
type: ["number", "string"],
216+
},
217+
},
218+
{
219+
selector: {
220+
format: "A-and-B",
221+
},
222+
output: {
223+
type: ["A", "B"],
224+
multiType: "allOf",
225+
},
226+
},
227+
],
228+
},
229+
};
230+
const codeGenerator = new CodeGenerator(inputFilename, option);
231+
```
232+
233+
これで生成される型定義は次のようになります。
234+
235+
```ts
236+
export namespace Schemas {
237+
export type Binary = Blob;
238+
export type IntOrString = number | string;
239+
export type AandB = A & B;
240+
}
241+
```
242+
177243
### TypeScript AST によるコードテンプレートを定義する
178244

179245
TypeScript AST の API を利用したコードの拡張が可能です。

scripts/testCodeGen.ts

Lines changed: 24 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,42 @@
1-
import * as fs from "fs";
2-
import { posix as path } from "path";
3-
4-
import { CodeGenerator } from "../lib";
5-
import * as Templates from "../lib/templates";
6-
import type * as Types from "../lib/types";
7-
8-
const writeText = (filename: string, text: string): void => {
9-
fs.mkdirSync(path.dirname(filename), { recursive: true });
10-
fs.writeFileSync(filename, text, { encoding: "utf-8" });
11-
console.log(`Generate Code : ${filename}`);
12-
};
13-
14-
const generateTypedefCodeOnly = (inputFilename: string, outputFilename: string, isValidate: boolean) => {
15-
const codeGenerator = new CodeGenerator(inputFilename);
16-
if (isValidate) {
17-
codeGenerator.validateOpenApiSchema({
18-
logger: { displayLogLines: 1 },
19-
});
20-
}
21-
const code = codeGenerator.generateTypeDefinition();
22-
writeText(outputFilename, code);
23-
};
24-
25-
const generateTemplateCodeOnly = (
26-
inputFilename: string,
27-
outputFilename: string,
28-
isValidate: boolean,
29-
option: Templates.ApiClient.Option,
30-
): void => {
31-
const codeGenerator = new CodeGenerator(inputFilename);
32-
if (isValidate) {
33-
codeGenerator.validateOpenApiSchema({
34-
logger: { displayLogLines: 1 },
35-
});
36-
}
37-
38-
const apiClientGeneratorTemplate: Types.CodeGenerator.CustomGenerator<Templates.ApiClient.Option> = {
39-
generator: Templates.ApiClient.generator,
40-
option: option,
41-
};
42-
43-
const code = codeGenerator.generateCode([apiClientGeneratorTemplate]);
44-
45-
writeText(outputFilename, code);
46-
};
47-
48-
const generateTypedefWithTemplateCode = (
49-
inputFilename: string,
50-
outputFilename: string,
51-
isValidate: boolean,
52-
option: Templates.ApiClient.Option,
53-
): void => {
54-
const codeGenerator = new CodeGenerator(inputFilename);
55-
if (isValidate) {
56-
codeGenerator.validateOpenApiSchema({
57-
logger: { displayLogLines: 1 },
58-
});
59-
}
60-
61-
const code = codeGenerator.generateTypeDefinition([
62-
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
63-
{
64-
generator: Templates.ApiClient.generator,
65-
option: option,
66-
},
67-
]);
68-
69-
writeText(outputFilename, code);
70-
};
71-
72-
const generateSplitCode = (inputFilename: string, outputDir: string) => {
73-
const codeGenerator = new CodeGenerator(inputFilename);
74-
75-
const apiClientGeneratorTemplate: Types.CodeGenerator.CustomGenerator<Templates.ApiClient.Option> = {
76-
generator: Templates.ApiClient.generator,
77-
option: { sync: false, additionalMethodComment: true },
78-
};
79-
80-
const typeDefCode = codeGenerator.generateTypeDefinition();
81-
const apiClientCode = codeGenerator.generateCode([
82-
{
83-
generator: () => {
84-
return [`import { Schemas } from "./types";`];
85-
},
86-
},
87-
codeGenerator.getAdditionalTypeDefinitionCustomCodeGenerator(),
88-
apiClientGeneratorTemplate,
89-
]);
90-
91-
writeText(path.join(outputDir, "types.ts"), typeDefCode);
92-
writeText(path.join(outputDir, "apiClient.ts"), apiClientCode);
93-
};
94-
95-
const generateParameter = (inputFilename: string, outputFilename: string) => {
96-
const codeGenerator = new CodeGenerator(inputFilename);
97-
writeText(outputFilename, JSON.stringify(codeGenerator.getCodeGeneratorParamsArray(), null, 2));
98-
};
1+
import * as Writer from "./writer";
992

1003
const main = () => {
101-
generateTypedefCodeOnly("test/api.test.domain/index.yml", "test/code/typedef-only/api.test.domain.ts", true);
102-
generateTypedefCodeOnly("test/infer.domain/index.yml", "test/code/typedef-only/infer.domain.ts", false);
4+
Writer.generateTypedefCodeOnly("test/api.test.domain/index.yml", "test/code/typedef-only/api.test.domain.ts", true);
5+
Writer.generateTypedefCodeOnly("test/infer.domain/index.yml", "test/code/typedef-only/infer.domain.ts", false);
1036

104-
generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/api.test.domain.ts", true, { sync: false });
105-
generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/sync-api.test.domain.ts", true, { sync: true });
106-
generateTemplateCodeOnly("test/infer.domain/index.yml", "test/code/template-only/infer.domain.ts", false, { sync: true });
7+
Writer.generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/api.test.domain.ts", true, { sync: false });
8+
Writer.generateTemplateCodeOnly("test/api.test.domain/index.yml", "test/code/template-only/sync-api.test.domain.ts", true, { sync: true });
9+
Writer.generateTemplateCodeOnly("test/infer.domain/index.yml", "test/code/template-only/infer.domain.ts", false, { sync: true });
10710

108-
generateTypedefWithTemplateCode("test/api.v2.domain/index.yml", "test/code/typedef-with-template/api.v2.domain.ts", false, { sync: false });
109-
generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/api.test.domain.ts", true, {
11+
Writer.generateTypedefWithTemplateCode("test/api.v2.domain/index.yml", "test/code/typedef-with-template/api.v2.domain.ts", false, {
11012
sync: false,
11113
});
112-
generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/sync-api.test.domain.ts", true, {
14+
Writer.generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/api.test.domain.ts", true, {
15+
sync: false,
16+
});
17+
Writer.generateTypedefWithTemplateCode("test/api.test.domain/index.yml", "test/code/typedef-with-template/sync-api.test.domain.ts", true, {
11318
sync: true,
11419
});
115-
generateTypedefWithTemplateCode("test/infer.domain/index.yml", "test/code/typedef-with-template/infer.domain.ts", false, { sync: false });
20+
Writer.generateTypedefWithTemplateCode("test/infer.domain/index.yml", "test/code/typedef-with-template/infer.domain.ts", false, {
21+
sync: false,
22+
});
11623

117-
generateTypedefWithTemplateCode("test/ref.access/index.yml", "test/code/typedef-with-template/ref-access.ts", false, {
24+
Writer.generateTypedefWithTemplateCode("test/ref.access/index.yml", "test/code/typedef-with-template/ref-access.ts", false, {
11825
sync: false,
11926
});
120-
generateTypedefWithTemplateCode("test/kubernetes/openapi-v1.18.5.json", "test/code/kubernetes/client-v1.18.5.ts", false, { sync: false });
121-
generateTypedefWithTemplateCode("test/argo-rollout/index.json", "test/code/argo-rollout/client.ts", false, {
27+
Writer.generateTypedefWithTemplateCode("test/kubernetes/openapi-v1.18.5.json", "test/code/kubernetes/client-v1.18.5.ts", false, {
12228
sync: false,
12329
});
30+
Writer.generateTypedefWithTemplateCode("test/argo-rollout/index.json", "test/code/argo-rollout/client.ts", false, {
31+
sync: false,
32+
});
33+
34+
Writer.generateSplitCode("test/api.test.domain/index.yml", "test/code/split");
12435

125-
generateSplitCode("test/api.test.domain/index.yml", "test/code/split");
36+
Writer.generateParameter("test/api.test.domain/index.yml", "test/code/parameter/api.test.domain.json");
37+
Writer.generateParameter("test/infer.domain/index.yml", "test/code/parameter/infer.domain.json");
12638

127-
generateParameter("test/api.test.domain/index.yml", "test/code/parameter/api.test.domain.json");
128-
generateParameter("test/infer.domain/index.yml", "test/code/parameter/infer.domain.json");
39+
Writer.generateFormatTypeCode("test/format.domain/index.yml", "test/code/format.domain/code.ts");
12940
};
13041

13142
main();

0 commit comments

Comments
 (0)