openapi-format
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -8,2 +8,3 @@ #!/usr/bin/env node | ||
const program = require('commander'); | ||
const {infoTable, infoOut, logOut, debugOut} = require("../util-log-output"); | ||
@@ -24,3 +25,3 @@ // CLI Helper - change verbosity | ||
.option('--no-sort', 'dont sort the OpenAPI file') | ||
.option('--sortComponentsFile <sortComponentsFile>', 'The file with components to sort alfabehtically') | ||
.option('--sortComponentsFile <sortComponentsFile>', 'The file with components to sort alphabetically') | ||
.option('--lineWidth <lineWidth>', 'max line width of YAML output', -1) | ||
@@ -38,3 +39,3 @@ .option('--rename <oaTitle>', 'overwrite the title in the OpenAPI document.') | ||
) { | ||
stdout.write("\n"); | ||
process.stdout.write("\n"); | ||
program.outputHelp(); | ||
@@ -48,17 +49,19 @@ } | ||
async function run(oaFile, options) { | ||
// Helper function to display info message, depending on the verbose level | ||
function info(msg) { | ||
if (options.verbose >= 1) { | ||
console.warn(msg); | ||
} | ||
} | ||
// General variables | ||
let outputLogOptions = '' | ||
let outputLogFiltered = '' | ||
let cliLog = {}; | ||
const consoleLine = process.stdout.columns ? '='.repeat(process.stdout.columns) : '='.repeat(80) | ||
if (!oaFile) { | ||
console.error('Provide file to OpenAPI document'); | ||
console.error('Please provide a file path for the OpenAPI document'); | ||
// process.exit(1) | ||
return; | ||
} | ||
infoOut(`${consoleLine}`); // LOG - horizontal rule | ||
infoOut(`OpenAPI-Format CLI settings:`) // LOG - config file | ||
// apply options from config file if present | ||
if (options && options.configFile) { | ||
info('Config File: ' + options.configFile) | ||
try { | ||
@@ -72,2 +75,3 @@ let configFileOptions = {} | ||
} | ||
infoOut(`- Config file:\t\t${options.configFile}`) // LOG - config file | ||
options = Object.assign({}, options, configFileOptions); | ||
@@ -82,9 +86,8 @@ } catch (err) { | ||
if (options.verbose >= 1 || options.verbose === true) { | ||
console.table(options); | ||
} | ||
// LOG - Render info table with options | ||
outputLogOptions = infoTable(options, options.verbose) | ||
// apply ordering by priority file if present | ||
if (options && options.sort === true) { | ||
info('Sort File: ' + options.sortFile) | ||
infoOut(`- Sort file:\t\t${options.sortFile}`) // LOG - sort file | ||
try { | ||
@@ -97,3 +100,3 @@ let sortOptions = {sortSet: {}} | ||
} catch (err) { | ||
console.error('\x1b[31m', 'Sort file error - no such file or directory "' + options.sortFile + '"') | ||
console.error('\x1b[31m', `Sort file error - no such file or directory "${options.sortFile}"`) | ||
if (options.verbose >= 1) { | ||
@@ -107,3 +110,3 @@ console.error(err) | ||
if (options && options.filterFile) { | ||
info('Filter File: ' + options.filterFile) | ||
infoOut(`- Filter file:\t\t${options.filterFile}`) // LOG - Filter file | ||
try { | ||
@@ -115,3 +118,3 @@ let filterOptions = {filterSet: {}} | ||
} catch (err) { | ||
console.error('\x1b[31m', 'Filter file error - no such file or directory "' + options.filterFile + '"') | ||
console.error('\x1b[31m', `Filter file error - no such file or directory "${options.filterFile}"`) | ||
if (options.verbose >= 1) { | ||
@@ -125,3 +128,3 @@ console.error(err) | ||
if (options && options.sortComponentsFile) { | ||
info('Sort Components File: ' + options.sortComponentsFile) | ||
infoOut(`- Sort Components file:\t ${options.sortComponentsFile}`) // LOG - Sort file | ||
try { | ||
@@ -133,3 +136,3 @@ let sortComponentsOptions = {sortComponentsSet: {}} | ||
} catch (err) { | ||
console.error('\x1b[31m', 'Sort Components file error - no such file or directory "' + options.sortComponentsFile + '"') | ||
console.error('\x1b[31m', `Sort Components file error - no such file or directory "${options.sortComponentsFile}"`) | ||
if (options.verbose >= 1) { | ||
@@ -141,3 +144,3 @@ console.error(err) | ||
info('Input file: ' + oaFile) | ||
infoOut(`- Input file:\t\t${oaFile}`) // LOG - Input file | ||
@@ -151,3 +154,6 @@ // Get | ||
if (options.filterSet) { | ||
res = await openapiFormat.openapiFilter(res, options); | ||
const resFilter = await openapiFormat.openapiFilter(res, options); | ||
cliLog.unusedComp = resFilter?.resultData?.unusedComp; | ||
outputLogFiltered = `filtered & `; | ||
res = resFilter.data; | ||
} | ||
@@ -157,3 +163,4 @@ | ||
if (options.sort === true) { | ||
res = await openapiFormat.openapiSort(res, options); | ||
const resFormat = await openapiFormat.openapiSort(res, options); | ||
if (resFormat.data) res = resFormat.data | ||
} | ||
@@ -163,4 +170,5 @@ | ||
if (options.rename) { | ||
res = await openapiFormat.openapiRename(res, options); | ||
info('OpenAPI title renamed to: "' + options.rename + '"') | ||
const resRename = await openapiFormat.openapiRename(res, options); | ||
if (resRename.data) res = resRename.data | ||
debugOut(`- OAS.title renamed to: "${options.rename}"`, options.verbose) // LOG - Rename title | ||
} | ||
@@ -172,3 +180,3 @@ | ||
// o = jy.dump(res,{lineWidth:-1}); | ||
let lineWidth = (options.lineWidth && options.lineWidth === -1 ? Infinity: options.lineWidth) || Infinity; | ||
let lineWidth = (options.lineWidth && options.lineWidth === -1 ? Infinity : options.lineWidth) || Infinity; | ||
o = sy.safeStringify(res, {lineWidth: lineWidth}); | ||
@@ -180,5 +188,5 @@ } | ||
fs.writeFileSync(options.output, o, 'utf8'); | ||
info('Output file: ' + options.output) | ||
infoOut(`- Output file:\t\t${options.output}`) // LOG - config file | ||
} catch (err) { | ||
console.error('\x1b[31m', 'Output file error - no such file or directory "' + options.output + '"') | ||
console.error('\x1b[31m', `Output file error - no such file or directory "${options.output}"`) | ||
if (options.verbose >= 1) { | ||
@@ -192,3 +200,33 @@ console.error(err) | ||
info('\n✅ OpenAPI was formatted successfully') | ||
if (outputLogOptions) { //&& options.verbose > 2) { | ||
// Show options | ||
debugOut(`${consoleLine}\n`, options.verbose); // LOG - horizontal rule | ||
debugOut(`OpenAPI-Format CLI options:`, options.verbose) // LOG - config file | ||
debugOut(`${outputLogOptions}`, options.verbose); | ||
} | ||
// Show unused components | ||
if (cliLog?.unusedComp) { | ||
// List unused component | ||
logOut(`${consoleLine}`, options.verbose); // LOG - horizontal rule | ||
logOut(`Removed unused components:`, options.verbose); // LOG - horizontal rule | ||
const unusedComp = cliLog.unusedComp | ||
const keys = Object.keys(unusedComp, options.verbose) | ||
let count = 0 | ||
keys.map((comp) => { | ||
if (unusedComp?.[comp].length > 0) { | ||
unusedComp[comp].forEach(value => { | ||
const spacer = (comp === 'requestBodies' ? `\t` : `\t\t`); | ||
logOut(`- components/${comp}${spacer} "${value}"`, options.verbose); | ||
count++; | ||
}); | ||
} | ||
}); | ||
logOut(`Total components removed: ${count}`, options.verbose); | ||
} | ||
// Final result | ||
infoOut(`${consoleLine}\n`); // LOG - horizontal rule | ||
infoOut(`✅ OpenAPI ${outputLogFiltered}formatted successfully\n`, 99) // LOG - success message | ||
infoOut(`${consoleLine}\n`); // LOG - horizontal rule | ||
} |
@@ -210,3 +210,5 @@ #!/usr/bin/env node | ||
} | ||
return jsonObj; | ||
// Return result object | ||
return {data: jsonObj, resultData: {}} | ||
} | ||
@@ -226,2 +228,4 @@ | ||
const httpVerbs = ["get", "post", "put", "patch", "delete"]; | ||
const fixedFlags = ["x-openapi-format-filter"] | ||
options.unusedDepth = options.unusedDepth || 0; | ||
@@ -232,3 +236,3 @@ // Merge object filters | ||
const filterOperations = [...filterSet.operations]; | ||
const filterProps = [...filterSet.operationIds, ...filterSet.flags]; | ||
const filterProps = [...filterSet.operationIds, ...filterSet.flags, ...fixedFlags]; | ||
const stripFlags = [...filterSet.stripFlags]; | ||
@@ -240,61 +244,64 @@ const stripUnused = [...filterSet.unusedComponents]; | ||
const filterFlagValues = [...filterSet.flagValues]; | ||
const filterFlagHash = filterFlagValues.map(o => (JSON.stringify(o))); | ||
// Initiate components tracking | ||
const compSchemas = {} | ||
const compResponses = {} | ||
const compParams = {} | ||
const compExamples = {} | ||
const compRequestBodies = {} | ||
const compHeaders = {} | ||
const comps = { | ||
schemas: {}, | ||
responses: {}, | ||
parameters: {}, | ||
examples: {}, | ||
requestBodies: {}, | ||
headers: {}, | ||
meta: {total: 0} | ||
} | ||
// Prepare unused components | ||
let unusedComp = { | ||
schemas: [], | ||
responses: [], | ||
parameters: [], | ||
examples: [], | ||
requestBodies: [], | ||
headers: [], | ||
meta: {total: 0} | ||
} | ||
// Use options.unusedComp to collect unused components during multiple recursion | ||
if (!options.unusedComp) options.unusedComp = JSON.parse(JSON.stringify(unusedComp)); | ||
let debugFilterStep = '' // uncomment // debugFilterStep below to see which sort part is triggered | ||
traverse(jsonObj).forEach(function (node) { | ||
// Register components | ||
// Register components presence | ||
if (this?.parent?.parent?.key === 'components') { | ||
if (this?.parent?.key === 'schemas') { | ||
compSchemas[this.key] = {...compSchemas[this.key], present: true}; | ||
if (this?.parent?.key && comps[this.parent.key]) { | ||
comps[this.parent.key][this.key] = {...comps[this.parent.key][this.key], present: true}; | ||
comps.meta.total = comps.meta.total++; | ||
} | ||
if (this?.parent?.key === 'responses') { | ||
compResponses[this.key] = {...compResponses[this.key], present: true}; | ||
} | ||
if (this?.parent?.key === 'parameters') { | ||
compParams[this.key] = {...compParams[this.key], present: true}; | ||
} | ||
if (this?.parent?.key === 'examples') { | ||
compExamples[this.key] = {...compExamples[this.key], present: true}; | ||
} | ||
if (this?.parent?.key === 'requestBodies') { | ||
compRequestBodies[this.key] = {...compRequestBodies[this.key], present: true}; | ||
} | ||
if (this?.parent?.key === 'headers') { | ||
compHeaders[this.key] = {...compHeaders[this.key], present: true}; | ||
} | ||
} | ||
// Register component/schemas usage | ||
// Register components usage | ||
if (this?.key === '$ref') { | ||
if (node.startsWith('#/components/schemas/')) { | ||
const compSchema = node.replace('#/components/schemas/', ''); | ||
compSchemas[compSchema] = {...compSchemas[compSchema], used: true}; | ||
comps.schemas[compSchema] = {...comps.schemas[compSchema], used: true}; | ||
} | ||
if (node.startsWith('#/components/responses/')) { | ||
const compResp = node.replace('#/components/responses/', ''); | ||
compResponses[compResp] = {...compResponses[compResp], used: true}; | ||
comps.responses[compResp] = {...comps.responses[compResp], used: true}; | ||
} | ||
if (node.startsWith('#/components/parameters/')) { | ||
const compParam = node.replace('#/components/parameters/', ''); | ||
compParams[compParam] = {...compParams[compParam], used: true}; | ||
comps.parameters[compParam] = {...comps.parameters[compParam], used: true}; | ||
} | ||
if (node.startsWith('#/components/examples/')) { | ||
const compExample = node.replace('#/components/examples/', ''); | ||
compExamples[compExample] = {...compExamples[compExample], used: true}; | ||
comps.examples[compExample] = {...comps.examples[compExample], used: true}; | ||
} | ||
if (node.startsWith('#/components/requestBodies/')) { | ||
const compRequestBody = node.replace('#/components/requestBodies/', ''); | ||
compRequestBodies[compRequestBody] = {...compRequestBodies[compRequestBody], used: true}; | ||
comps.requestBodies[compRequestBody] = {...comps.requestBodies[compRequestBody], used: true}; | ||
} | ||
if (node.startsWith('#/components/headers/')) { | ||
const compHeader = node.replace('#/components/headers/', ''); | ||
compHeaders[compHeader] = {...compHeaders[compHeader], used: true}; | ||
comps.headers[compHeader] = {...comps.headers[compHeader], used: true}; | ||
} | ||
@@ -330,6 +337,16 @@ } | ||
const itmObj = {[this.key]: node[i]}; | ||
if (filterFlagValues.some(item => JSON.stringify(item) === JSON.stringify(itmObj))) { | ||
// debugFilterStep = 'Filter - Single field - flagValues - array value' | ||
// Top parent has other nodes, so remove only targeted parent node of matching element | ||
this.parent.remove(); | ||
const itmObjHash = JSON.stringify(itmObj); | ||
if (filterFlagHash.some(filterFlag => filterFlag === itmObjHash)) { | ||
// ======================================================================== | ||
// HACK to overcome the issue with removing items from an array | ||
if (this?.parent?.parent.key === 'x-tagGroups') { | ||
// debugFilterStep = 'Filter -x-tagGroups - flagValues - array value' | ||
const tagGroup = this.parent.node | ||
tagGroup['x-openapi-format-filter'] = true | ||
this.parent.update(tagGroup) | ||
// ======================================================================== | ||
} else { | ||
// debugFilterStep = 'Filter - Single field - flagValues - array value' | ||
this.parent.remove(); | ||
} | ||
} | ||
@@ -352,6 +369,16 @@ } | ||
const itmObj = {[this.key]: node}; | ||
if (filterFlagValues.some(item => JSON.stringify(item) === JSON.stringify(itmObj))) { | ||
// debugFilterStep = 'Filter - Single field - flagValues - single value' | ||
// Top parent has other nodes, so remove only targeted parent node of matching element | ||
this.parent.remove(); | ||
const itmObjHash = JSON.stringify(itmObj); | ||
if (filterFlagHash.some(filterFlagHash => filterFlagHash === itmObjHash)) { | ||
// ======================================================================== | ||
// HACK to overcome the issue with removing items from an array | ||
if (this?.parent?.parent.key === 'x-tagGroups') { | ||
// debugFilterStep = 'Filter -x-tagGroups - flagValues - single value' | ||
const tagGroup = this.parent.node | ||
tagGroup['x-openapi-format-filter'] = true | ||
this.parent.update(tagGroup) | ||
// ======================================================================== | ||
} else { | ||
// debugFilterStep = 'Filter - Single field - flagValues - single value' | ||
this.parent.remove(); | ||
} | ||
} | ||
@@ -363,3 +390,2 @@ } | ||
// debugFilterStep = 'Filter - Single field - Tags/operationIds' | ||
// Top parent has other nodes, so remove only targeted parent node of matching element | ||
this.parent.remove(); | ||
@@ -389,57 +415,49 @@ } | ||
} | ||
// Filter out markdown comments in description fields | ||
if (this.key === 'description') { | ||
const lines = node.split('\n'); | ||
if (lines.length > 1) { | ||
const filtered = lines.filter(line => !line.startsWith('[comment]: <>')) | ||
const cleanDescription = filtered.join('\n'); | ||
this.update(cleanDescription) | ||
} | ||
} | ||
}); | ||
// Prepare unused components | ||
let unusedSchemas = [] | ||
let unusedResponses = [] | ||
let unusedParams = [] | ||
let unusedExamples = [] | ||
let unusedRequestBodies = [] | ||
let unusedHeaders = [] | ||
if (stripUnused.length > 0) { | ||
unusedSchemas = Object.keys(compSchemas).filter(key => !compSchemas[key]?.used); | ||
unusedResponses = Object.keys(compResponses).filter(key => !compResponses[key]?.used); | ||
unusedParams = Object.keys(compParams).filter(key => !compParams[key]?.used); | ||
unusedExamples = Object.keys(compExamples).filter(key => !compExamples[key]?.used); | ||
unusedRequestBodies = Object.keys(compRequestBodies).filter(key => !compRequestBodies[key]?.used); | ||
unusedHeaders = Object.keys(compHeaders).filter(key => !compHeaders[key]?.used); | ||
unusedComp.schemas = Object.keys(comps.schemas).filter(key => !comps.schemas[key]?.used); | ||
options.unusedComp.schemas = [...options.unusedComp.schemas, ...unusedComp.schemas]; | ||
unusedComp.responses = Object.keys(comps.responses).filter(key => !comps.responses[key]?.used); | ||
options.unusedComp.responses = [...options.unusedComp.responses, ...unusedComp.responses]; | ||
unusedComp.parameters = Object.keys(comps.parameters).filter(key => !comps.parameters[key]?.used); | ||
options.unusedComp.parameters = [...options.unusedComp.parameters, ...unusedComp.parameters]; | ||
unusedComp.examples = Object.keys(comps.examples).filter(key => !comps.examples[key]?.used); | ||
options.unusedComp.examples = [...options.unusedComp.examples, ...unusedComp.examples]; | ||
unusedComp.requestBodies = Object.keys(comps.requestBodies).filter(key => !comps.requestBodies[key]?.used); | ||
options.unusedComp.requestBodies = [...options.unusedComp.requestBodies, ...unusedComp.requestBodies]; | ||
unusedComp.headers = Object.keys(comps.headers).filter(key => !comps.headers[key]?.used); | ||
options.unusedComp.headers = [...options.unusedComp.headers, ...unusedComp.headers]; | ||
unusedComp.meta.total = unusedComp.schemas.length + unusedComp.responses.length + unusedComp.parameters.length + unusedComp.examples.length + unusedComp.requestBodies.length + unusedComp.headers.length | ||
} | ||
// if (options.verbose >= 1 || options.verbose === true) { | ||
// if (unusedSchemas.length > 0) console.log('- Removed unused components/schemas:\n', unusedSchemas.join(', ')) | ||
// if (unusedResponses.length > 0) console.log('- Removed unused components/responses:\n', unusedResponses.join(', ')) | ||
// if (unusedParams.length > 0) console.log('- Removed unused components/parameters:\n', unusedParams.join(', ')) | ||
// if (unusedExamples.length > 0) console.log('- Removed unused components/examples:\n', unusedExamples.join(', ')) | ||
// if (unusedRequestBodies.length > 0) console.log('- Removed unused components/requestBodies:\n', unusedRequestBodies.join(', ')) | ||
// if (unusedHeaders.length > 0) console.log('- Removed unused components/headers:\n', unusedHeaders.join(', ')) | ||
// } | ||
// Clean-up jsonObj | ||
traverse(jsonObj).forEach(function (node) { | ||
// Remove unused component/schemas | ||
// Remove unused component | ||
if (this.path[0] === 'components' && stripUnused.length > 0) { | ||
if (this.path[1] === 'schemas' && stripUnused.includes('schemas') && unusedSchemas.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/schemas' | ||
if (stripUnused.includes(this.path[1]) && unusedComp[this.path[1]].includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused components' | ||
this.delete(); | ||
} | ||
if (this.path[1] === 'responses' && stripUnused.includes('responses') && unusedResponses.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/responses' | ||
this.delete(); | ||
} | ||
// Filter out OpenApi.tags & OpenApi.x-tagGroups matching the fixedFlags | ||
if ((this?.key === 'tags' || this?.key === 'x-tagGroups') && this?.parent.key === undefined && Array.isArray(node)) { | ||
if (fixedFlags.length > 0) { | ||
debugFilterStep = 'Filter - tag/x-tagGroup - fixed flags' | ||
// Deep filter array of tag/x-tagGroup | ||
let oaTags = JSON.parse(JSON.stringify(node)); // Deep copy of the object | ||
const oaFilteredTags = oaTags.filter(item => !fixedFlags.some(i => (Object.keys(item).includes(i)))); | ||
this.update(oaFilteredTags); | ||
} | ||
if (this.path[1] === 'parameters' && stripUnused.includes('parameters') && unusedParams.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/parameters' | ||
this.delete(); | ||
} | ||
if (this.path[1] === 'examples' && stripUnused.includes('examples') && unusedExamples.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/examples' | ||
this.delete(); | ||
} | ||
if (this.path[1] === 'requestBodies' && stripUnused.includes('requestBodies') && unusedRequestBodies.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/requestBodies' | ||
this.delete(); | ||
} | ||
if (this.path[1] === 'headers' && stripUnused.includes('headers') && unusedHeaders.includes(this.key)) { | ||
// debugFilterStep = 'Filter - Remove unused component/headers' | ||
this.delete(); | ||
} | ||
} | ||
@@ -464,3 +482,12 @@ | ||
return jsonObj; | ||
// Recurse to strip any remaining unusedComp, to a maximum depth of 10 | ||
if (stripUnused.length > 0 && unusedComp.meta.total > 0 && options.unusedDepth <= 10) { | ||
options.unusedDepth++; | ||
const resultObj = openapiFilter(jsonObj, options); | ||
jsonObj = resultObj.data; | ||
unusedComp = JSON.parse(JSON.stringify(options.unusedComp)); | ||
} | ||
// Return result object | ||
return {data: jsonObj, resultData: {unusedComp: unusedComp}} | ||
} | ||
@@ -483,3 +510,4 @@ | ||
return jsonObj; | ||
// Return result object | ||
return {data: jsonObj, resultData: {}} | ||
} | ||
@@ -486,0 +514,0 @@ |
{ | ||
"name": "openapi-format", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "Format an OpenAPI document by ordering and filtering fields.", | ||
@@ -30,2 +30,3 @@ "keywords": [ | ||
"openapi-format.js", | ||
"util-log-output.js", | ||
"defaultSort.json", | ||
@@ -43,3 +44,3 @@ "defaultFilter.json", | ||
"scripts": { | ||
"test": "npx mocha", | ||
"test": "mocha", | ||
"release": "np --branch main" | ||
@@ -46,0 +47,0 @@ }, |
@@ -9,3 +9,3 @@ # openapi-format | ||
Next to the ordering, the CLI provides additional options to filter fields & parts of the OpenAPI document based on | ||
flags, tags, methods and operationID's. | ||
flags, tags, methods, operationID's and even unused components. | ||
@@ -34,2 +34,9 @@ <a href="https://www.npmjs.com/package/openapi-format" alt="Latest Stable Version">![npm](https://img.shields.io/npm/v/openapi-format.svg)</a> | ||
**Public documentation:** | ||
An OpenAPI document is a specification that evolves and changes. To facilitate working with the specification and publishing the | ||
document as public documentation, you want to deliver a clean and structured specification. OpenAPI-format helps you to | ||
organize the fields by sorting and filtering specific elements from the OpenAPI like internal endpoints, beta tags, ... | ||
and even unused schemas, examples, responses, ... with a clean and optimized OpenAPI document as a result. | ||
**Maintenance:** | ||
When working on large OpenAPI documents or with multiple team members, the file can be become messy and difficult to | ||
@@ -39,4 +46,4 @@ compare changes. By sorting it from time to time, the fields are all ordered in a structured manner, which will help you | ||
The filtering is a handy add-on to remove specific elements from the OpenAPI like internal endpoints, beta tags, ... | ||
This can be useful in CI/CD pipelines, where the OpenAPI is used as source for other documents like Web documentation, | ||
**CI/CD pipelines:** | ||
OpenAPI-format can be useful in CI/CD pipelines, where the OpenAPI is used as the source for other documents like Web documentation, | ||
Postman collections, test suites, ... | ||
@@ -119,3 +126,3 @@ | ||
--no-sort Don't sort the OpenAPI file [boolean] | ||
--sortComponentsFile The file with components to sort alfabehtically [path] | ||
--sortComponentsFile The file with components to sort alphabetically [path] | ||
@@ -162,3 +169,3 @@ --rename Rename the OpenAPI title [string] | ||
You can easily modify this by specifying your own ordering per key, which can passed on to the CLI (see below for an | ||
You can easily modify this by specifying your own ordering per key, which can be passed on to the CLI (see below for an | ||
example on how to do this). | ||
@@ -189,3 +196,3 @@ | ||
For more complex use-cases, we can advise the excellent https://github.com/Mermade/openapi-filter package, which has | ||
really extended options for filtering OpenAPI documents. | ||
extended options for filtering OpenAPI documents. | ||
@@ -263,9 +270,8 @@ | Type | Description | Type | Examples | | ||
=> **operations**: Refers to a combination of a OpenApi method & path from the "Path | ||
=> **operations**: Refers to a combination of a OpenAPI method & path from the "Path | ||
Object" https://spec.openapis.org/oas/v3.0.3.html#paths-object & "Path | ||
item" https://spec.openapis.org/oas/v3.0.3.html#path-item-object | ||
This will remove specific path items that matches the operation definition `PUT::/pets`. In the | ||
example below, this would mean that the item with the path '/pets' and method 'PUT' would be removed from the OpenAPI | ||
document. | ||
This will remove specific path items that match the operation definition `PUT::/pets`. In the example below, this would | ||
mean that the item with the path '/pets' and method 'PUT' would be removed from the OpenAPI document. | ||
@@ -287,7 +293,7 @@ For example: | ||
An `operationId` is an optional property. To offer support for OpenApi documents that don't have operationIds, we have | ||
added the `operation` definition which is the unique combination of the OpenApi method & path, with a `::` separator | ||
An `operationId` is an optional property. To offer support for OpenAPI documents that don't have operationIds, we have | ||
added the `operation` definition which is the unique combination of the OpenAPI method & path, with a `::` separator | ||
symbol. | ||
This will allow filtering for very specific OpenApi items, without the need of adding operationIds to the OpenApi | ||
This will allow filtering for very specific OpenAPI items, without the need of adding operationIds to the OpenAPI | ||
document. | ||
@@ -312,5 +318,5 @@ | ||
Method & Path wildcard matching example: `"*::/pets/*"` | ||
A combination of wildcards for the method and path parts are even possible. | ||
A combination of wildcards for the method and path parts is even possible. | ||
=> **flags**: Refers to a custom property which can be set on any field in the OpenAPI document. | ||
=> **flags**: Refers to a custom property that can be set on any field in the OpenAPI document. | ||
@@ -344,3 +350,3 @@ This will remove all fields and attached fields that match the flags. In the example below, this would mean that all | ||
``` | ||
In the example below, this would mean that all items with the flag `x-version` that match `x-version: 1.0` OR `x-version: 3.0` would be removed from the OpenAPI document. | ||
In the example below, this would mean that all items with the flag `x-version` that matches `x-version: 1.0` OR `x-version: 3.0` would be removed from the OpenAPI document. | ||
@@ -388,6 +394,6 @@ ```yaml | ||
This option allows you to strip the OpenApi document from any unused items of the targeted `components` types. | ||
An item in the `components` that is not referenced by `$ref`, will get marked and removed from the OpenAPI document. | ||
This option allows you to strip the OpenAPI document from any unused items of the targeted `components` types. | ||
Any item in the list of OpenAPI `components` that is not referenced as `$ref`, will get marked and removed from the OpenAPI document. | ||
REMARK: We will only strip unused components **once**, if after this one-time removal other items become unused, they will remain in the OpenApi doc. | ||
REMARK: We will recursively strip all unused components, with a maximum depth of 10 times. This means that "nested" components, that become unused, will also get removed | ||
@@ -402,3 +408,3 @@ Supported component types that can be marked as "unused": | ||
=> **stripFlags**: Refers to a lis of custom properties which can be set on any field in the OpenAPI document. | ||
=> **stripFlags**: Refers to a list of custom properties that can be set on any field in the OpenAPI document. | ||
@@ -443,3 +449,3 @@ The `stripFlags` will remove only the flags, the linked parent and properties will remain. In the example below, this would mean that all | ||
- Format a OpenAPI JSON document with the default sorting and saves it as a new YAML file | ||
- Format an OpenAPI JSON document with the default sorting and saves it as a new YAML file | ||
@@ -450,3 +456,3 @@ ```shell | ||
- Format a OpenAPI document with the default sorting and output it as JSON to STDOUT | ||
- Format an OpenAPI document with the default sorting and output it as JSON to STDOUT | ||
@@ -457,3 +463,3 @@ ```shell | ||
- Format a OpenAPI document with the default sorting and output it as YAML to STDOUT | ||
- Format an OpenAPI document with the default sorting and output it as YAML to STDOUT | ||
@@ -464,3 +470,3 @@ ```shell | ||
- Format a OpenAPI JSON document with the default sorting and save it as YAML | ||
- Format an OpenAPI JSON document with the default sorting and save it as YAML | ||
@@ -471,3 +477,3 @@ ```shell | ||
- Format a OpenAPI document but skip the sorting and save it as a new JSON file | ||
- Format an OpenAPI document but skip the sorting and save it as a new JSON file | ||
@@ -481,3 +487,3 @@ ```shell | ||
- Format a OpenAPI document, including sorting all elements in the components section | ||
- Format an OpenAPI document, including sorting all elements in the components section | ||
@@ -494,3 +500,3 @@ ```shell | ||
- Format a OpenAPI document by filtering fields, default sorting and saves it as a new file | ||
- Format an OpenAPI document by filtering fields, default sorting and saves it as a new file | ||
@@ -500,3 +506,3 @@ When you want to strip certain methods ,tags, operationIds, operations, flags you can pass a `filterFile` which contains the | ||
This can be useful to combine with the sorting, to end-up with an order and filtered OpenAPI document. | ||
This can be useful to combine with the sorting, to end up with an order and filtered OpenAPI document. | ||
@@ -523,6 +529,6 @@ example: | ||
- Format a OpenAPI document by changing the title and saves it as a new JSON file | ||
- Format an OpenAPI document by changing the title and saves it as a new JSON file | ||
During CI/CD pipelines, you might want to create different results of the OpenAPI document. Having the option to rename | ||
them, might make it easier to work with the results, so that is why we provide this command option. | ||
them might make it easier to work with the results, so that is why we provide this command option. | ||
@@ -555,3 +561,3 @@ ```shell | ||
All the CLI options can be managed in separate configuration file and passed along the openapi-format command. This will | ||
All the CLI options can be managed in a separate configuration file and passed along the openapi-format command. This will | ||
make configuration easier, especially in CI/CD implementations where the configuration can be stored in version control | ||
@@ -583,6 +589,6 @@ systems. | ||
By using the Stoplight YAML parsing, the results will be slightly different from when using a normal YAML parsing | ||
library, like [js-to-yaml](https://www.npmjs.com/package/js-yaml). We appreciate the Stoplight Studio | ||
tool, since it is an excellent GUI for working with OpenAPI documents for non-OpenAPI experts who will be contributing | ||
changes. By adopting to the Stoplight Studio YAML parsing, the potential risk of merge conflicts will | ||
be lower, which is the main reason why we opted for using the @stoplight/yaml package. | ||
library, like [js-to-yaml](https://www.npmjs.com/package/js-yaml). We appreciate the Stoplight Studio tool, since it is | ||
an excellent GUI for working with OpenAPI documents for non-OpenAPI experts who will be contributing changes. By | ||
adopting the Stoplight Studio YAML parsing, the potential risk of merge conflicts will be lower, which is the main | ||
reason why we opted for using the @stoplight/yaml package. | ||
@@ -589,0 +595,0 @@ ## Credits |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
62308
9
729
581