-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a295ed2
Showing
44 changed files
with
17,538 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules | ||
jspm_packages | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# ========================= | ||
# Operating System Files | ||
# ========================= | ||
|
||
# OSX | ||
# ========================= | ||
|
||
.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Thumbnails | ||
._* | ||
|
||
# Files that might appear in the root of a volume | ||
.DocumentRevisions-V100 | ||
.fseventsd | ||
.Spotlight-V100 | ||
.TemporaryItems | ||
.Trashes | ||
.VolumeIcon.icns | ||
|
||
# Directories potentially created on remote AFP share | ||
.AppleDB | ||
.AppleDesktop | ||
Network Trash Folder | ||
Temporary Items | ||
.apdisk | ||
|
||
# Windows | ||
# ========================= | ||
|
||
# Windows image file caches | ||
Thumbs.db | ||
ehthumbs.db | ||
|
||
# Folder config file | ||
Desktop.ini | ||
|
||
# Recycle Bin used on file shares | ||
$RECYCLE.BIN/ | ||
|
||
# Windows Installer files | ||
*.cab | ||
*.msi | ||
*.msm | ||
*.msp | ||
|
||
# Windows shortcuts | ||
*.lnk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Changelog | ||
|
||
## [Unreleased] | ||
### Changed | ||
|
||
## [v1.0.0] 30-05-2021 | ||
Initial version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# OpenAPI schema validator | ||
[](https://github.com/seriousme/openapi-schema-validator/actions?query=workflow%3A%22Node.js+CI%22) | ||
[](https://coveralls.io/github/seriousme/openapi-schema-validator?branch=master) | ||
[](https://lgtm.com/projects/g/seriousme/openapi-schema-validator/context:javascript) | ||
[](https://www.npmjs.com/package/@seriousme/openapi-schema-validator) | ||
 | ||
|
||
|
||
|
||
A JSON schema validator for [OpenAPI](https://www.openapis.org/) specifications, it currently supports: | ||
- [2.0](https://spec.openapis.org/oas/v2.0) | ||
- [3.0.x](https://spec.openapis.org/oas/v3.0.3) | ||
- [3.1.x](https://spec.openapis.org/oas/v3.1.0) | ||
|
||
<a name="install"></a> | ||
## Install | ||
``` | ||
npm i @seriousme/openapi-schema-validator --save | ||
``` | ||
|
||
<a name="Usage"></a> | ||
### Usage | ||
|
||
```javascript | ||
import Validator from "openapi-schema-validator"; | ||
|
||
console.log(Validator.supportedVersions.has("3.1")) | ||
// prints true | ||
|
||
const validator = new Validator(); | ||
const res = await validator.validate('./petstore.json'); | ||
if (res.valid){ | ||
console.log("Specification matches schema for version", validator.version); | ||
const schema = validator.resolveRefs()); | ||
// schema now contains a Javascript object containing the dereferenced schema | ||
} else { | ||
console.log("Specification does not match Schema"); | ||
console.log(res.errors); | ||
} | ||
|
||
``` | ||
|
||
<a name="Usage"></a> | ||
### API | ||
- `<instance>.validate(specification)` | ||
|
||
Thsi function tries to validata a specification against the OpenApi schemas. `specification` can be one of: | ||
|
||
- a JSON object | ||
- a JSON object encoded as string | ||
- a YAML string | ||
- a filename | ||
|
||
External references are *not* automatically resolved so you need to inline them yourself if required. | ||
The result is an object: | ||
``` | ||
{ | ||
valid: <boolean>, | ||
errors: <any> // only present if valid is false | ||
} | ||
``` | ||
|
||
- `<instance>.version` | ||
|
||
If validation is succesfull this will return the openApi version found e.g. ("2.0","3.0","3.1). | ||
The openApi specification only specifies major/minor versions as separate schemas. So "3.0.3" results in "3.0". | ||
|
||
- `<instance>.resolveRefs(options)` | ||
|
||
This function tries to resolve all internal references. External references are *not* automatically resolved so you need to inline them yourself if required. By default it will use the last specification passed to `<instance>.validate()` | ||
but you can explicity pass a specification by passing `{specification:<object>}` as options. | ||
The result is an `object` where all references have been resolved. | ||
Resolution of references is `shallow` This should normally not be a problem for this use case. | ||
|
||
- `Validator.supportedVersions` | ||
|
||
This static property returns the OpenApi versions supported by this package as a `Set`. If present, the result of `<instance>.version` is a member of this `Set`. | ||
|
||
<a name="license"></a> | ||
# License | ||
Licensed under the [MIT license](https://opensource.org/licenses/MIT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export default class Validator { | ||
static supportedVersions: Set<string>; | ||
constructor(ajvOptions?: { | ||
strict: boolean; | ||
validateFormats: boolean; | ||
}); | ||
resolveRefs(opts?: { | ||
specification?: object | ||
}): object; | ||
validate(schema: object | string): Promise<{ | ||
valid: boolean; | ||
errors?: any | ||
}>; | ||
specification: object; | ||
version: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import Ajv from 'ajv'; | ||
import Ajv2020 from 'ajv/dist/2020.js'; | ||
import { createRequire } from 'module'; | ||
import JSYaml from 'js-yaml'; | ||
import { readFile, stat } from 'fs/promises' | ||
import { resolve } from './resolve.js' | ||
|
||
|
||
const importJSON = createRequire(import.meta.url); | ||
|
||
const openApiVersions = new Set(['2.0', '3.0', '3.1']); | ||
const ajvVersions = { | ||
"http://json-schema.org/draft-07/schema": Ajv, | ||
"https://json-schema.org/draft/2020-12/schema": Ajv2020 | ||
} | ||
|
||
const openApiSchemas = {}; | ||
|
||
function getOpenApiVersion(specification) { | ||
for (const version of openApiVersions) { | ||
const prop = specification[(version == "2.0") ? 'swagger' : 'openapi']; | ||
if (typeof prop === "string" && prop.startsWith(version)) { | ||
return version | ||
} | ||
} | ||
return undefined | ||
} | ||
|
||
async function getSpecFromData(data) { | ||
if (typeof data === 'object') { | ||
return data; | ||
} | ||
if (typeof data === 'string') { | ||
if (data.match(/\n/)) { | ||
try { | ||
return JSYaml.load(data); | ||
} | ||
catch (_) { | ||
return undefined | ||
}; | ||
} | ||
try { | ||
const fileData = await readFile(data, "utf-8"); | ||
return JSYaml.load(fileData); | ||
} catch (_) { | ||
return undefined; | ||
} | ||
} | ||
} | ||
|
||
|
||
export default class Validator { | ||
constructor(ajvOptions = { strict: false, validateFormats: false }) { | ||
this.ajvOptions = ajvOptions; | ||
return this; | ||
} | ||
|
||
resolveRefs(opts={}){ | ||
return resolve(this.specification || opts.specification) | ||
} | ||
|
||
static supportedVersions = openApiVersions; | ||
|
||
async validate(data) { | ||
const specification = await getSpecFromData(data); | ||
this.specification = specification; | ||
if (specification === undefined || specification === null) { | ||
return { | ||
valid: false, | ||
errors: "Cannot find JSON, YAML or filename in data" | ||
}; | ||
} | ||
const version = getOpenApiVersion(specification); | ||
this.version = version; | ||
if (!version) { | ||
return { | ||
valid: false, | ||
errors: "Cannot find supported swagger/openapi version in specification, version must be a string." | ||
}; | ||
} | ||
const schema = await importJSON(`./schemas/v${version}/schema.json`); | ||
const schemaVersion = schema.$schema; | ||
const AjvClass = ajvVersions[schemaVersion]; | ||
const ajv = new AjvClass(this.ajvOptions); | ||
const validate = ajv.compile(schema); | ||
const result = { | ||
valid: validate(specification) | ||
}; | ||
if (validate.errors) { | ||
result.errors = validate.errors | ||
} | ||
return result | ||
} | ||
} |
Oops, something went wrong.