-
-
Notifications
You must be signed in to change notification settings - Fork 532
Feature add custom http headers #764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
84706cc
bf9f06c
e0cbe7f
2acdb2e
c866a0a
a9c0ff6
1e1bfc7
7c55976
22402b1
51ef119
7a4557c
b5e2490
beae345
a759e41
eadf75d
53df7cb
0945189
5cbdb05
94b2859
84e0ab3
9c7d489
4d1d74b
9a2e530
a31eef4
24db309
bd27e94
b28b060
6d5e08f
12454dc
9d79d08
f8f419b
f9735d8
e974bfd
1b13ccf
4d9d18c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,17 @@ const path = require("path"); | |
const glob = require("tiny-glob"); | ||
const { default: openapiTS } = require("../dist/cjs/index.js"); | ||
|
||
let cli = meow( | ||
const cli = meow( | ||
`Usage | ||
$ openapi-typescript [input] [options] | ||
|
||
Options | ||
--help display this | ||
--output, -o Specify output file (default: stdout) | ||
--auth (optional) Provide an authentication token for private URL | ||
--headersObject, -h (optional) Provide a JSON object as string of HTTP headers for remote schema request | ||
--header, -x (optional) Provide an array of or singular headers as an alternative to a JSON object. Each header must follow the key: value pattern | ||
--httpMethod, -m (optional) Provide the HTTP Verb/Method for fetching a schema from a remote URL | ||
--immutable-types, -it (optional) Generates immutable types (readonly properties and readonly array) | ||
--additional-properties, -ap (optional) Allow arbitrary properties for all schema objects without "additionalProperties: false" | ||
--default-non-nullable (optional) If a schema object has a default value set, don’t mark it as nullable | ||
|
@@ -31,6 +34,20 @@ Options | |
auth: { | ||
type: "string", | ||
}, | ||
headersObject: { | ||
type: "string", | ||
alias: "h", | ||
}, | ||
header: { | ||
type: "string", | ||
alias: "x", | ||
isMultiple: true, | ||
}, | ||
httpMethod: { | ||
type: "string", | ||
alias: "m", | ||
default: "GET", | ||
}, | ||
immutableTypes: { | ||
type: "boolean", | ||
alias: "it", | ||
|
@@ -69,6 +86,22 @@ function errorAndExit(errorMessage) { | |
async function generateSchema(pathToSpec) { | ||
const output = cli.flags.output ? OUTPUT_FILE : OUTPUT_STDOUT; // FILE or STDOUT | ||
|
||
// Parse incoming headers from CLI flags | ||
let httpHeaders = {}; | ||
// prefer --headersObject if specified | ||
if (cli.flags.headersObject) { | ||
httpHeaders = JSON.parse(cli.flags.headersObject); // note: this will generate a recognizable error for the user to act on | ||
} | ||
// otherwise, parse --header | ||
else if (Array.isArray(cli.flags.header)) { | ||
cli.flags.header.forEach((header) => { | ||
const firstColon = header.indexOf(":"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was using a RegEx instead ( |
||
const k = header.substring(0, firstColon).trim(); | ||
const v = header.substring(firstColon + 1).trim(); | ||
httpHeaders[k] = v; | ||
}); | ||
} | ||
|
||
// generate schema | ||
const result = await openapiTS(pathToSpec, { | ||
additionalProperties: cli.flags.additionalProperties, | ||
|
@@ -79,22 +112,24 @@ async function generateSchema(pathToSpec) { | |
rawSchema: cli.flags.rawSchema, | ||
silent: output === OUTPUT_STDOUT, | ||
version: cli.flags.version, | ||
httpHeaders, | ||
httpMethod: cli.flags.httpMethod, | ||
}); | ||
|
||
// output | ||
if (output === OUTPUT_FILE) { | ||
let outputFile = path.resolve(process.cwd(), cli.flags.output); // note: may be directory | ||
const isDir = fs.existsSync(outputFile) && fs.lstatSync(outputFile).isDirectory(); | ||
let outputFilePath = path.resolve(process.cwd(), cli.flags.output); // note: may be directory | ||
const isDir = fs.existsSync(outputFilePath) && fs.lstatSync(outputFilePath).isDirectory(); | ||
if (isDir) { | ||
const filename = pathToSpec.replace(new RegExp(`${path.extname(pathToSpec)}$`), ".ts"); | ||
outputFile = path.join(outputFile, filename); | ||
outputFilePath = path.join(outputFilePath, filename); | ||
} | ||
|
||
await fs.promises.writeFile(outputFile, result, "utf8"); | ||
await fs.promises.writeFile(outputFilePath, result, "utf8"); | ||
|
||
const timeEnd = process.hrtime(timeStart); | ||
const time = timeEnd[0] + Math.round(timeEnd[1] / 1e6); | ||
console.log(green(`🚀 ${pathToSpec} -> ${bold(outputFile)} [${time}ms]`)); | ||
console.log(green(`🚀 ${pathToSpec} -> ${bold(outputFilePath)} [${time}ms]`)); | ||
} else { | ||
process.stdout.write(result); | ||
// if stdout, (still) don’t log anything to console! | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ export interface OpenAPI3 { | |
}; | ||
} | ||
|
||
export type Headers = Record<string, string>; | ||
|
||
export interface HeaderObject { | ||
// note: this extends ParameterObject, minus "name" & "in" | ||
type?: string; // required | ||
|
@@ -134,6 +136,21 @@ export interface SwaggerToTSOptions { | |
silent?: boolean; | ||
/** (optional) OpenAPI version. Must be present if parsing raw schema */ | ||
version?: number; | ||
/** | ||
* (optional) List of HTTP headers that will be sent with the fetch request to a remote schema. This is | ||
* in addition to the authorization header. In some cases, servers require headers such as Accept: application/json | ||
* or Accept: text/yaml to be sent in order to figure out how to properly fetch the OpenAPI/Swagger document as code. | ||
* These headers will only be sent in the case that the schema URL protocol is of type http or https. | ||
*/ | ||
httpHeaders?: Headers; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an opinionated change, but in the previous PR we allowed Instead, I opted to go with just a plain JS object for headers because that’s what gets passed to |
||
/** | ||
* HTTP verb used to fetch the schema from a remote server. This is only applied | ||
* when the schema is a string and has the http or https protocol present. By default, | ||
* the request will use the HTTP GET method to fetch the schema from the server. | ||
* | ||
* @default {string} GET | ||
*/ | ||
httpMethod?: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar approach: rather than maintain a discriminated union of all valid HTTP methods, I opted instead to allow a simple Again, I know this was not the author’s original intent, and I respect their level of quality! But I feel this was one of many details which just added on a lot of maintenance and potential typing bugs without much benefit to the average user. |
||
} | ||
|
||
/** Context passed to all submodules */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor change here: we had a
getCLISchemaHeadersJSON()
function that did a lot of setup aroundJSON.parse()
, and in the end obscured the error from the user. Instead, I’d like to expose the error to the user so it’s more clear what’s not parsing correctly.