@f3liz/rescript-autogen-openapi 0.5.4 → 0.7.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.
@@ -0,0 +1,328 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+
3
+ // Templates.res - All Handlebars templates in one place
4
+
5
+ // === CodegenUtils ===
6
+
7
+ let fileHeader = `// {{{description}}}
8
+ // Generated by @f3liz/rescript-autogen-openapi
9
+ // DO NOT EDIT - This file is auto-generated
10
+
11
+ S.enableJson()
12
+ `
13
+
14
+ let docCommentSingle = `/** {{{content}}} */
15
+ `
16
+
17
+ let docCommentMulti = `/**
18
+ {{#each lines}}{{{this}}}
19
+ {{/each}}*/
20
+ `
21
+
22
+ let docComment = `{{#if summary}}// {{{summary}}}
23
+ {{/if}}{{#if description}}// {{{description}}}
24
+ {{/if}}`
25
+
26
+ // === EndpointGenerator ===
27
+
28
+ let endpointFunction = `{{{docComment}}}let {{{functionName}}} = async ({{{bodyParam}}}{{{paramSep}}}~fetch: {{{fetchTypeSignature}}}): {{{functionName}}}Response => {
29
+ {{{bodyValueConversion}}}
30
+ let response = await fetch(
31
+ ~url="{{{path}}}",
32
+ ~method_="{{{methodUpper}}}",
33
+ ~body={{{bodyArg}}},
34
+ )
35
+ {{{responseHandling}}}
36
+ }`
37
+
38
+ let moduleWrapped = `{{{header}}}
39
+
40
+ module {{{moduleName}}} = {
41
+ {{{body}}}
42
+ }`
43
+
44
+ let moduleUnwrapped = `{{{header}}}
45
+
46
+ {{{body}}}`
47
+
48
+ // === ModuleGenerator ===
49
+
50
+ let indexModule = `{{{header}}}
51
+
52
+ module {{{moduleName}}} = {
53
+ {{#each tags}} module {{{modulePascal}}} = {{{modulePascal}}}
54
+ {{/each}}}`
55
+
56
+ let combinedModule = `{{{header}}}
57
+
58
+ {{{shared}}}
59
+
60
+ {{{extension}}}`
61
+
62
+ // === ThinWrapperGenerator ===
63
+
64
+ let clientType = `type client = {
65
+ baseUrl: string,
66
+ token: option<string>,
67
+ fetch: {{{fetchTypeSignature}}},
68
+ }`
69
+
70
+ let connectFunction = `/** Create a client for {{{title}}} */
71
+ let connect = (~baseUrl: string, ~token: option<string>=?, ~fetch: {{{fetchTypeSignature}}}, ()): client => {
72
+ baseUrl,
73
+ token,
74
+ fetch,
75
+ }`
76
+
77
+ let wrapperFunction = `{{{docComment}}} {{{signature}}}: promise<{{{generatedModuleName}}}.{{{operationName}}}Response> =>
78
+ {{{generatedModuleName}}}.{{{operationName}}}({{{callArguments}}}~fetch=client.fetch)`
79
+
80
+ let wrapperFile = `// Generated thin wrapper
81
+
82
+ {{{clientTypeCode}}}
83
+
84
+ {{{connectFunctionCode}}}
85
+
86
+ {{{modulesCode}}}`
87
+
88
+ // === TypeScriptDtsGenerator ===
89
+
90
+ let methodSignature = `{{{docLines}}}
91
+ {{{functionName}}}({{{params}}}): Promise<{{{responsePascalName}}}Response>;`
92
+
93
+ let moduleDts = `// TypeScript definitions for {{{moduleName}}}
94
+ // Generated by @f3liz/rescript-autogen-openapi
95
+ // DO NOT EDIT
96
+
97
+ import { MisskeyClient } from './index';
98
+ import * as ComponentSchemas from './ComponentSchemas';
99
+
100
+ {{{interfaces}}}
101
+
102
+ export interface {{{moduleName}}}Module {
103
+ {{{methodSignatures}}}
104
+ }
105
+
106
+ export const {{{moduleName}}}: {{{moduleName}}}Module;`
107
+
108
+ let componentSchemasDts = `// TypeScript definitions for ComponentSchemas
109
+ // Generated by @f3liz/rescript-autogen-openapi
110
+ // DO NOT EDIT
111
+
112
+ {{{content}}}`
113
+
114
+ let indexDts = `// TypeScript definitions
115
+ // Generated by @f3liz/rescript-autogen-openapi
116
+ // DO NOT EDIT
117
+
118
+ {{#each modules}}{{{importLine}}}
119
+ {{/each}}
120
+ export class MisskeyClient {
121
+ constructor(baseUrl: string, token?: string);
122
+ readonly baseUrl: string;
123
+ readonly token?: string;
124
+ }
125
+
126
+ {{#each modules}}{{{exportLine}}}
127
+ {{/each}}`
128
+
129
+ // === TypeScriptWrapperGenerator ===
130
+
131
+ let wrapperMjsMethod = ` async {{{functionName}}}(client{{{requestArg}}}) {
132
+ return {{{moduleName}}}.{{{functionName}}}({
133
+ {{{bodyArg}}}fetch: (url, method, body) => client._fetch(url, method, body)
134
+ });
135
+ },`
136
+
137
+ let wrapperMjsNamespace = `export const {{{moduleName}}} = {
138
+ {{{methods}}}
139
+ };`
140
+
141
+ let wrapperMjs = `// Generated wrapper
142
+ {{#each tags}}{{{importLine}}}
143
+ {{/each}}
144
+ {{{clientCode}}}
145
+
146
+ {{#each tags}}{{{namespace}}}
147
+
148
+ {{/each}}`
149
+
150
+ let wrapperDtsFunction = `{{{docComment}}} export function {{{functionName}}}(client: MisskeyClient{{{requestParam}}}): Promise<{{{pascalName}}}Response>;`
151
+
152
+ let wrapperDtsNamespace = `export namespace {{{moduleName}}} {
153
+ {{{functions}}}
154
+ }`
155
+
156
+ let wrapperDts = `// Generated TypeScript definitions for wrapper
157
+ {{#each tags}}{{{importBlock}}}
158
+ {{/each}}
159
+ export class MisskeyClient {
160
+ constructor(baseUrl: string, token?: string);
161
+ readonly baseUrl: string;
162
+ readonly token?: string;
163
+ }
164
+
165
+ {{#each tags}}{{{namespace}}}
166
+
167
+ {{/each}}`
168
+
169
+ // === DiffReportGenerator ===
170
+
171
+ let mergeReport = `# Merge Report: {{{baseName}}} + {{{forkName}}}
172
+
173
+ ## Shared Code
174
+
175
+ - **Shared Endpoints**: {{{sharedEndpoints}}}
176
+ - **Shared Schemas**: {{{sharedSchemas}}}
177
+
178
+ ## {{{forkName}}} Extensions
179
+
180
+ - **Extension Endpoints**: {{{extensionEndpoints}}}
181
+ - **Extension Schemas**: {{{extensionSchemas}}}
182
+
183
+ ## Summary
184
+
185
+ The shared base contains {{{sharedEndpoints}}} endpoints and {{{sharedSchemas}}} schemas.
186
+
187
+ {{{forkName}}} adds {{{extensionEndpoints}}} endpoints and {{{extensionSchemas}}} schemas.
188
+
189
+ ---
190
+ *Generated on {{{timestamp}}}*`
191
+
192
+ // === SchemaCodeGenerator ===
193
+
194
+ let endpointModule = `{{{docComment}}}module {{{moduleName}}} = {
195
+ {{{schemasCode}}}
196
+
197
+ let endpoint = "{{{path}}}"
198
+ let method = #{{{methodStr}}}
199
+ }`
200
+
201
+ // === DocOverride ===
202
+
203
+ let overrideMarkdown = `{{{metadataBlock}}}
204
+
205
+ # {{{title}}}
206
+
207
+ **Path**: \`{{{path}}}\`
208
+ **Method**: \`{{{methodUpper}}}\`
209
+ **Operation**: \`{{{operationName}}}\`
210
+
211
+ ## Default Description
212
+
213
+ {{{defaultDesc}}}
214
+
215
+ ## Override
216
+
217
+ Add your custom documentation here. If this code block is empty, the default description will be used.
218
+
219
+ \`\`\`
220
+ <!-- Empty - no override -->
221
+ \`\`\``
222
+
223
+ let overrideReadme = `# API Documentation Overrides
224
+
225
+ This directory contains markdown files that allow you to override the auto-generated documentation.
226
+
227
+ ## Global Information
228
+
229
+ - **Host**: {{{hostInfo}}}
230
+ - **Version**: {{{versionInfo}}}
231
+
232
+ ## Structure
233
+
234
+ Each module has its own directory, and each endpoint has its own markdown file:
235
+
236
+ \`\`\`
237
+ docs/
238
+ ├── README.md (this file)
239
+ ├── Account/
240
+ │ ├── postBlockingCreate.md
241
+ │ ├── postBlockingDelete.md
242
+ │ └── ...
243
+ ├── Notes/
244
+ │ ├── postNotesCreate.md
245
+ │ └── ...
246
+ └── ...
247
+ \`\`\`
248
+
249
+ ## How to Override
250
+
251
+ 1. Find the endpoint you want to document in its module directory
252
+ 2. Open the markdown file
253
+ 3. Edit the code block under the "## Override" section
254
+ 4. Add your custom documentation (supports markdown)
255
+ 5. Regenerate the code - your custom documentation will be used instead of the default
256
+
257
+ ## File Format
258
+
259
+ Each file contains:
260
+
261
+ ### Frontmatter
262
+ - \`endpoint\`: The API endpoint path
263
+ - \`method\`: HTTP method (GET, POST, etc.)
264
+ - \`hash\`: Hash of the endpoint for change detection
265
+ - \`host\`: API host URL
266
+ - \`version\`: API version
267
+ - \`operationId\`: OpenAPI operation ID
268
+
269
+ ### Default Description
270
+ The original description from the OpenAPI spec.
271
+
272
+ ### Override Section
273
+ A code block where you can add your custom documentation. If empty, the default description is used.
274
+
275
+ ## Example
276
+
277
+ \`\`\`markdown
278
+ ---
279
+ endpoint: /blocking/create
280
+ method: POST
281
+ hash: abc123
282
+ host: https://misskey.io
283
+ version: 1.0.0
284
+ ---
285
+
286
+ # blocking/create
287
+
288
+ **Path**: \`/blocking/create\`
289
+ **Method**: \`POST\`
290
+
291
+ ## Default Description
292
+
293
+ No description provided.
294
+
295
+ **Credential required**: *Yes* / **Permission**: *write:blocks*
296
+
297
+ ## Override
298
+
299
+ \`\`\`
300
+ Create a blocking relationship with another user.
301
+
302
+ This endpoint allows you to block a user by their user ID. Once blocked:
303
+ - The user will not be able to see your posts
304
+ - You will not see their posts in your timeline
305
+ - They cannot follow you
306
+
307
+ **Parameters:**
308
+ - \`userId\`: The ID of the user to block
309
+
310
+ **Example:**
311
+ \`\`\`typescript
312
+ await client.blocking.create({ userId: "user123" })
313
+ \`\`\`
314
+ \`\`\`
315
+ \`\`\`
316
+
317
+ ## Notes
318
+
319
+ - The hash is used to detect if the endpoint has changed in the OpenAPI spec
320
+ - If the endpoint changes, you may need to update your override
321
+ - Empty override blocks (with just \`<!-- Empty - no override -->\`) are ignored`
322
+
323
+ // === ComponentSchemaGenerator ===
324
+
325
+ let componentSchemaModule = `{{{docComment}}}module {{{moduleName}}} = {
326
+ {{{extractedBlock}}}{{{typeKeyword}}} = {{{typeCode}}}
327
+ let schema = {{{schemaCode}}}
328
+ }`
@@ -193,10 +193,14 @@ let generate = (~spec, ~outputDir) => {
193
193
  ? `S.recursive("${schema.name}", schema => ${schemaCode})`
194
194
  : schemaCode
195
195
 
196
- `${docComment}module ${CodegenUtils.toPascalCase(schema.name)} = {
197
- ${extractedBlock} ${typeKeyword} = ${typeCode}
198
- let schema = ${finalSchemaCode}
199
- }`
196
+ Handlebars.render(Templates.componentSchemaModule, {
197
+ "docComment": docComment,
198
+ "moduleName": CodegenUtils.toPascalCase(schema.name),
199
+ "extractedBlock": extractedBlock,
200
+ "typeKeyword": ` ${typeKeyword}`,
201
+ "typeCode": typeCode,
202
+ "schemaCode": finalSchemaCode,
203
+ })
200
204
  })
201
205
 
202
206
  let fileHeader = CodegenUtils.generateFileHeader(~description="Shared component schemas")
@@ -76,35 +76,17 @@ let generateCompactSummary = (diff: specDiff) => {
76
76
  `Found ${totalChanges->Int.toString} changes: +${addedCount->Int.toString} -${removedCount->Int.toString} ~${modifiedCount->Int.toString} endpoints${breakingText}`
77
77
  }
78
78
 
79
- let generateMergeReport = (~stats: SpecMerger.mergeStats, ~baseName, ~forkName) => {
80
- let sharedEndpoints = stats.sharedEndpointCount->Int.toString
81
- let sharedSchemas = stats.sharedSchemaCount->Int.toString
82
- let extensionEndpoints = stats.forkExtensionCount->Int.toString
83
- let extensionSchemas = stats.forkSchemaCount->Int.toString
84
-
85
- `
86
- |# Merge Report: ${baseName} + ${forkName}
87
- |
88
- |## Shared Code
89
- |
90
- |- **Shared Endpoints**: ${sharedEndpoints}
91
- |- **Shared Schemas**: ${sharedSchemas}
92
- |
93
- |## ${forkName} Extensions
94
- |
95
- |- **Extension Endpoints**: ${extensionEndpoints}
96
- |- **Extension Schemas**: ${extensionSchemas}
97
- |
98
- |## Summary
99
- |
100
- |The shared base contains ${sharedEndpoints} endpoints and ${sharedSchemas} schemas.
101
- |
102
- |${forkName} adds ${extensionEndpoints} endpoints and ${extensionSchemas} schemas.
103
- |
104
- |---
105
- |*Generated on ${Date.make()->Date.toISOString}*
106
- |`->CodegenUtils.trimMargin
107
- }
79
+ let generateMergeReport = (~stats: SpecMerger.mergeStats, ~baseName, ~forkName) =>
80
+ Handlebars.render(Templates.mergeReport, {
81
+ "baseName": baseName,
82
+ "forkName": forkName,
83
+ "sharedEndpoints": stats.sharedEndpointCount->Int.toString,
84
+ "sharedSchemas": stats.sharedSchemaCount->Int.toString,
85
+ "extensionEndpoints": stats.forkExtensionCount->Int.toString,
86
+ "extensionSchemas": stats.forkSchemaCount->Int.toString,
87
+ "timestamp": Date.make()->Date.toISOString,
88
+ },
89
+ )
108
90
 
109
91
  let generateEndpointsByTagReport = (endpoints: array<endpoint>) => {
110
92
  let endpointsByTag = Dict.make()
@@ -53,9 +53,9 @@ let generateEndpointFunction = (endpoint: endpoint, ~overrideDir=?, ~moduleName=
53
53
  ->Array.get(0)
54
54
 
55
55
  let responseHandling = successResponse->Option.mapOr(" response", response =>
56
- response.content->Option.mapOr(" let _ = response\n ()", content =>
56
+ response.content->Option.mapOr(" let _ = response", content =>
57
57
  Dict.toArray(content)->Array.length > 0
58
- ? ` let value = response->S.parseOrThrow(${functionName}ResponseSchema)\n value`
58
+ ? ` response->S.parseOrThrow(${functionName}ResponseSchema)`
59
59
  : " response"
60
60
  )
61
61
  )
@@ -85,21 +85,23 @@ let generateEndpointFunction = (endpoint: endpoint, ~overrideDir=?, ~moduleName=
85
85
  (),
86
86
  )
87
87
 
88
- let code = `
89
- |${docComment->String.trimEnd}
90
- |let ${functionName} = (${bodyParam}${paramSep}~fetch: ${CodegenUtils.fetchTypeSignature}): promise<${functionName}Response> => {
91
- |${bodyValueConversion}
92
- | fetch(
93
- | ~url="${endpoint.path}",
94
- | ~method_="${endpoint.method->String.toUpperCase}",
95
- | ~body=${hasRequestBody ? "Some(jsonBody)" : "None"},
96
- | )->Promise.then(response => {
97
- |${responseHandling}
98
- | ->Promise.resolve
99
- | })
100
- |}`
88
+ let code = Handlebars.render(
89
+ Templates.endpointFunction,
90
+ {
91
+ "docComment": docComment,
92
+ "functionName": functionName,
93
+ "bodyParam": bodyParam,
94
+ "paramSep": paramSep,
95
+ "fetchTypeSignature": CodegenUtils.fetchTypeSignature,
96
+ "bodyValueConversion": bodyValueConversion,
97
+ "path": endpoint.path,
98
+ "methodUpper": endpoint.method->String.toUpperCase,
99
+ "bodyArg": hasRequestBody ? "Some(jsonBody)" : "None",
100
+ "responseHandling": responseHandling,
101
+ },
102
+ )
101
103
 
102
- code->CodegenUtils.trimMargin
104
+ code
103
105
  }
104
106
 
105
107
  let generateEndpointCode = (endpoint, ~overrideDir=?, ~moduleName=?, ~modulePrefix="") => {
@@ -143,13 +145,14 @@ let generateEndpointCode = (endpoint, ~overrideDir=?, ~moduleName=?, ~modulePref
143
145
  let generateEndpointModule = (~endpoint, ~modulePrefix="") => {
144
146
  let functionName = CodegenUtils.generateOperationName(endpoint.operationId, endpoint.path, endpoint.method)
145
147
  let header = CodegenUtils.generateFileHeader(~description=endpoint.summary->Option.getOr(`API: ${endpoint.path}`))
146
- `
147
- |${header->String.trimEnd}
148
- |
149
- |module ${CodegenUtils.toPascalCase(functionName)} = {
150
- |${generateEndpointCode(endpoint, ~modulePrefix)->CodegenUtils.indent(2)}
151
- |}
152
- |`->CodegenUtils.trimMargin
148
+ Handlebars.render(
149
+ Templates.moduleWrapped,
150
+ {
151
+ "header": header->String.trimEnd,
152
+ "moduleName": CodegenUtils.toPascalCase(functionName),
153
+ "body": generateEndpointCode(endpoint, ~modulePrefix)->CodegenUtils.indent(2),
154
+ },
155
+ )
153
156
  }
154
157
 
155
158
  let generateEndpointsModule = (~moduleName, ~endpoints, ~description=?, ~overrideDir=?, ~modulePrefix="") => {
@@ -159,13 +162,14 @@ let generateEndpointsModule = (~moduleName, ~endpoints, ~description=?, ~overrid
159
162
  ->Array.map(ep => generateEndpointCode(ep, ~overrideDir?, ~moduleName, ~modulePrefix)->CodegenUtils.indent(2))
160
163
  ->Array.join("\n\n")
161
164
 
162
- `
163
- |${header->String.trimEnd}
164
- |
165
- |module ${moduleName} = {
166
- |${body}
167
- |}
168
- |`->CodegenUtils.trimMargin
165
+ Handlebars.render(
166
+ Templates.moduleWrapped,
167
+ {
168
+ "header": header->String.trimEnd,
169
+ "moduleName": moduleName,
170
+ "body": body,
171
+ },
172
+ )
169
173
  }
170
174
 
171
175
  let generateEndpointSignature = (endpoint) => {
@@ -63,19 +63,22 @@ let generateTagModuleFile = (
63
63
  ->Array.join("\n\n")
64
64
 
65
65
  if wrapInModule {
66
- `
67
- |${header->String.trimEnd}
68
- |
69
- |module ${moduleName} = {
70
- |${body->CodegenUtils.indent(2)}
71
- |}
72
- |`->CodegenUtils.trimMargin
66
+ Handlebars.render(
67
+ Templates.moduleWrapped,
68
+ {
69
+ "header": header->String.trimEnd,
70
+ "moduleName": moduleName,
71
+ "body": body->CodegenUtils.indent(2),
72
+ },
73
+ )
73
74
  } else {
74
- `
75
- |${header->String.trimEnd}
76
- |
77
- |${body}
78
- |`->CodegenUtils.trimMargin
75
+ Handlebars.render(
76
+ Templates.moduleUnwrapped,
77
+ {
78
+ "header": header->String.trimEnd,
79
+ "body": body,
80
+ },
81
+ )
79
82
  }
80
83
  }
81
84
 
@@ -96,22 +99,19 @@ let generateAllTagModules = (
96
99
 
97
100
  let generateIndexModule = (~tags, ~moduleName="API") => {
98
101
  let header = CodegenUtils.generateFileHeader(~description="Main API module index")
99
- let modules =
102
+ let tagData =
100
103
  tags
101
104
  ->Array.toSorted(String.compare)
102
- ->Array.map(tag => {
103
- let m = CodegenUtils.toPascalCase(tag)
104
- ` module ${m} = ${m}`
105
- })
106
- ->Array.join("\n")
105
+ ->Array.map(tag => {"modulePascal": CodegenUtils.toPascalCase(tag)})
107
106
 
108
- `
109
- |${header->String.trimEnd}
110
- |
111
- |module ${moduleName} = {
112
- |${modules}
113
- |}
114
- |`->CodegenUtils.trimMargin
107
+ Handlebars.render(
108
+ Templates.indexModule,
109
+ {
110
+ "header": header->String.trimEnd,
111
+ "moduleName": moduleName,
112
+ "tags": tagData,
113
+ },
114
+ )
115
115
  }
116
116
 
117
117
  let generateFlatModuleCode = (~moduleName, ~endpoints, ~overrideDir=?) => {
@@ -127,13 +127,14 @@ let generateFlatModuleCode = (~moduleName, ~endpoints, ~overrideDir=?) => {
127
127
  )
128
128
  ->Array.join("\n\n")
129
129
 
130
- `
131
- |${header->String.trimEnd}
132
- |
133
- |module ${moduleName} = {
134
- |${body}
135
- |}
136
- |`->CodegenUtils.trimMargin
130
+ Handlebars.render(
131
+ Templates.moduleWrapped,
132
+ {
133
+ "header": header->String.trimEnd,
134
+ "moduleName": moduleName,
135
+ "body": body,
136
+ },
137
+ )
137
138
  }
138
139
 
139
140
  let internalGenerateIntegratedModule = (
@@ -220,13 +221,14 @@ let generateCombinedModule = (
220
221
  ~includeHeader=false,
221
222
  )
222
223
 
223
- `
224
- |${header->String.trimEnd}
225
- |
226
- |${shared}
227
- |
228
- |${extension}
229
- |`->CodegenUtils.trimMargin
224
+ Handlebars.render(
225
+ Templates.combinedModule,
226
+ {
227
+ "header": header->String.trimEnd,
228
+ "shared": shared,
229
+ "extension": extension,
230
+ },
231
+ )
230
232
  }
231
233
 
232
234
  let generateTagModuleFiles = (~endpoints, ~outputDir, ~wrapInModule=false, ~overrideDir=?) => {
@@ -75,10 +75,12 @@ let generateEndpointModule = (path, method, operation: Types.operation) => {
75
75
  }
76
76
  let schemasCode = generateOperationSchemas(operationId, operation)
77
77
 
78
- `${docComment}module ${CodegenUtils.toPascalCase(operationId)} = {
79
- ${schemasCode->CodegenUtils.indent(2)}
80
-
81
- let endpoint = "${path}"
82
- let method = #${methodStr}
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
- |type client = {
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
- |/** Create a client for ${title} */
17
- |let connect = (~baseUrl: string, ~token: option<string>=?, ~fetch: ${CodegenUtils.fetchTypeSignature}, ()): client => {
18
- | baseUrl,
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
- `${docComment} ${signature}: promise<${generatedModuleName}.${operationName}Response> =>
45
- ${generatedModuleName}.${operationName}(${callArguments}~fetch=client.fetch)`
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 = `// Generated thin wrapper
113
-
114
- ${clientTypeCode}
115
-
116
- ${generateConnectFunction(spec.info.title)}
117
-
118
- ${modulesCode}`
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}],