@apiture/openapi-down-convert
Advanced tools
Comparing version 0.5.0 to 0.6.0
{ | ||
"name": "@apiture/openapi-down-convert", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Tool to down convert OpenAPI 3.1 to OpenAPI 3.0", | ||
@@ -5,0 +5,0 @@ "main": "lib/src/index.js", |
@@ -43,3 +43,5 @@ #!/usr/bin/env node | ||
const outDir = path.dirname(outputFileName); | ||
fs.mkdirSync(outDir); | ||
if (!fs.existsSync(outDir)) { | ||
fs.mkdirSync(outDir, { recursive: true }); | ||
} | ||
fs.writeFileSync(outputFileName, text, 'utf8'); | ||
@@ -46,0 +48,0 @@ } |
@@ -23,3 +23,6 @@ export interface ConverterOptions { | ||
convertJsonSchemaExamples(): void; | ||
private walkNestedSchemaObjects; | ||
convertConstToEnum(): void; | ||
convertNullableTypeArray(): void; | ||
removeUnsupportedSchemaKeywords(): void; | ||
private json; | ||
@@ -26,0 +29,0 @@ convertSecuritySchemes(): void; |
@@ -47,2 +47,4 @@ "use strict"; | ||
this.convertConstToEnum(); | ||
this.convertNullableTypeArray(); | ||
this.removeUnsupportedSchemaKeywords(); | ||
return this.openapi30; | ||
@@ -81,21 +83,51 @@ } | ||
} | ||
walkNestedSchemaObjects(schema, schemaVisitor) { | ||
for (const key in schema) { | ||
const subSchema = schema[key]; | ||
if (subSchema !== null && typeof subSchema === 'object') { | ||
schema[key] = (0, RefVisitor_1.walkObject)(subSchema, schemaVisitor); | ||
} | ||
} | ||
return schema; | ||
} | ||
convertConstToEnum() { | ||
const schemaVisitor = (schema) => { | ||
for (const key in schema) { | ||
if (key === 'const') { | ||
const constant = schema['const']; | ||
delete schema['const']; | ||
schema['enum'] = [constant]; | ||
if (schema['const']) { | ||
const constant = schema['const']; | ||
delete schema['const']; | ||
schema['enum'] = [constant]; | ||
this.log(`Converted const: ${constant} to enum`); | ||
} | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
(0, RefVisitor_1.visitSchemaObjects)(this.openapi30, schemaVisitor); | ||
} | ||
convertNullableTypeArray() { | ||
const schemaVisitor = (schema) => { | ||
if (schema.hasOwnProperty('type')) { | ||
const schemaType = schema['type']; | ||
if (Array.isArray(schemaType) && schemaType.length === 2 && schemaType.includes('null')) { | ||
const nonNull = schemaType.filter((_) => _ !== 'null')[0]; | ||
schema['type'] = nonNull; | ||
schema['nullable'] = true; | ||
this.log(`Converted schema type array to nullable`); | ||
} | ||
else { | ||
const subSchema = schema[key]; | ||
if (subSchema !== null && typeof subSchema === 'object') { | ||
schema[key] = (0, RefVisitor_1.walkObject)(subSchema, schemaVisitor); | ||
} | ||
} | ||
} | ||
return schema; | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
(0, RefVisitor_1.visitSchemaObjects)(this.openapi30, schemaVisitor); | ||
} | ||
removeUnsupportedSchemaKeywords() { | ||
const keywordsToRemove = ['$id', '$schema', 'unevaluatedProperties']; | ||
const schemaVisitor = (schema) => { | ||
keywordsToRemove.forEach((key) => { | ||
if (schema.hasOwnProperty(key)) { | ||
delete schema[key]; | ||
this.log(`Removed unsupported schema keyword ${key}`); | ||
} | ||
}); | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
(0, RefVisitor_1.visitSchemaObjects)(this.openapi30, schemaVisitor); | ||
} | ||
json(x) { | ||
@@ -102,0 +134,0 @@ return JSON.stringify(x, null, 2); |
{ | ||
"name": "@apiture/openapi-down-convert", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Tool to down convert OpenAPI 3.1 to OpenAPI 3.0", | ||
@@ -5,0 +5,0 @@ "main": "lib/src/index.js", |
101
README.md
@@ -235,2 +235,103 @@ # OpenAPI Down Convert | ||
### Convert type arrays to nullable | ||
If a schema has a type array of exactly two values, and one of them | ||
is the string `'null'`, the type is converted to the non-null string item, | ||
and `nullable: true` added to the schema. | ||
For example: | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: [ object, 'null' ] | ||
allOf: | ||
... | ||
``` | ||
becomes | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: object | ||
nullable: true | ||
allOf: | ||
... | ||
``` | ||
and | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: arrray | ||
items: | ||
type: [ 'string', 'null' ] | ||
... | ||
``` | ||
becomes | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: arrray | ||
items: | ||
type: string | ||
nullable: true | ||
... | ||
``` | ||
This transformation does not handle more complex `type` array | ||
scenarios such as | ||
```yaml | ||
type: [ number, string, boolean, 'null'] | ||
``` | ||
To support that, the schema would need to be recast using `oneOf`, | ||
but this is not trivial do to other schema attributes that may | ||
be possible (`properties`, `allOf` etc.) | ||
(Contributions welcome.) | ||
### Remove `unevaluatedProperties` | ||
The tool removes the `unevaluatedProperties` value, introduced in later | ||
versions of JSON Schema, | ||
as this is not supported in OAS 3.0 JSON Schema Draft 7 | ||
used in OAS 3.0. | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: object | ||
unevaluatedProperties: false | ||
allOf: | ||
... | ||
``` | ||
becomes | ||
```yaml | ||
myResponse: | ||
title: My Response | ||
description: Response from an API operation | ||
type: object | ||
unevaluatedProperties: false | ||
allOf: | ||
... | ||
``` | ||
### Remove schema `$id` and `$schema` | ||
The tool removes any `$id` or `$schema` keywords that may appear | ||
inside schema objects. | ||
## Unsupported down conversions | ||
@@ -237,0 +338,0 @@ |
@@ -47,3 +47,5 @@ #!/usr/bin/env node | ||
const outDir = path.dirname(outputFileName); | ||
fs.mkdirSync(outDir); | ||
if (!fs.existsSync(outDir)) { | ||
fs.mkdirSync(outDir, {recursive: true}); | ||
} | ||
fs.writeFileSync(outputFileName, text, 'utf8'); | ||
@@ -50,0 +52,0 @@ } else { |
@@ -101,2 +101,4 @@ import * as v8 from 'v8'; | ||
this.convertConstToEnum(); | ||
this.convertNullableTypeArray(); | ||
this.removeUnsupportedSchemaKeywords(); | ||
return this.openapi30; | ||
@@ -144,2 +146,12 @@ } | ||
private walkNestedSchemaObjects(schema, schemaVisitor) { | ||
for (const key in schema) { | ||
const subSchema = schema[key]; | ||
if (subSchema !== null && typeof subSchema === 'object') { | ||
schema[key] = walkObject(subSchema, schemaVisitor); | ||
} | ||
} | ||
return schema; | ||
} | ||
/** | ||
@@ -152,16 +164,29 @@ * OpenAPI 3.1 uses JSON Schema 2020-12 which allows `const` | ||
const schemaVisitor: SchemaVisitor = (schema: SchemaObject): SchemaObject => { | ||
for (const key in schema) { | ||
if (key === 'const') { | ||
const constant = schema['const']; | ||
delete schema['const']; | ||
schema['enum'] = [constant]; | ||
} else { | ||
const subSchema = schema[key]; | ||
if (schema['const']) { | ||
const constant = schema['const']; | ||
delete schema['const']; | ||
schema['enum'] = [constant]; | ||
this.log(`Converted const: ${constant} to enum`); | ||
} | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
visitSchemaObjects(this.openapi30, schemaVisitor); | ||
} | ||
if (subSchema !== null && typeof subSchema === 'object') { | ||
schema[key] = walkObject(subSchema, schemaVisitor); | ||
} | ||
/** | ||
* Convert 2-element type arrays containing 'null' to | ||
* string type and `nullable: true` | ||
*/ | ||
convertNullableTypeArray() { | ||
const schemaVisitor: SchemaVisitor = (schema: SchemaObject): SchemaObject => { | ||
if (schema.hasOwnProperty('type')) { | ||
const schemaType = schema['type']; | ||
if (Array.isArray(schemaType) && schemaType.length === 2 && schemaType.includes('null')) { | ||
const nonNull = schemaType.filter((_) => _ !== 'null')[0]; | ||
schema['type'] = nonNull; | ||
schema['nullable'] = true; | ||
this.log(`Converted schema type array to nullable`); | ||
} | ||
} | ||
return schema; | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
@@ -171,2 +196,16 @@ visitSchemaObjects(this.openapi30, schemaVisitor); | ||
removeUnsupportedSchemaKeywords() { | ||
const keywordsToRemove = ['$id', '$schema', 'unevaluatedProperties']; | ||
const schemaVisitor: SchemaVisitor = (schema: SchemaObject): SchemaObject => { | ||
keywordsToRemove.forEach((key) => { | ||
if (schema.hasOwnProperty(key)) { | ||
delete schema[key]; | ||
this.log(`Removed unsupported schema keyword ${key}`); | ||
} | ||
}); | ||
return this.walkNestedSchemaObjects(schema, schemaVisitor); | ||
}; | ||
visitSchemaObjects(this.openapi30, schemaVisitor); | ||
} | ||
private json(x) { | ||
@@ -173,0 +212,0 @@ return JSON.stringify(x, null, 2); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
61512
897
344