@f3liz/rescript-autogen-openapi 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/es6/src/bindings/Handlebars.mjs +43 -0
- package/lib/es6/src/core/CodegenUtils.mjs +17 -39
- package/lib/es6/src/core/DocOverride.mjs +14 -123
- package/lib/es6/src/core/Templates.mjs +341 -0
- package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +10 -4
- package/lib/es6/src/generators/DiffReportGenerator.mjs +12 -28
- package/lib/es6/src/generators/EndpointGenerator.mjs +25 -31
- package/lib/es6/src/generators/IRToSuryGenerator.mjs +8 -41
- package/lib/es6/src/generators/ModuleGenerator.mjs +29 -37
- package/lib/es6/src/generators/SchemaCodeGenerator.mjs +10 -7
- package/lib/es6/src/generators/ThinWrapperGenerator.mjs +21 -24
- package/lib/es6/src/generators/TypeScriptDtsGenerator.mjs +52 -58
- package/lib/es6/src/generators/TypeScriptWrapperGenerator.mjs +76 -80
- package/package.json +2 -1
- package/src/bindings/Handlebars.res +43 -0
- package/src/core/CodegenUtils.res +9 -33
- package/src/core/DocOverride.res +10 -124
- package/src/core/Templates.res +330 -0
- package/src/generators/ComponentSchemaGenerator.res +8 -4
- package/src/generators/DiffReportGenerator.res +11 -29
- package/src/generators/EndpointGenerator.res +32 -28
- package/src/generators/IRToSuryGenerator.res +9 -43
- package/src/generators/ModuleGenerator.res +41 -39
- package/src/generators/SchemaCodeGenerator.res +8 -6
- package/src/generators/ThinWrapperGenerator.res +24 -24
- package/src/generators/TypeScriptDtsGenerator.res +41 -61
- package/src/generators/TypeScriptWrapperGenerator.res +58 -83
|
@@ -75,10 +75,12 @@ let generateEndpointModule = (path, method, operation: Types.operation) => {
|
|
|
75
75
|
}
|
|
76
76
|
let schemasCode = generateOperationSchemas(operationId, operation)
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
Handlebars.render(Templates.endpointModule, {
|
|
79
|
+
"docComment": docComment,
|
|
80
|
+
"moduleName": CodegenUtils.toPascalCase(operationId),
|
|
81
|
+
"schemasCode": schemasCode->CodegenUtils.indent(2),
|
|
82
|
+
"path": path,
|
|
83
|
+
"methodStr": methodStr,
|
|
84
|
+
},
|
|
85
|
+
)
|
|
84
86
|
}
|
|
@@ -3,23 +3,14 @@
|
|
|
3
3
|
// ThinWrapperGenerator.res - Generate ReScript thin wrappers with pipe-first ergonomics
|
|
4
4
|
open Types
|
|
5
5
|
|
|
6
|
-
let clientTypeCode =
|
|
7
|
-
|
|
8
|
-
| baseUrl: string,
|
|
9
|
-
| token: option<string>,
|
|
10
|
-
| fetch: ${CodegenUtils.fetchTypeSignature},
|
|
11
|
-
|}
|
|
12
|
-
|`->CodegenUtils.trimMargin
|
|
6
|
+
let clientTypeCode =
|
|
7
|
+
Handlebars.render(Templates.clientType, {"fetchTypeSignature": CodegenUtils.fetchTypeSignature})
|
|
13
8
|
|
|
14
9
|
let generateConnectFunction = (title) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
| token,
|
|
20
|
-
| fetch,
|
|
21
|
-
|}
|
|
22
|
-
|`->CodegenUtils.trimMargin
|
|
10
|
+
Handlebars.render(
|
|
11
|
+
Templates.connectFunction,
|
|
12
|
+
{"title": title, "fetchTypeSignature": CodegenUtils.fetchTypeSignature},
|
|
13
|
+
)
|
|
23
14
|
|
|
24
15
|
let generateWrapperFunction = (~endpoint: endpoint, ~generatedModuleName: string) => {
|
|
25
16
|
let operationName = CodegenUtils.generateOperationName(
|
|
@@ -41,8 +32,16 @@ let generateWrapperFunction = (~endpoint: endpoint, ~generatedModuleName: string
|
|
|
41
32
|
|
|
42
33
|
let callArguments = hasRequestBody ? "~body=request, " : ""
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
Handlebars.render(
|
|
36
|
+
Templates.wrapperFunction,
|
|
37
|
+
{
|
|
38
|
+
"docComment": docComment,
|
|
39
|
+
"signature": signature,
|
|
40
|
+
"generatedModuleName": generatedModuleName,
|
|
41
|
+
"operationName": operationName,
|
|
42
|
+
"callArguments": callArguments,
|
|
43
|
+
},
|
|
44
|
+
)
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
let generateWrapper = (
|
|
@@ -109,13 +108,14 @@ let generateWrapper = (
|
|
|
109
108
|
})
|
|
110
109
|
->Array.join("\n\n")
|
|
111
110
|
|
|
112
|
-
let fileContent =
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
let fileContent = Handlebars.render(
|
|
112
|
+
Templates.wrapperFile,
|
|
113
|
+
{
|
|
114
|
+
"clientTypeCode": clientTypeCode,
|
|
115
|
+
"connectFunctionCode": generateConnectFunction(spec.info.title),
|
|
116
|
+
"modulesCode": modulesCode,
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
119
|
|
|
120
120
|
Pipeline.fromFilesAndWarnings(
|
|
121
121
|
[{path: FileSystem.makePath(outputDir, `${wrapperModuleName}.res`), content: fileContent}],
|
|
@@ -47,22 +47,29 @@ let generateMethodSignature = (~endpoint: endpoint, ~functionName) => {
|
|
|
47
47
|
? `client: MisskeyClient, request: ${CodegenUtils.toPascalCase(functionName)}Request`
|
|
48
48
|
: "client: MisskeyClient"
|
|
49
49
|
|
|
50
|
-
let docLines = endpoint.summary
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
50
|
+
let docLines = switch (endpoint.summary, endpoint.description) {
|
|
51
|
+
| (None, None) => ""
|
|
52
|
+
| (Some(summary), None) => ` /** ${summary} */`
|
|
53
|
+
| (None, Some(desc)) => {
|
|
54
|
+
let lines = desc->String.split("\n")->Array.map(line => line == "" ? " *" : ` * ${line}`)
|
|
55
|
+
` /**\n${lines->Array.join("\n")}\n */`
|
|
56
|
+
}
|
|
57
|
+
| (Some(summary), Some(desc)) if summary == desc => ` /** ${summary} */`
|
|
58
|
+
| (Some(summary), Some(desc)) => {
|
|
59
|
+
let descLines = desc->String.split("\n")->Array.map(line => line == "" ? " *" : ` * ${line}`)
|
|
60
|
+
` /**\n * ${summary}\n *\n${descLines->Array.join("\n")}\n */`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Handlebars.render(
|
|
65
|
+
Templates.methodSignature,
|
|
66
|
+
{
|
|
67
|
+
"docLines": docLines,
|
|
68
|
+
"functionName": functionName,
|
|
69
|
+
"params": params,
|
|
70
|
+
"responsePascalName": CodegenUtils.toPascalCase(functionName),
|
|
71
|
+
},
|
|
72
|
+
)
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
// Generate .d.ts file for a module (grouped by tag)
|
|
@@ -96,26 +103,14 @@ let generateModuleDts = (~moduleName, ~endpoints: array<endpoint>) => {
|
|
|
96
103
|
)
|
|
97
104
|
->Array.join("\n")
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
`
|
|
109
|
-
|${header}
|
|
110
|
-
|
|
|
111
|
-
|${interfaces}
|
|
112
|
-
|
|
|
113
|
-
|export interface ${moduleName}Module {
|
|
114
|
-
|${methodSignatures}
|
|
115
|
-
|}
|
|
116
|
-
|
|
|
117
|
-
|export const ${moduleName}: ${moduleName}Module;
|
|
118
|
-
|`->CodegenUtils.trimMargin
|
|
106
|
+
Handlebars.render(
|
|
107
|
+
Templates.moduleDts,
|
|
108
|
+
{
|
|
109
|
+
"moduleName": moduleName,
|
|
110
|
+
"interfaces": interfaces,
|
|
111
|
+
"methodSignatures": methodSignatures,
|
|
112
|
+
},
|
|
113
|
+
)
|
|
119
114
|
}
|
|
120
115
|
|
|
121
116
|
// Generate ComponentSchemas.d.ts
|
|
@@ -125,35 +120,20 @@ let generateComponentSchemasDts = (~schemas: Dict.t<jsonSchema>) => {
|
|
|
125
120
|
->Array.map(((name, schema)) => generateTypeScriptType(name, schema.description, schema))
|
|
126
121
|
->Array.join("\n\n")
|
|
127
122
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
|
133
|
-
|${content}
|
|
134
|
-
|`->CodegenUtils.trimMargin
|
|
123
|
+
Handlebars.render(
|
|
124
|
+
Templates.componentSchemasDts,
|
|
125
|
+
{"content": content},
|
|
126
|
+
)
|
|
135
127
|
}
|
|
136
128
|
|
|
137
129
|
// Generate main index.d.ts with MisskeyClient class
|
|
138
130
|
let generateIndexDts = (~moduleNames) => {
|
|
139
|
-
let
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|// DO NOT EDIT
|
|
146
|
-
|
|
|
147
|
-
|${imports}
|
|
148
|
-
|
|
|
149
|
-
|export class MisskeyClient {
|
|
150
|
-
| constructor(baseUrl: string, token?: string);
|
|
151
|
-
| readonly baseUrl: string;
|
|
152
|
-
| readonly token?: string;
|
|
153
|
-
|}
|
|
154
|
-
|
|
|
155
|
-
|${exports}
|
|
156
|
-
|`->CodegenUtils.trimMargin
|
|
131
|
+
let modules = moduleNames->Array.map(m => {
|
|
132
|
+
"importLine": `import { ${m}Module } from './${m}';`,
|
|
133
|
+
"exportLine": `export const ${m}: ${m}Module;`,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
Handlebars.render(Templates.indexDts, {"modules": modules})
|
|
157
137
|
}
|
|
158
138
|
|
|
159
139
|
// Generate all .d.ts files for a spec
|
|
@@ -3,43 +3,22 @@
|
|
|
3
3
|
// TypeScriptWrapperGenerator.res - Generate TypeScript/JavaScript wrapper
|
|
4
4
|
open Types
|
|
5
5
|
|
|
6
|
-
let misskeyClientJsCode =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
|
13
|
-
| async _fetch(url, method, body) {
|
|
14
|
-
| const headers = { 'Content-Type': 'application/json' };
|
|
15
|
-
| if (this.token) {
|
|
16
|
-
| headers['Authorization'] = \`Bearer \${this.token}\`;
|
|
17
|
-
| }
|
|
18
|
-
| const response = await fetch(this.baseUrl + url, {
|
|
19
|
-
| method,
|
|
20
|
-
| headers,
|
|
21
|
-
| body: body ? JSON.stringify(body) : undefined,
|
|
22
|
-
| });
|
|
23
|
-
| return response.json();
|
|
24
|
-
| }
|
|
25
|
-
|}`->CodegenUtils.trimMargin
|
|
6
|
+
let misskeyClientJsCode = {
|
|
7
|
+
let body: string = %raw(`
|
|
8
|
+
"export class MisskeyClient {\n constructor(baseUrl, token) {\n this.baseUrl = baseUrl;\n this.token = token;\n }\n\n async _fetch(url, method, body) {\n const headers = { 'Content-Type': 'application/json' };\n if (this.token) {\n headers['Authorization'] = \x60Bearer \x24{this.token}\x60;\n }\n const response = await fetch(this.baseUrl + url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n return response.json();\n }\n}"
|
|
9
|
+
`)
|
|
10
|
+
body
|
|
11
|
+
}
|
|
26
12
|
|
|
27
13
|
let generateWrapperMjs = (~endpoints, ~generatedModulePath) => {
|
|
28
14
|
let endpointsByTag = OpenAPIParser.groupByTag(endpoints)
|
|
29
15
|
let tags = Dict.keysToArray(endpointsByTag)
|
|
30
16
|
|
|
31
|
-
let
|
|
32
|
-
tags
|
|
33
|
-
->Array.map(tag => {
|
|
34
|
-
let moduleName = CodegenUtils.toPascalCase(tag)
|
|
35
|
-
`import * as ${moduleName} from '${generatedModulePath}/${moduleName}.mjs';`
|
|
36
|
-
})
|
|
37
|
-
->Array.join("\n")
|
|
38
|
-
|
|
39
|
-
let wrappers =
|
|
17
|
+
let tagData =
|
|
40
18
|
tags
|
|
41
19
|
->Array.map(tag => {
|
|
42
20
|
let moduleName = CodegenUtils.toPascalCase(tag)
|
|
21
|
+
let importLine = `import * as ${moduleName} from '${generatedModulePath}/${moduleName}.mjs';`
|
|
43
22
|
let methods =
|
|
44
23
|
Dict.get(endpointsByTag, tag)
|
|
45
24
|
->Option.getOr([])
|
|
@@ -50,37 +29,36 @@ let generateWrapperMjs = (~endpoints, ~generatedModulePath) => {
|
|
|
50
29
|
endpoint.method,
|
|
51
30
|
)
|
|
52
31
|
let hasRequestBody = endpoint.requestBody->Option.isSome
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
32
|
+
Handlebars.render(
|
|
33
|
+
Templates.wrapperMjsMethod,
|
|
34
|
+
{
|
|
35
|
+
"functionName": functionName,
|
|
36
|
+
"moduleName": moduleName,
|
|
37
|
+
"requestArg": hasRequestBody ? ", request" : "",
|
|
38
|
+
"bodyArg": hasRequestBody ? "body: request, " : "",
|
|
39
|
+
},
|
|
40
|
+
)
|
|
60
41
|
})
|
|
61
42
|
->Array.join("\n")
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
43
|
+
|
|
44
|
+
let namespace = Handlebars.render(
|
|
45
|
+
Templates.wrapperMjsNamespace,
|
|
46
|
+
{"moduleName": moduleName, "methods": methods},
|
|
47
|
+
)
|
|
48
|
+
{"importLine": importLine, "namespace": namespace}
|
|
66
49
|
})
|
|
67
|
-
->Array.join("\n\n")
|
|
68
50
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|${misskeyClientJsCode}
|
|
74
|
-
|
|
|
75
|
-
|${wrappers}
|
|
76
|
-
|`->CodegenUtils.trimMargin
|
|
51
|
+
Handlebars.render(
|
|
52
|
+
Templates.wrapperMjs,
|
|
53
|
+
{"tags": tagData, "clientCode": misskeyClientJsCode},
|
|
54
|
+
)
|
|
77
55
|
}
|
|
78
56
|
|
|
79
57
|
let generateWrapperDts = (~endpoints) => {
|
|
80
58
|
let endpointsByTag = OpenAPIParser.groupByTag(endpoints)
|
|
81
59
|
let tags = Dict.keysToArray(endpointsByTag)
|
|
82
60
|
|
|
83
|
-
let
|
|
61
|
+
let tagData =
|
|
84
62
|
tags
|
|
85
63
|
->Array.map(tag => {
|
|
86
64
|
let moduleName = CodegenUtils.toPascalCase(tag)
|
|
@@ -98,16 +76,8 @@ let generateWrapperDts = (~endpoints) => {
|
|
|
98
76
|
}
|
|
99
77
|
})
|
|
100
78
|
->Array.join("\n")
|
|
101
|
-
`import type {
|
|
102
|
-
${typesToImport}
|
|
103
|
-
} from '../types/${moduleName}.d.ts';`
|
|
104
|
-
})
|
|
105
|
-
->Array.join("\n")
|
|
79
|
+
let importBlock = `import type {\n${typesToImport}\n} from '../types/${moduleName}.d.ts';`
|
|
106
80
|
|
|
107
|
-
let namespaces =
|
|
108
|
-
tags
|
|
109
|
-
->Array.map(tag => {
|
|
110
|
-
let moduleName = CodegenUtils.toPascalCase(tag)
|
|
111
81
|
let functions =
|
|
112
82
|
Dict.get(endpointsByTag, tag)
|
|
113
83
|
->Option.getOr([])
|
|
@@ -118,35 +88,40 @@ ${typesToImport}
|
|
|
118
88
|
endpoint.method,
|
|
119
89
|
)
|
|
120
90
|
let pascalName = CodegenUtils.toPascalCase(functionName)
|
|
121
|
-
let docComment = endpoint.summary
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
91
|
+
let docComment = switch (endpoint.summary, endpoint.description) {
|
|
92
|
+
| (None, None) => ""
|
|
93
|
+
| (Some(summary), None) => ` /** ${summary} */\n`
|
|
94
|
+
| (None, Some(desc)) => {
|
|
95
|
+
let lines = desc->String.split("\n")->Array.map(line => line == "" ? " *" : ` * ${line}`)
|
|
96
|
+
` /**\n${lines->Array.join("\n")}\n */\n`
|
|
97
|
+
}
|
|
98
|
+
| (Some(summary), Some(desc)) if summary == desc => ` /** ${summary} */\n`
|
|
99
|
+
| (Some(summary), Some(desc)) => {
|
|
100
|
+
let descLines = desc->String.split("\n")->Array.map(line => line == "" ? " *" : ` * ${line}`)
|
|
101
|
+
` /**\n * ${summary}\n *\n${descLines->Array.join("\n")}\n */\n`
|
|
102
|
+
}
|
|
103
|
+
}
|
|
127
104
|
let requestParam = endpoint.requestBody->Option.isSome ? `, request: ${pascalName}Request` : ""
|
|
128
|
-
|
|
105
|
+
Handlebars.render(
|
|
106
|
+
Templates.wrapperDtsFunction,
|
|
107
|
+
{
|
|
108
|
+
"docComment": docComment,
|
|
109
|
+
"functionName": functionName,
|
|
110
|
+
"requestParam": requestParam,
|
|
111
|
+
"pascalName": pascalName,
|
|
112
|
+
},
|
|
113
|
+
)
|
|
129
114
|
})
|
|
130
115
|
->Array.join("\n")
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
116
|
+
|
|
117
|
+
let namespace = Handlebars.render(
|
|
118
|
+
Templates.wrapperDtsNamespace,
|
|
119
|
+
{"moduleName": moduleName, "functions": functions},
|
|
120
|
+
)
|
|
121
|
+
{"importBlock": importBlock, "namespace": namespace}
|
|
135
122
|
})
|
|
136
|
-
->Array.join("\n\n")
|
|
137
123
|
|
|
138
|
-
|
|
139
|
-
|// Generated TypeScript definitions for wrapper
|
|
140
|
-
|${imports}
|
|
141
|
-
|
|
|
142
|
-
|export class MisskeyClient {
|
|
143
|
-
| constructor(baseUrl: string, token?: string);
|
|
144
|
-
| readonly baseUrl: string;
|
|
145
|
-
| readonly token?: string;
|
|
146
|
-
|}
|
|
147
|
-
|
|
|
148
|
-
|${namespaces}
|
|
149
|
-
|`->CodegenUtils.trimMargin
|
|
124
|
+
Handlebars.render(Templates.wrapperDts, {"tags": tagData})
|
|
150
125
|
}
|
|
151
126
|
|
|
152
127
|
let generate = (~endpoints, ~outputDir, ~generatedModulePath="../generated") => {
|