massimo-cli 0.3.0 → 0.4.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/index.js +191 -40
- package/lib/graphql-generator.js +22 -8
- package/lib/openapi-generator.js +24 -9
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { access, mkdir, readFile, rm, writeFile } from 'fs/promises'
|
|
|
4
4
|
import graphql from 'graphql'
|
|
5
5
|
import helpMe from 'help-me'
|
|
6
6
|
import parseArgs from 'minimist'
|
|
7
|
-
import { join } from 'path'
|
|
7
|
+
import { join, dirname } from 'path'
|
|
8
8
|
import pino from 'pino'
|
|
9
9
|
import pinoPretty from 'pino-pretty'
|
|
10
10
|
import { getGlobalDispatcher, interceptors, request } from 'undici'
|
|
@@ -43,6 +43,35 @@ export async function createDirectory (path, empty = false) {
|
|
|
43
43
|
return mkdir(path, { recursive: true, maxRetries: 10, retryDelay: 1000 })
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
export async function detectModuleFormat (folder, explicitFormat) {
|
|
47
|
+
if (explicitFormat) {
|
|
48
|
+
if (explicitFormat === 'esm' || explicitFormat === 'cjs') {
|
|
49
|
+
return explicitFormat
|
|
50
|
+
}
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Invalid module format: ${explicitFormat}. Valid values are 'esm' or 'cjs'`
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
let currentDir = folder
|
|
56
|
+
while (currentDir !== dirname(currentDir)) {
|
|
57
|
+
const packageJsonPath = join(currentDir, 'package.json')
|
|
58
|
+
if (await isFileAccessible(packageJsonPath)) {
|
|
59
|
+
try {
|
|
60
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
|
|
61
|
+
if (packageJson.type === 'module') return 'esm'
|
|
62
|
+
// If no type field or any other value, it's CommonJS per Node.js defaults
|
|
63
|
+
return 'cjs'
|
|
64
|
+
} catch (err) {
|
|
65
|
+
// If we can't parse it, continue searching
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
currentDir = dirname(currentDir)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Default to ESM
|
|
72
|
+
return 'esm'
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
async function writeOpenAPIClient (
|
|
47
76
|
folder,
|
|
48
77
|
name,
|
|
@@ -58,17 +87,23 @@ async function writeOpenAPIClient (
|
|
|
58
87
|
typesComment,
|
|
59
88
|
logger,
|
|
60
89
|
withCredentials,
|
|
61
|
-
propsOptional
|
|
90
|
+
propsOptional,
|
|
91
|
+
moduleFormat
|
|
62
92
|
) {
|
|
63
93
|
await createDirectory(folder)
|
|
64
94
|
|
|
65
95
|
// TODO deal with yaml
|
|
66
96
|
const schema = parseFile(text)
|
|
67
97
|
if (!schema) {
|
|
68
|
-
throw new Error(
|
|
98
|
+
throw new Error(
|
|
99
|
+
'Cannot parse OpenAPI file. Please make sure is a JSON or a YAML file.'
|
|
100
|
+
)
|
|
69
101
|
}
|
|
70
102
|
if (!typesOnly) {
|
|
71
|
-
await writeFile(
|
|
103
|
+
await writeFile(
|
|
104
|
+
join(folder, `${name}.openapi.json`),
|
|
105
|
+
JSON.stringify(schema, null, 2)
|
|
106
|
+
)
|
|
72
107
|
}
|
|
73
108
|
|
|
74
109
|
if (isFrontend) {
|
|
@@ -80,7 +115,7 @@ async function writeOpenAPIClient (
|
|
|
80
115
|
language,
|
|
81
116
|
logger,
|
|
82
117
|
withCredentials,
|
|
83
|
-
propsOptional
|
|
118
|
+
propsOptional,
|
|
84
119
|
})
|
|
85
120
|
await writeFile(join(folder, `${name}-types.d.mts`), types)
|
|
86
121
|
if (generateImplementation) {
|
|
@@ -96,30 +131,54 @@ async function writeOpenAPIClient (
|
|
|
96
131
|
optionalHeaders,
|
|
97
132
|
validateResponse,
|
|
98
133
|
typesComment,
|
|
99
|
-
propsOptional
|
|
134
|
+
propsOptional,
|
|
135
|
+
moduleFormat,
|
|
100
136
|
})
|
|
101
|
-
|
|
137
|
+
const typeExt = moduleFormat === 'esm' ? 'd.mts' : 'd.cts'
|
|
138
|
+
const implExt = moduleFormat === 'esm' ? 'mjs' : 'cjs'
|
|
139
|
+
await writeFile(join(folder, `${name}.${typeExt}`), types)
|
|
102
140
|
if (generateImplementation) {
|
|
103
|
-
await writeFile(join(folder, `${name}
|
|
141
|
+
await writeFile(join(folder, `${name}.${implExt}`), implementation)
|
|
104
142
|
}
|
|
105
143
|
|
|
106
144
|
if (!typesOnly) {
|
|
107
|
-
await writeFile(
|
|
145
|
+
await writeFile(
|
|
146
|
+
join(folder, 'package.json'),
|
|
147
|
+
getPackageJSON({ name, generateImplementation, moduleFormat })
|
|
148
|
+
)
|
|
108
149
|
}
|
|
109
150
|
}
|
|
110
151
|
}
|
|
111
152
|
|
|
112
|
-
async function writeGraphQLClient (
|
|
153
|
+
async function writeGraphQLClient (
|
|
154
|
+
folder,
|
|
155
|
+
name,
|
|
156
|
+
schema,
|
|
157
|
+
url,
|
|
158
|
+
generateImplementation,
|
|
159
|
+
moduleFormat
|
|
160
|
+
) {
|
|
113
161
|
await createDirectory(folder, { recursive: true })
|
|
114
|
-
const { types, implementation } = processGraphQL({
|
|
162
|
+
const { types, implementation } = processGraphQL({
|
|
163
|
+
schema,
|
|
164
|
+
name,
|
|
165
|
+
folder,
|
|
166
|
+
url,
|
|
167
|
+
moduleFormat,
|
|
168
|
+
})
|
|
115
169
|
const clientSchema = graphql.buildClientSchema(schema)
|
|
116
170
|
const sdl = graphql.printSchema(clientSchema)
|
|
171
|
+
const typeExt = moduleFormat === 'esm' ? 'd.mts' : 'd.cts'
|
|
172
|
+
const implExt = moduleFormat === 'esm' ? 'mjs' : 'cjs'
|
|
117
173
|
await writeFile(join(folder, `${name}.schema.graphql`), sdl)
|
|
118
|
-
await writeFile(join(folder, `${name}
|
|
174
|
+
await writeFile(join(folder, `${name}.${typeExt}`), types)
|
|
119
175
|
if (generateImplementation) {
|
|
120
|
-
await writeFile(join(folder, `${name}
|
|
176
|
+
await writeFile(join(folder, `${name}.${implExt}`), implementation)
|
|
121
177
|
}
|
|
122
|
-
await writeFile(
|
|
178
|
+
await writeFile(
|
|
179
|
+
join(folder, 'package.json'),
|
|
180
|
+
getPackageJSON({ name, generateImplementation, moduleFormat })
|
|
181
|
+
)
|
|
123
182
|
}
|
|
124
183
|
|
|
125
184
|
async function downloadAndWriteOpenAPI (
|
|
@@ -139,7 +198,8 @@ async function downloadAndWriteOpenAPI (
|
|
|
139
198
|
typesComment,
|
|
140
199
|
withCredentials,
|
|
141
200
|
propsOptional,
|
|
142
|
-
retryTimeoutMs
|
|
201
|
+
retryTimeoutMs,
|
|
202
|
+
moduleFormat
|
|
143
203
|
) {
|
|
144
204
|
logger.debug(`Trying to download OpenAPI schema from ${url}`)
|
|
145
205
|
let requestOptions
|
|
@@ -152,7 +212,9 @@ async function downloadAndWriteOpenAPI (
|
|
|
152
212
|
}
|
|
153
213
|
|
|
154
214
|
const dispatcher = retryTimeoutMs
|
|
155
|
-
? getGlobalDispatcher().compose([
|
|
215
|
+
? getGlobalDispatcher().compose([
|
|
216
|
+
interceptors.retry({ minTimeout: retryTimeoutMs })
|
|
217
|
+
])
|
|
156
218
|
: undefined
|
|
157
219
|
const res = await request(url, { ...requestOptions, dispatcher })
|
|
158
220
|
if (res.statusCode === 200) {
|
|
@@ -174,7 +236,8 @@ async function downloadAndWriteOpenAPI (
|
|
|
174
236
|
typesComment,
|
|
175
237
|
logger,
|
|
176
238
|
withCredentials,
|
|
177
|
-
propsOptional
|
|
239
|
+
propsOptional,
|
|
240
|
+
moduleFormat
|
|
178
241
|
)
|
|
179
242
|
/* c8 ignore next 3 */
|
|
180
243
|
} catch (err) {
|
|
@@ -188,7 +251,14 @@ async function downloadAndWriteOpenAPI (
|
|
|
188
251
|
return false
|
|
189
252
|
}
|
|
190
253
|
|
|
191
|
-
async function downloadAndWriteGraphQL (
|
|
254
|
+
async function downloadAndWriteGraphQL (
|
|
255
|
+
logger,
|
|
256
|
+
url,
|
|
257
|
+
folder,
|
|
258
|
+
name,
|
|
259
|
+
generateImplementation,
|
|
260
|
+
moduleFormat
|
|
261
|
+
) {
|
|
192
262
|
logger.debug(`Trying to download GraphQL schema from ${url}`)
|
|
193
263
|
const query = graphql.getIntrospectionQuery()
|
|
194
264
|
const res = await request(url, {
|
|
@@ -198,7 +268,7 @@ async function downloadAndWriteGraphQL (logger, url, folder, name, generateImple
|
|
|
198
268
|
},
|
|
199
269
|
body: JSON.stringify({
|
|
200
270
|
query
|
|
201
|
-
})
|
|
271
|
+
}),
|
|
202
272
|
})
|
|
203
273
|
|
|
204
274
|
const text = await res.body.text()
|
|
@@ -208,7 +278,14 @@ async function downloadAndWriteGraphQL (logger, url, folder, name, generateImple
|
|
|
208
278
|
}
|
|
209
279
|
|
|
210
280
|
const { data: schema } = JSON.parse(text)
|
|
211
|
-
await writeGraphQLClient(
|
|
281
|
+
await writeGraphQLClient(
|
|
282
|
+
folder,
|
|
283
|
+
name,
|
|
284
|
+
schema,
|
|
285
|
+
url,
|
|
286
|
+
generateImplementation,
|
|
287
|
+
moduleFormat
|
|
288
|
+
)
|
|
212
289
|
return 'graphql'
|
|
213
290
|
}
|
|
214
291
|
|
|
@@ -227,7 +304,8 @@ async function readFromFileAndWrite (
|
|
|
227
304
|
language,
|
|
228
305
|
typesComment,
|
|
229
306
|
withCredentials,
|
|
230
|
-
propsOptional
|
|
307
|
+
propsOptional,
|
|
308
|
+
moduleFormat
|
|
231
309
|
) {
|
|
232
310
|
logger.info(`Trying to read schema from file ${file}`)
|
|
233
311
|
const text = await readFile(file, 'utf8')
|
|
@@ -248,17 +326,28 @@ async function readFromFileAndWrite (
|
|
|
248
326
|
typesComment,
|
|
249
327
|
logger,
|
|
250
328
|
withCredentials,
|
|
251
|
-
propsOptional
|
|
329
|
+
propsOptional,
|
|
330
|
+
moduleFormat
|
|
252
331
|
)
|
|
253
332
|
return 'openapi'
|
|
254
333
|
} catch (err) {
|
|
255
|
-
logger.error(
|
|
334
|
+
logger.error(
|
|
335
|
+
err,
|
|
336
|
+
`Error parsing OpenAPI definition: "${err.message}". Trying with GraphQL`
|
|
337
|
+
)
|
|
256
338
|
// try GraphQL
|
|
257
339
|
const schema = graphql.buildSchema(text)
|
|
258
340
|
const introspectionResult = graphql.introspectionFromSchema(schema)
|
|
259
341
|
|
|
260
342
|
// dummy URL
|
|
261
|
-
await writeGraphQLClient(
|
|
343
|
+
await writeGraphQLClient(
|
|
344
|
+
folder,
|
|
345
|
+
name,
|
|
346
|
+
introspectionResult,
|
|
347
|
+
'http://localhost:3042/graphql',
|
|
348
|
+
generateImplementation,
|
|
349
|
+
moduleFormat
|
|
350
|
+
)
|
|
262
351
|
return 'graphql'
|
|
263
352
|
}
|
|
264
353
|
}
|
|
@@ -280,7 +369,8 @@ async function downloadAndProcess (options) {
|
|
|
280
369
|
typesComment,
|
|
281
370
|
withCredentials,
|
|
282
371
|
propsOptional,
|
|
283
|
-
retryTimeoutMs
|
|
372
|
+
retryTimeoutMs,
|
|
373
|
+
moduleFormat
|
|
284
374
|
} = options
|
|
285
375
|
|
|
286
376
|
const generateImplementation = options.generateImplementation
|
|
@@ -308,7 +398,8 @@ async function downloadAndProcess (options) {
|
|
|
308
398
|
typesComment,
|
|
309
399
|
withCredentials,
|
|
310
400
|
propsOptional,
|
|
311
|
-
retryTimeoutMs
|
|
401
|
+
retryTimeoutMs,
|
|
402
|
+
moduleFormat
|
|
312
403
|
)
|
|
313
404
|
)
|
|
314
405
|
toTry.push(
|
|
@@ -330,14 +421,33 @@ async function downloadAndProcess (options) {
|
|
|
330
421
|
typesComment,
|
|
331
422
|
withCredentials,
|
|
332
423
|
propsOptional,
|
|
333
|
-
retryTimeoutMs
|
|
424
|
+
retryTimeoutMs,
|
|
425
|
+
moduleFormat
|
|
334
426
|
)
|
|
335
427
|
)
|
|
336
428
|
} else if (options.type === 'graphql') {
|
|
337
429
|
toTry.push(
|
|
338
|
-
downloadAndWriteGraphQL.bind(
|
|
430
|
+
downloadAndWriteGraphQL.bind(
|
|
431
|
+
null,
|
|
432
|
+
logger,
|
|
433
|
+
url + '/graphql',
|
|
434
|
+
folder,
|
|
435
|
+
name,
|
|
436
|
+
generateImplementation,
|
|
437
|
+
moduleFormat
|
|
438
|
+
)
|
|
439
|
+
)
|
|
440
|
+
toTry.push(
|
|
441
|
+
downloadAndWriteGraphQL.bind(
|
|
442
|
+
null,
|
|
443
|
+
logger,
|
|
444
|
+
url,
|
|
445
|
+
folder,
|
|
446
|
+
name,
|
|
447
|
+
generateImplementation,
|
|
448
|
+
moduleFormat
|
|
449
|
+
)
|
|
339
450
|
)
|
|
340
|
-
toTry.push(downloadAndWriteGraphQL.bind(null, logger, url, folder, name, generateImplementation, typesOnly))
|
|
341
451
|
} else {
|
|
342
452
|
// add download functions only if it's an URL
|
|
343
453
|
toTry.push(
|
|
@@ -359,11 +469,20 @@ async function downloadAndProcess (options) {
|
|
|
359
469
|
typesComment,
|
|
360
470
|
withCredentials,
|
|
361
471
|
propsOptional,
|
|
362
|
-
retryTimeoutMs
|
|
472
|
+
retryTimeoutMs,
|
|
473
|
+
moduleFormat
|
|
363
474
|
)
|
|
364
475
|
)
|
|
365
476
|
toTry.push(
|
|
366
|
-
downloadAndWriteGraphQL.bind(
|
|
477
|
+
downloadAndWriteGraphQL.bind(
|
|
478
|
+
null,
|
|
479
|
+
logger,
|
|
480
|
+
url + '/graphql',
|
|
481
|
+
folder,
|
|
482
|
+
name,
|
|
483
|
+
generateImplementation,
|
|
484
|
+
moduleFormat
|
|
485
|
+
)
|
|
367
486
|
)
|
|
368
487
|
toTry.push(
|
|
369
488
|
downloadAndWriteOpenAPI.bind(
|
|
@@ -384,10 +503,21 @@ async function downloadAndProcess (options) {
|
|
|
384
503
|
typesComment,
|
|
385
504
|
withCredentials,
|
|
386
505
|
propsOptional,
|
|
387
|
-
retryTimeoutMs
|
|
506
|
+
retryTimeoutMs,
|
|
507
|
+
moduleFormat
|
|
508
|
+
)
|
|
509
|
+
)
|
|
510
|
+
toTry.push(
|
|
511
|
+
downloadAndWriteGraphQL.bind(
|
|
512
|
+
null,
|
|
513
|
+
logger,
|
|
514
|
+
url,
|
|
515
|
+
folder,
|
|
516
|
+
name,
|
|
517
|
+
generateImplementation,
|
|
518
|
+
moduleFormat
|
|
388
519
|
)
|
|
389
520
|
)
|
|
390
|
-
toTry.push(downloadAndWriteGraphQL.bind(null, logger, url, folder, name, generateImplementation, typesOnly))
|
|
391
521
|
}
|
|
392
522
|
} else {
|
|
393
523
|
// add readFromFileAndWrite to the functions only if it's not an URL
|
|
@@ -408,7 +538,8 @@ async function downloadAndProcess (options) {
|
|
|
408
538
|
language,
|
|
409
539
|
typesComment,
|
|
410
540
|
withCredentials,
|
|
411
|
-
propsOptional
|
|
541
|
+
propsOptional,
|
|
542
|
+
moduleFormat
|
|
412
543
|
)
|
|
413
544
|
)
|
|
414
545
|
}
|
|
@@ -420,18 +551,25 @@ async function downloadAndProcess (options) {
|
|
|
420
551
|
}
|
|
421
552
|
/* c8 ignore next 3 */
|
|
422
553
|
if (!found) {
|
|
423
|
-
throw new Error(
|
|
554
|
+
throw new Error(
|
|
555
|
+
`Could not find a valid OpenAPI or GraphQL schema at ${url}`
|
|
556
|
+
)
|
|
424
557
|
}
|
|
425
558
|
}
|
|
426
559
|
|
|
427
|
-
function getPackageJSON ({ name, generateImplementation }) {
|
|
560
|
+
function getPackageJSON ({ name, generateImplementation, moduleFormat }) {
|
|
561
|
+
const isESM = moduleFormat === 'esm'
|
|
428
562
|
const obj = {
|
|
429
563
|
name,
|
|
430
|
-
types: `./${name}.d.
|
|
564
|
+
types: `./${name}.${isESM ? 'd.mts' : 'd.cts'}`
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (isESM) {
|
|
568
|
+
obj.type = 'module'
|
|
431
569
|
}
|
|
432
570
|
|
|
433
571
|
if (generateImplementation) {
|
|
434
|
-
obj.main = `./${name}
|
|
572
|
+
obj.main = `./${name}.${isESM ? 'mjs' : 'cjs'}`
|
|
435
573
|
}
|
|
436
574
|
|
|
437
575
|
return JSON.stringify(obj, null, 2)
|
|
@@ -447,7 +585,16 @@ export async function command (argv) {
|
|
|
447
585
|
_: [url],
|
|
448
586
|
...options
|
|
449
587
|
} = parseArgs(argv, {
|
|
450
|
-
string: [
|
|
588
|
+
string: [
|
|
589
|
+
'name',
|
|
590
|
+
'folder',
|
|
591
|
+
'optional-headers',
|
|
592
|
+
'language',
|
|
593
|
+
'type',
|
|
594
|
+
'url-auth-headers',
|
|
595
|
+
'types-comment',
|
|
596
|
+
'module'
|
|
597
|
+
],
|
|
451
598
|
boolean: [
|
|
452
599
|
'typescript',
|
|
453
600
|
'full-response',
|
|
@@ -507,7 +654,7 @@ export async function command (argv) {
|
|
|
507
654
|
options.propsOptional = options['props-optional'] ?? true
|
|
508
655
|
|
|
509
656
|
options.optionalHeaders = options['optional-headers']
|
|
510
|
-
? options['optional-headers'].split(',').map(h => h.trim())
|
|
657
|
+
? options['optional-headers'].split(',').map((h) => h.trim())
|
|
511
658
|
: []
|
|
512
659
|
|
|
513
660
|
options.validateResponse = options['validate-response']
|
|
@@ -516,6 +663,10 @@ export async function command (argv) {
|
|
|
516
663
|
options.name = options.isFrontend ? 'api' : 'client'
|
|
517
664
|
}
|
|
518
665
|
options.folder = options.folder || join(process.cwd(), options.name)
|
|
666
|
+
options.moduleFormat = await detectModuleFormat(options.folder, options.module)
|
|
667
|
+
if (!options.module) {
|
|
668
|
+
logger.info(`Module format detected: ${options.moduleFormat}`)
|
|
669
|
+
}
|
|
519
670
|
options.urlAuthHeaders = options['url-auth-headers']
|
|
520
671
|
options.typesComment = options['types-comment']
|
|
521
672
|
options.withCredentials = options['with-credentials']
|
package/lib/graphql-generator.js
CHANGED
|
@@ -2,11 +2,11 @@ import CodeBlockWriter from 'code-block-writer'
|
|
|
2
2
|
import { UnknownTypeError } from './errors.js'
|
|
3
3
|
import { capitalize, toJavaScriptName } from './utils.js'
|
|
4
4
|
|
|
5
|
-
export function processGraphQL ({ schema, name, folder, url }) {
|
|
5
|
+
export function processGraphQL ({ schema, name, folder, url, moduleFormat }) {
|
|
6
6
|
schema = schema.__schema
|
|
7
7
|
return {
|
|
8
8
|
types: generateTypesFromGraphQL({ schema, name }),
|
|
9
|
-
implementation: generateImplementationFromGraqhQL({ schema, name, url })
|
|
9
|
+
implementation: generateImplementationFromGraqhQL({ schema, name, url, moduleFormat })
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -60,8 +60,9 @@ function generateTypesFromGraphQL ({ schema, name }) {
|
|
|
60
60
|
return writer.toString()
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function generateImplementationFromGraqhQL ({ name, url }) {
|
|
63
|
+
function generateImplementationFromGraqhQL ({ name, url, moduleFormat }) {
|
|
64
64
|
const camelcasedName = toJavaScriptName(name)
|
|
65
|
+
const isESM = moduleFormat === 'esm'
|
|
65
66
|
|
|
66
67
|
const writer = new CodeBlockWriter({
|
|
67
68
|
indentNumberOfSpaces: 2,
|
|
@@ -69,27 +70,40 @@ function generateImplementationFromGraqhQL ({ name, url }) {
|
|
|
69
70
|
useSingleQuote: true
|
|
70
71
|
})
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
if (isESM) {
|
|
74
|
+
writer.writeLine("import { buildGraphQLClient } from 'massimo'")
|
|
75
|
+
writer.writeLine("import { join } from 'node:path'")
|
|
76
|
+
} else {
|
|
77
|
+
writer.writeLine("const { buildGraphQLClient } = require('massimo')")
|
|
78
|
+
writer.writeLine("const { join } = require('node:path')")
|
|
79
|
+
}
|
|
74
80
|
writer.blankLine()
|
|
75
81
|
|
|
76
82
|
url = new URL(url)
|
|
77
83
|
|
|
78
84
|
const functionName = `generate${capitalize(camelcasedName)}Client`
|
|
79
|
-
|
|
85
|
+
const funcDecl = isESM ? `export async function ${functionName} (opts)` : `async function ${functionName} (opts)`
|
|
86
|
+
writer.write(funcDecl).block(() => {
|
|
80
87
|
writer.writeLine('const url = new URL(opts.url)')
|
|
81
88
|
writer.writeLine(`url.pathname = '${url.pathname}'`)
|
|
82
89
|
writer.write('return buildGraphQLClient(').inlineBlock(() => {
|
|
83
90
|
writer.writeLine("type: 'graphql',")
|
|
84
91
|
writer.writeLine(`name: '${camelcasedName}',`)
|
|
85
|
-
|
|
92
|
+
const pathExpr = isESM ? `join(import.meta.dirname, '${name}.schema.graphql')` : `join(__dirname, '${name}.schema.graphql')`
|
|
93
|
+
writer.writeLine(`path: ${pathExpr},`)
|
|
86
94
|
writer.writeLine('serviceId: opts.serviceId,')
|
|
87
95
|
writer.writeLine('url: url.toString()')
|
|
88
96
|
})
|
|
89
97
|
writer.write(')')
|
|
90
98
|
})
|
|
91
99
|
writer.blankLine()
|
|
92
|
-
|
|
100
|
+
if (isESM) {
|
|
101
|
+
writer.writeLine(`export default ${functionName}`)
|
|
102
|
+
} else {
|
|
103
|
+
writer.writeLine(`module.exports = ${functionName}`)
|
|
104
|
+
writer.writeLine(`module.exports.default = ${functionName}`)
|
|
105
|
+
writer.writeLine(`module.exports.${functionName} = ${functionName}`)
|
|
106
|
+
}
|
|
93
107
|
return writer.toString()
|
|
94
108
|
}
|
|
95
109
|
|
package/lib/openapi-generator.js
CHANGED
|
@@ -11,7 +11,8 @@ export function processOpenAPI ({
|
|
|
11
11
|
optionalHeaders,
|
|
12
12
|
validateResponse,
|
|
13
13
|
typesComment,
|
|
14
|
-
propsOptional
|
|
14
|
+
propsOptional,
|
|
15
|
+
moduleFormat
|
|
15
16
|
}) {
|
|
16
17
|
return {
|
|
17
18
|
types: generateTypesFromOpenAPI({
|
|
@@ -23,12 +24,13 @@ export function processOpenAPI ({
|
|
|
23
24
|
typesComment,
|
|
24
25
|
propsOptional
|
|
25
26
|
}),
|
|
26
|
-
implementation: generateImplementationFromOpenAPI({ name, fullResponse, fullRequest, validateResponse })
|
|
27
|
+
implementation: generateImplementationFromOpenAPI({ name, fullResponse, fullRequest, validateResponse, moduleFormat })
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
function generateImplementationFromOpenAPI ({ name, fullResponse, fullRequest, validateResponse }) {
|
|
31
|
+
function generateImplementationFromOpenAPI ({ name, fullResponse, fullRequest, validateResponse, moduleFormat }) {
|
|
31
32
|
const camelcasedName = toJavaScriptName(name)
|
|
33
|
+
const isESM = moduleFormat === 'esm'
|
|
32
34
|
|
|
33
35
|
const writer = new CodeBlockWriter({
|
|
34
36
|
indentNumberOfSpaces: 2,
|
|
@@ -36,16 +38,23 @@ function generateImplementationFromOpenAPI ({ name, fullResponse, fullRequest, v
|
|
|
36
38
|
useSingleQuote: true
|
|
37
39
|
})
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
if (isESM) {
|
|
42
|
+
writer.writeLine("import { buildOpenAPIClient } from 'massimo'")
|
|
43
|
+
writer.writeLine("import { join } from 'node:path'")
|
|
44
|
+
} else {
|
|
45
|
+
writer.writeLine("const { buildOpenAPIClient } = require('massimo')")
|
|
46
|
+
writer.writeLine("const { join } = require('node:path')")
|
|
47
|
+
}
|
|
41
48
|
writer.blankLine()
|
|
42
49
|
|
|
43
50
|
const functionName = `generate${capitalize(camelcasedName)}Client`
|
|
44
|
-
|
|
51
|
+
const funcDecl = isESM ? `export async function ${functionName} (opts)` : `async function ${functionName} (opts)`
|
|
52
|
+
writer.write(funcDecl).block(() => {
|
|
45
53
|
writer.write('return buildOpenAPIClient(').inlineBlock(() => {
|
|
46
54
|
writer.writeLine("type: 'openapi',")
|
|
47
55
|
writer.writeLine(`name: '${camelcasedName}',`)
|
|
48
|
-
|
|
56
|
+
const pathExpr = isESM ? `join(import.meta.dirname, '${name}.openapi.json')` : `join(__dirname, '${name}.openapi.json')`
|
|
57
|
+
writer.writeLine(`path: ${pathExpr},`)
|
|
49
58
|
writer.writeLine('url: opts.url,')
|
|
50
59
|
writer.writeLine('serviceId: opts.serviceId,')
|
|
51
60
|
writer.writeLine('throwOnError: opts.throwOnError,')
|
|
@@ -57,7 +66,13 @@ function generateImplementationFromOpenAPI ({ name, fullResponse, fullRequest, v
|
|
|
57
66
|
writer.write(')')
|
|
58
67
|
})
|
|
59
68
|
writer.blankLine()
|
|
60
|
-
|
|
69
|
+
if (isESM) {
|
|
70
|
+
writer.writeLine(`export default ${functionName}`)
|
|
71
|
+
} else {
|
|
72
|
+
writer.writeLine(`module.exports = ${functionName}`)
|
|
73
|
+
writer.writeLine(`module.exports.default = ${functionName}`)
|
|
74
|
+
writer.writeLine(`module.exports.${functionName} = ${functionName}`)
|
|
75
|
+
}
|
|
61
76
|
return writer.toString()
|
|
62
77
|
}
|
|
63
78
|
|
|
@@ -68,7 +83,7 @@ function generateTypesFromOpenAPI ({
|
|
|
68
83
|
fullRequest,
|
|
69
84
|
optionalHeaders,
|
|
70
85
|
typesComment,
|
|
71
|
-
propsOptional
|
|
86
|
+
propsOptional,
|
|
72
87
|
}) {
|
|
73
88
|
const camelcasedName = toJavaScriptName(name)
|
|
74
89
|
const capitalizedName = capitalize(camelcasedName)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "massimo-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A client for HTTP services.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"pino-pretty": "^13.0.0",
|
|
31
31
|
"undici": "^7.0.0",
|
|
32
32
|
"yaml": "^2.4.1",
|
|
33
|
-
"massimo": "0.
|
|
33
|
+
"massimo": "0.4.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@platformatic/composer": "3.0.0-alpha.6",
|