1
1
#!/usr/bin/env node
2
2
3
- const fs = require ( "fs" ) ;
4
- const { bold, green, red } = require ( "kleur" ) ;
5
- const meow = require ( "meow" ) ;
6
- const path = require ( "path" ) ;
7
- const glob = require ( "tiny-glob" ) ;
8
- const { default : openapiTS } = require ( "../dist/cjs/index.js" ) ;
9
-
10
- const cli = meow (
11
- `Usage
3
+ import fs from "fs" ;
4
+ import path from "path" ;
5
+ import glob from "tiny-glob" ;
6
+ import parser from "yargs-parser" ;
7
+ import openapiTS from "../dist/esm/index.js" ;
8
+
9
+ const GREEN = "\u001b[32m" ;
10
+ const BOLD = "\u001b[1m" ;
11
+ const RESET = "\u001b[0m" ;
12
+
13
+ const HELP = `Usage
12
14
$ openapi-typescript [input] [options]
13
15
14
16
Options
@@ -24,54 +26,7 @@ Options
24
26
--prettier-config, -c (optional) specify path to Prettier config file
25
27
--raw-schema (optional) Parse as partial schema (raw components)
26
28
--version (optional) Force schema parsing version
27
- ` ,
28
- {
29
- flags : {
30
- output : {
31
- type : "string" ,
32
- alias : "o" ,
33
- } ,
34
- auth : {
35
- type : "string" ,
36
- } ,
37
- headersObject : {
38
- type : "string" ,
39
- alias : "h" ,
40
- } ,
41
- header : {
42
- type : "string" ,
43
- alias : "x" ,
44
- isMultiple : true ,
45
- } ,
46
- httpMethod : {
47
- type : "string" ,
48
- alias : "m" ,
49
- default : "GET" ,
50
- } ,
51
- immutableTypes : {
52
- type : "boolean" ,
53
- alias : "it" ,
54
- } ,
55
- defaultNonNullable : {
56
- type : "boolean" ,
57
- } ,
58
- additionalProperties : {
59
- type : "boolean" ,
60
- alias : "ap" ,
61
- } ,
62
- prettierConfig : {
63
- type : "string" ,
64
- alias : "c" ,
65
- } ,
66
- rawSchema : {
67
- type : "boolean" ,
68
- } ,
69
- version : {
70
- type : "number" ,
71
- } ,
72
- } ,
73
- }
74
- ) ;
29
+ ` ;
75
30
76
31
const OUTPUT_FILE = "FILE" ;
77
32
const OUTPUT_STDOUT = "STDOUT" ;
@@ -80,21 +35,42 @@ const timeStart = process.hrtime();
80
35
81
36
function errorAndExit ( errorMessage ) {
82
37
process . exitCode = 1 ; // needed for async functions
83
- throw new Error ( red ( errorMessage ) ) ;
38
+ throw new Error ( errorMessage ) ;
84
39
}
85
40
41
+ const [ , , input , ...args ] = process . argv ;
42
+ const flags = parser ( args , {
43
+ array : [ "header" ] ,
44
+ boolean : [ "defaultNonNullable" , "immutableTypes" , "rawSchema" ] ,
45
+ number : [ "version" ] ,
46
+ string : [ "auth" , "header" , "headersObject" , "httpMethod" , "prettierConfig" ] ,
47
+ alias : {
48
+ additionalProperties : [ "ap" ] ,
49
+ header : [ "x" ] ,
50
+ headersObject : [ "h" ] ,
51
+ httpMethod : [ "m" ] ,
52
+ immutableTypes : [ "it" ] ,
53
+ output : [ "o" ] ,
54
+ prettierConfig : [ "c" ] ,
55
+ } ,
56
+ default : {
57
+ httpMethod : "GET" ,
58
+ } ,
59
+ } ) ;
60
+
86
61
async function generateSchema ( pathToSpec ) {
87
- const output = cli . flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
62
+ const output = flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
88
63
89
64
// Parse incoming headers from CLI flags
90
65
let httpHeaders = { } ;
66
+
91
67
// prefer --headersObject if specified
92
- if ( cli . flags . headersObject ) {
93
- httpHeaders = JSON . parse ( cli . flags . headersObject ) ; // note: this will generate a recognizable error for the user to act on
68
+ if ( flags . headersObject ) {
69
+ httpHeaders = JSON . parse ( flags . headersObject ) ; // note: this will generate a recognizable error for the user to act on
94
70
}
95
71
// otherwise, parse --header
96
- else if ( Array . isArray ( cli . flags . header ) ) {
97
- cli . flags . header . forEach ( ( header ) => {
72
+ else if ( Array . isArray ( flags . header ) ) {
73
+ flags . header . forEach ( ( header ) => {
98
74
const firstColon = header . indexOf ( ":" ) ;
99
75
const k = header . substring ( 0 , firstColon ) . trim ( ) ;
100
76
const v = header . substring ( firstColon + 1 ) . trim ( ) ;
@@ -104,21 +80,21 @@ async function generateSchema(pathToSpec) {
104
80
105
81
// generate schema
106
82
const result = await openapiTS ( pathToSpec , {
107
- additionalProperties : cli . flags . additionalProperties ,
108
- auth : cli . flags . auth ,
109
- defaultNonNullable : cli . flags . defaultNonNullable ,
110
- immutableTypes : cli . flags . immutableTypes ,
111
- prettierConfig : cli . flags . prettierConfig ,
112
- rawSchema : cli . flags . rawSchema ,
83
+ additionalProperties : flags . additionalProperties ,
84
+ auth : flags . auth ,
85
+ defaultNonNullable : flags . defaultNonNullable ,
86
+ immutableTypes : flags . immutableTypes ,
87
+ prettierConfig : flags . prettierConfig ,
88
+ rawSchema : flags . rawSchema ,
113
89
silent : output === OUTPUT_STDOUT ,
114
- version : cli . flags . version ,
90
+ version : flags . version ,
115
91
httpHeaders,
116
- httpMethod : cli . flags . httpMethod ,
92
+ httpMethod : flags . httpMethod ,
117
93
} ) ;
118
94
119
95
// output
120
96
if ( output === OUTPUT_FILE ) {
121
- let outputFilePath = path . resolve ( process . cwd ( ) , cli . flags . output ) ; // note: may be directory
97
+ let outputFilePath = path . resolve ( process . cwd ( ) , flags . output ) ; // note: may be directory
122
98
const isDir = fs . existsSync ( outputFilePath ) && fs . lstatSync ( outputFilePath ) . isDirectory ( ) ;
123
99
if ( isDir ) {
124
100
const filename = pathToSpec . replace ( new RegExp ( `${ path . extname ( pathToSpec ) } $` ) , ".ts" ) ;
@@ -129,7 +105,7 @@ async function generateSchema(pathToSpec) {
129
105
130
106
const timeEnd = process . hrtime ( timeStart ) ;
131
107
const time = timeEnd [ 0 ] + Math . round ( timeEnd [ 1 ] / 1e6 ) ;
132
- console . log ( green ( `🚀 ${ pathToSpec } -> ${ bold ( outputFilePath ) } [${ time } ms]` ) ) ;
108
+ console . log ( `🚀 ${ GREEN } ${ pathToSpec } -> ${ BOLD } ${ outputFilePath } ${ RESET } ${ GREEN } [${ time } ms]${ RESET } ` ) ;
133
109
} else {
134
110
process . stdout . write ( result ) ;
135
111
// if stdout, (still) don’t log anything to console!
@@ -139,21 +115,27 @@ async function generateSchema(pathToSpec) {
139
115
}
140
116
141
117
async function main ( ) {
142
- let output = cli . flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
143
- const pathToSpec = cli . input [ 0 ] ;
118
+ if ( flags . help ) {
119
+ console . info ( HELP ) ;
120
+ process . exit ( 0 ) ;
121
+ }
122
+
123
+ let output = flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
124
+ const pathToSpec = input ;
144
125
145
126
if ( output === OUTPUT_FILE ) {
146
- console . info ( bold ( `✨ openapi-typescript ${ require ( "../package.json" ) . version } ` ) ) ; // only log if we’re NOT writing to stdout
127
+ const packageJSON = JSON . parse ( fs . readFileSync ( new URL ( "../package.json" , import . meta. url ) , "utf8" ) ) ;
128
+ console . info ( `✨ ${ BOLD } openapi-typescript ${ packageJSON . version } ${ RESET } ` ) ; // only log if we’re NOT writing to stdout
147
129
}
148
130
149
131
// error: --raw-schema
150
- if ( cli . flags . rawSchema && ! cli . flags . version ) {
132
+ if ( flags . rawSchema && ! flags . version ) {
151
133
throw new Error ( `--raw-schema requires --version flag` ) ;
152
134
}
153
135
154
136
// handle remote schema, exit
155
137
if ( / ^ h t t p s ? : \/ \/ / . test ( pathToSpec ) ) {
156
- if ( output !== "." && output === OUTPUT_FILE ) fs . mkdirSync ( path . dirname ( cli . flags . output ) , { recursive : true } ) ;
138
+ if ( output !== "." && output === OUTPUT_FILE ) fs . mkdirSync ( path . dirname ( flags . output ) , { recursive : true } ) ;
157
139
await generateSchema ( pathToSpec ) ;
158
140
return ;
159
141
}
@@ -168,15 +150,15 @@ async function main() {
168
150
}
169
151
170
152
// error: tried to glob output to single file
171
- if ( isGlob && output === OUTPUT_FILE && fs . existsSync ( cli . flags . output ) && fs . lstatSync ( cli . flags . output ) . isFile ( ) ) {
172
- errorAndExit ( `❌ Expected directory for --output if using glob patterns. Received "${ cli . flags . output } ".` ) ;
153
+ if ( isGlob && output === OUTPUT_FILE && fs . existsSync ( flags . output ) && fs . lstatSync ( flags . output ) . isFile ( ) ) {
154
+ errorAndExit ( `❌ Expected directory for --output if using glob patterns. Received "${ flags . output } ".` ) ;
173
155
}
174
156
175
157
// generate schema(s) in parallel
176
158
await Promise . all (
177
159
inputSpecPaths . map ( async ( specPath ) => {
178
- if ( cli . flags . output !== "." && output === OUTPUT_FILE ) {
179
- let outputDir = path . resolve ( process . cwd ( ) , cli . flags . output ) ;
160
+ if ( flags . output !== "." && output === OUTPUT_FILE ) {
161
+ let outputDir = path . resolve ( process . cwd ( ) , flags . output ) ;
180
162
if ( isGlob ) {
181
163
outputDir = path . resolve ( outputDir , path . dirname ( specPath ) ) ; // globs: use output dir + spec dir
182
164
} else {
0 commit comments