11#!/usr/bin/env node
22
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
1214 $ openapi-typescript [input] [options]
1315
1416Options
@@ -24,54 +26,7 @@ Options
2426 --prettier-config, -c (optional) specify path to Prettier config file
2527 --raw-schema (optional) Parse as partial schema (raw components)
2628 --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+ ` ;
7530
7631const OUTPUT_FILE = "FILE" ;
7732const OUTPUT_STDOUT = "STDOUT" ;
@@ -80,21 +35,42 @@ const timeStart = process.hrtime();
8035
8136function errorAndExit ( errorMessage ) {
8237 process . exitCode = 1 ; // needed for async functions
83- throw new Error ( red ( errorMessage ) ) ;
38+ throw new Error ( errorMessage ) ;
8439}
8540
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+
8661async 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
8863
8964 // Parse incoming headers from CLI flags
9065 let httpHeaders = { } ;
66+
9167 // 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
9470 }
9571 // 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 ) => {
9874 const firstColon = header . indexOf ( ":" ) ;
9975 const k = header . substring ( 0 , firstColon ) . trim ( ) ;
10076 const v = header . substring ( firstColon + 1 ) . trim ( ) ;
@@ -104,21 +80,21 @@ async function generateSchema(pathToSpec) {
10480
10581 // generate schema
10682 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 ,
11389 silent : output === OUTPUT_STDOUT ,
114- version : cli . flags . version ,
90+ version : flags . version ,
11591 httpHeaders,
116- httpMethod : cli . flags . httpMethod ,
92+ httpMethod : flags . httpMethod ,
11793 } ) ;
11894
11995 // output
12096 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
12298 const isDir = fs . existsSync ( outputFilePath ) && fs . lstatSync ( outputFilePath ) . isDirectory ( ) ;
12399 if ( isDir ) {
124100 const filename = pathToSpec . replace ( new RegExp ( `${ path . extname ( pathToSpec ) } $` ) , ".ts" ) ;
@@ -129,7 +105,7 @@ async function generateSchema(pathToSpec) {
129105
130106 const timeEnd = process . hrtime ( timeStart ) ;
131107 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 } ` ) ;
133109 } else {
134110 process . stdout . write ( result ) ;
135111 // if stdout, (still) don’t log anything to console!
@@ -139,21 +115,27 @@ async function generateSchema(pathToSpec) {
139115}
140116
141117async 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 ;
144125
145126 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
147129 }
148130
149131 // error: --raw-schema
150- if ( cli . flags . rawSchema && ! cli . flags . version ) {
132+ if ( flags . rawSchema && ! flags . version ) {
151133 throw new Error ( `--raw-schema requires --version flag` ) ;
152134 }
153135
154136 // handle remote schema, exit
155137 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 } ) ;
157139 await generateSchema ( pathToSpec ) ;
158140 return ;
159141 }
@@ -168,15 +150,15 @@ async function main() {
168150 }
169151
170152 // 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 } ".` ) ;
173155 }
174156
175157 // generate schema(s) in parallel
176158 await Promise . all (
177159 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 ) ;
180162 if ( isGlob ) {
181163 outputDir = path . resolve ( outputDir , path . dirname ( specPath ) ) ; // globs: use output dir + spec dir
182164 } else {
0 commit comments