@@ -4,6 +4,7 @@ const fs = require("fs");
4
4
const { bold, green, red } = require ( "kleur" ) ;
5
5
const path = require ( "path" ) ;
6
6
const meow = require ( "meow" ) ;
7
+ const glob = require ( "tiny-glob" ) ;
7
8
const { default : openapiTS } = require ( "../dist/cjs/index.js" ) ;
8
9
const { loadSpec } = require ( "./loaders" ) ;
9
10
@@ -52,36 +53,31 @@ Options
52
53
}
53
54
) ;
54
55
56
+ const OUTPUT_FILE = "FILE" ;
57
+ const OUTPUT_STDOUT = "STDOUT" ;
58
+
55
59
const timeStart = process . hrtime ( ) ;
56
60
57
- async function main ( ) {
58
- let output = "FILE" ; // FILE or STDOUT
59
- const pathToSpec = cli . input [ 0 ] ;
61
+ function errorAndExit ( errorMessage ) {
62
+ process . exitCode = 1 ; // needed for async functions
63
+ throw new Error ( red ( errorMessage ) ) ;
64
+ }
60
65
61
- // 0. setup
62
- if ( ! cli . flags . output ) {
63
- output = "STDOUT" ; // if --output not specified, fall back to stdout
64
- }
65
- if ( output === "FILE" ) {
66
- console . info ( bold ( `✨ openapi-typescript ${ require ( "../package.json" ) . version } ` ) ) ; // only log if we’re NOT writing to stdout
67
- }
68
- if ( cli . flags . rawSchema && ! cli . flags . version ) {
69
- throw new Error ( `--raw-schema requires --version flag` ) ;
70
- }
66
+ async function generateSchema ( pathToSpec ) {
67
+ const output = cli . flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
71
68
72
- // 1. input
69
+ // load spec
73
70
let spec = undefined ;
74
71
try {
75
72
spec = await loadSpec ( pathToSpec , {
76
73
auth : cli . flags . auth ,
77
- log : output !== "STDOUT" ,
74
+ log : output !== OUTPUT_STDOUT ,
78
75
} ) ;
79
76
} catch ( err ) {
80
- process . exitCode = 1 ; // needed for async functions
81
- throw new Error ( red ( `❌ ${ err } ` ) ) ;
77
+ errorAndExit ( `❌ ${ err } ` ) ;
82
78
}
83
79
84
- // 2. generate schema (the main part!)
80
+ // generate schema
85
81
const result = openapiTS ( spec , {
86
82
auth : cli . flags . auth ,
87
83
additionalProperties : cli . flags . additionalProperties ,
@@ -91,11 +87,54 @@ async function main() {
91
87
version : cli . flags . version ,
92
88
} ) ;
93
89
94
- // 3. output
95
- if ( output === "FILE" ) {
96
- // output option 1: file
97
- const outputFile = path . resolve ( process . cwd ( ) , cli . flags . output ) ;
90
+ // output
91
+ if ( output === OUTPUT_FILE ) {
92
+ let outputFile = path . resolve ( process . cwd ( ) , cli . flags . output ) ;
93
+
94
+ // decide filename if outputFile is a directory
95
+ if ( fs . existsSync ( outputFile ) && fs . lstatSync ( outputFile ) . isDirectory ( ) ) {
96
+ const basename = path . basename ( pathToSpec ) . split ( "." ) . slice ( 0 , - 1 ) . join ( "." ) + ".ts" ;
97
+ outputFile = path . resolve ( outputFile , basename ) ;
98
+ }
99
+
100
+ fs . writeFileSync ( outputFile , result , "utf8" ) ;
101
+
102
+ const timeEnd = process . hrtime ( timeStart ) ;
103
+ const time = timeEnd [ 0 ] + Math . round ( timeEnd [ 1 ] / 1e6 ) ;
104
+ console . log ( green ( `🚀 ${ pathToSpec } -> ${ bold ( outputFile ) } [${ time } ms]` ) ) ;
105
+ } else {
106
+ process . stdout . write ( result ) ;
107
+ }
108
+
109
+ return result ;
110
+ }
111
+
112
+ async function main ( ) {
113
+ const output = cli . flags . output ? OUTPUT_FILE : OUTPUT_STDOUT ; // FILE or STDOUT
114
+ const pathToSpec = cli . input [ 0 ] ;
115
+ const inputSpecPaths = await glob ( pathToSpec , { filesOnly : true } ) ;
116
+
117
+ if ( output === OUTPUT_FILE ) {
118
+ console . info ( bold ( `✨ openapi-typescript ${ require ( "../package.json" ) . version } ` ) ) ; // only log if we’re NOT writing to stdout
119
+ }
120
+
121
+ if ( cli . flags . rawSchema && ! cli . flags . version ) {
122
+ throw new Error ( `--raw-schema requires --version flag` ) ;
123
+ }
124
+
125
+ if ( / ^ h t t p s ? : \/ \/ / . test ( pathToSpec ) ) {
126
+ // handle remote resource input and exit
127
+ return await generateSchema ( pathToSpec ) ;
128
+ }
129
+
130
+ // no matches for glob
131
+ if ( inputSpecPaths . length === 0 ) {
132
+ errorAndExit (
133
+ `❌ Could not find any spec files matching the provided input path glob. Please check that the path is correct.`
134
+ ) ;
135
+ }
98
136
137
+ if ( output === OUTPUT_FILE ) {
99
138
// recursively create parent directories if they don’t exist
100
139
const parentDirs = cli . flags . output . split ( path . sep ) ;
101
140
for ( var i = 1 ; i < parentDirs . length ; i ++ ) {
@@ -104,15 +143,19 @@ async function main() {
104
143
fs . mkdirSync ( dir ) ;
105
144
}
106
145
}
146
+ }
107
147
108
- fs . writeFileSync ( outputFile , result , "utf8" ) ;
148
+ // if there are multiple specs, ensure that output is a directory
149
+ if ( inputSpecPaths . length > 1 && output === OUTPUT_FILE && ! fs . lstatSync ( cli . flags . output ) . isDirectory ( ) ) {
150
+ errorAndExit (
151
+ `❌ When specifying a glob matching multiple input specs, you must specify a directory for generated type definitions.`
152
+ ) ;
153
+ }
109
154
110
- const timeEnd = process . hrtime ( timeStart ) ;
111
- const time = timeEnd [ 0 ] + Math . round ( timeEnd [ 1 ] / 1e6 ) ;
112
- console . log ( green ( `🚀 ${ pathToSpec } -> ${ bold ( cli . flags . output ) } [${ time } ms]` ) ) ;
113
- } else {
114
- // output option 2: stdout
115
- process . stdout . write ( result ) ;
155
+ let result = "" ;
156
+ for ( const specPath of inputSpecPaths ) {
157
+ // append result returned for each spec
158
+ result += await generateSchema ( specPath ) ;
116
159
}
117
160
118
161
return result ;
0 commit comments