UNPKG

openapi-examples-validator

Version:
3 lines 16.7 kB
#!/usr/bin/env node (()=>{var e={115:(e,t,r)=>{const a=r(723).version,o=r(858),{validateFile:s,validateExample:n,validateExamplesByMap:i}=r(497),p="true"===process.env.OPENAPI_EXAMPLES_VALIDATOR_TESTS;o.version(a).arguments("<filepath>").description("Validate embedded examples in OpenAPI-specs (JSON and YAML supported).\n To validate external examples, use the `-s` and `-e` option.\n To pass a mapping-file, to validate multiple external examples, use the `-m` option.").option("-s, --schema-jsonpath <schema-jsonpath>","Path to OpenAPI-schema, to validate the example file against").option("-e, --example-filepath <example-filepath>","file path to example file, to be validated").option("-m, --mapping-filepath <mapping-filepath>","file path to map, containing schema-paths as key and the file-path(s) to examples as value. If wildcards are used, the parameter has to be put in quotes.").option("-c, --cwd-to-mapping-file","changes to the directory of the mapping-file, before resolving the example's paths. Use this option, if your mapping-files use relative paths for the examples").option("-n, --no-additional-properties","don't allow properties that are not described in the schema").option("-r, --all-properties-required","make all the properties in the schema required").option("-o, --ignore-formats <ignored-formats...>",'Datatype formats to ignore (to prevent "unknown format" message in the error-console.)').action((async function(e,t){const{schemaJsonpath:r,exampleFilepath:a,mappingFilepath:o,cwdToMappingFile:l,allPropertiesRequired:c}=t,u=!t.additionalProperties,d=function(e){return null!=e&&Array.isArray(e)?1!==e.length||-1===e[0].indexOf("\n")?e:e[0].split("\n").filter((e=>!e.match(/^\s*$/))):e}(t.ignoreFormats);let m;o?(console.log("Validating with mapping file"),m=await i(e,o,{cwdToMappingFile:l,noAdditionalProperties:u,ignoreFormats:d,allPropertiesRequired:c})):r&&a?(console.log("Validating single external example"),m=await n(e,r,a,{noAdditionalProperties:u,ignoreFormats:d,allPropertiesRequired:c})):(console.log("Validating examples"),m=await s(e,{noAdditionalProperties:u,ignoreFormats:d,allPropertiesRequired:c})),function(e){const t=p;if(function(e){const{schemasWithExamples:t,examplesWithoutSchema:r,examplesTotal:a,matchingFilePathsMapping:o}=e,s=[`Schemas with examples found: ${t}`,`Examples without schema found: ${r}`,`Total examples found: ${a}`];null!=o&&s.push(`Matching mapping files found: ${o}`),process.stdout.write(`${s.join("\n")}\n`)}(e.statistics),e.valid)return process.stdout.write("\nNo errors found.\n\n"),void(!t&&process.exit(0));process.stdout.write("\nErrors found.\n\n"),process.stderr.write(JSON.stringify(e.errors,null," ")),!t&&process.exit(1)}(m)})),o.on("--help",(()=>{console.log("\n\n Example for external example-file:\n"),console.log(" $ openapi-examples-validator -s $.paths./.get.responses.200.schema -e example.json openapi-spec.json\n\n")})),e.exports=o.parseAsync(process.argv)},149:e=>{"use strict";e.exports=require("lodash.flatten")},184:e=>{"use strict";e.exports=require("errno")},258:e=>{"use strict";e.exports=require("json-pointer")},273:(e,t,r)=>{const a=r(984),{setAllPropertiesRequired:o}=r(299),{setNoAdditionalProperties:s}=r(305);function n(){return['$..examples[?(@property && typeof @property === "string" && @property.match(/[/+]json/))]']}e.exports={buildValidationMap:function(e){return e.reduce(((e,t)=>{const r=function(e){const t=e.split("/"),r=t.lastIndexOf("examples");return t.splice(r,t.length-r,"schema"),t.join("/")}(t);return e[r]=(e[r]||new Set).add(t),e}),{})},getJsonPathsToExamples:n,prepare:function(e,{noAdditionalProperties:t,allPropertiesRequired:r}={}){const n=a(e);return t&&s(n,['$..examples[?(@property && typeof @property === "string" && @property.match(/[/+]json/))]']),r&&o(n,['$..examples[?(@property && typeof @property === "string" && @property.match(/[/+]json/))]']),n}}},285:e=>{e.exports={parent:"parent",parentProperty:"parentProperty",path:"path",pointer:"pointer",value:"value"}},299:(e,t,r)=>{const{applyCallbackToAllObjectModels:a}=r(935);e.exports={setAllPropertiesRequired:function(e,t=[]){a(e,t,(()=>e=>{e.hasOwnProperty("properties")&&(e.required=Object.keys(e.properties))}))}}},305:(e,t,r)=>{const{applyCallbackToAllObjectModels:a}=r(935);e.exports={setNoAdditionalProperties:function(e,t=[]){const r=new RegExp("(?<!\\['properties'\\])\\['(?:"+o.join("|")+")'\\]");a(e,t,(e=>t=>{r.test(e)?console.warn(`"additionalProperties" flag not set for ${e} because it has a parent with a JSON-schema combiner keyword.`):o.some((e=>t.hasOwnProperty(e)))?console.warn(`"additionalProperties" flag not set for ${e} because it contains JSON-schema combiner keyword.`):t.hasOwnProperty("additionalProperties")||(t.additionalProperties=!1)}))}};const o=["oneOf","allOf","anyOf","not"]},402:e=>{"use strict";e.exports=require("ajv-formats")},410:e=>{"use strict";e.exports=require("glob")},427:(e,t,r)=>{const a=r(928),o=r(694);e.exports={createValidationResponse:function({errors:e,statistics:t={}}){return{valid:!e.length,statistics:t,errors:e}},dereferenceJsonSchema:async function(e,t){const r=process.cwd();process.chdir(a.dirname(e));const s=await o.dereference(t);return process.chdir(r),s}}},474:(e,t,r)=>{const a=r(984),{ApplicationError:o,ErrorType:s}=r(476),{setAllPropertiesRequired:n}=r(299),{setNoAdditionalProperties:i}=r(305),p='$..responses..content[?(@property && typeof @property === "string" && @property.match(/[/+]json/))]',l='$..requestBody.content[?(@property && typeof @property === "string" && @property.match(/[/+]json/))]',c=".example",u=".examples.*.value",d=`${p}${c}`,m=`${p}${u}`,h=`${l}${c}`,f=`${l}${u}`,g="single";function x(){return[d,m,"$..parameters..example","$..parameters..examples.*.value",h,f]}e.exports={buildValidationMap:function(e){const t=new Map;return e.reduce(((e,r)=>{const{pathSchemaAsArray:a,exampleType:n}=function(e){const t=e.split("/"),r=t.lastIndexOf("example"),a=r>-1?g:"multi",o=a===g?r:t.lastIndexOf("examples");return t.splice(o,t.length-o,"schema"),{exampleType:a,pathSchemaAsArray:t}}(r),i=a.join("/"),p=t.get(i);return p&&p!==n&&function(e){const t=e.slice(0,e.length-1);throw o.create({type:s.errorAndErrorsMutuallyExclusive,message:'Properties "error" and "errors" are mutually exclusive',params:{pathContext:t.join("/")}})}(a),t.set(i,n),e[i]=(e[i]||new Set).add(r),e}),{})},getJsonPathsToExamples:x,prepare:function(e,{noAdditionalProperties:t,allPropertiesRequired:r}={}){const o=a(e);return t&&i(o,x()),r&&n(o,x()),o}}},476:(e,t,r)=>{const a=r(711),{ENOENT:o}=r(184).code,s={jsENOENT:o.code,jsonPathNotFound:"JsonPathNotFound",errorAndErrorsMutuallyExclusive:"ErrorErrorsMutuallyExclusive",parseError:"ParseError",validation:"Validation"};class n{static create(e){const{code:t,message:r,path:o,cause:i}=e,p=t||e.type||s.validation,l={message:r};return s.validation===p||s.errorAndErrorsMutuallyExclusive===p?a(l,e):(o&&a(l,{params:{path:o}}),i&&a(l,i)),new n(p,l)}constructor(e,t={}){Object.assign(this,{type:e,...t})}}e.exports={ApplicationError:n,ErrorType:s}},496:e=>{"use strict";e.exports=require("yaml")},497:(e,t,r)=>{const a=r(711),o=r(149),s=r(668),n=r(258),i=r(896),p=r(928),l=r(410),c=r(496),{JSONPath:u}=r(940),d=r(694),{createError:m}=r(184).custom,h=r(285),{getValidatorFactory:f,compileValidate:g}=r(631),x=r(600),{ApplicationError:y,ErrorType:v}=r(476),{createValidationResponse:P,dereferenceJsonSchema:b}=r(427),w=Symbol("internal"),j="schemasWithExamples",E=["yaml","yml"],A=m(v.jsonPathNotFound);async function F(e,{noAdditionalProperties:t,ignoreFormats:r,allPropertiesRequired:a}={}){const o=x.getImplementation(e);e=await d.dereference(e),e=o.prepare(e,{noAdditionalProperties:t,allPropertiesRequired:a});let s=o.getJsonPathsToExamples().reduce(((t,r)=>t.concat(S(r,e))),[]);return function({impl:e},t,r,{ignoreFormats:a}){const o=T(),s={valid:!0,statistics:o,errors:[]},n=R(r,{ignoreFormats:a});let i;try{i=e.buildValidationMap(t)}catch(e){if(!(e instanceof y))throw e;return s.valid=!1,s.errors.push(e),s}return Object.keys(i).forEach((e=>{!function({openapiSpec:e,createValidator:t,schemaPointer:r,validationMap:a,statistics:o,validationResult:s}){const n=s.errors;a[r].forEach((a=>{const i=M(a,e),p=V(r,e,!0),l=N({createValidator:t,schema:p,example:i,statistics:o}).map((e=>(e.examplePath=a,e)));l.length&&(s.valid=!1,n.splice(n.length-1,0,...l))}))}({openapiSpec:r,createValidator:n,schemaPointer:e,validationMap:i,statistics:o,validationResult:s})})),s}({impl:o},s,e,{ignoreFormats:r})}async function O(e){const t=function(e){const t=e.split(".").pop();return E.includes(t)}(e);let r;if(t)try{r=c.parse(i.readFileSync(e,"utf-8"))}catch(e){const{name:t,message:r}=e;throw new y(v.parseError,{message:`${t}: ${r}`})}else r=JSON.parse(i.readFileSync(e,"utf-8"));return await b(e,r)}function q(e){const t=T(),r=e(t);return P({errors:r,statistics:t})}function $(e,t,r,{cwdToMappingFile:a=!1,dirPathMapExternalExamples:n,ignoreFormats:c}){return s(Object.entries(t),(([t,u])=>{let d=null;try{d=V(k(t,e),e)}catch(e){return y.create(e)}return s(o([u]),(t=>{let o=[];try{const e=a?p.join(n,t):t,r=l.sync(e);if(0===r.length)return[y.create({type:v.jsENOENT,message:`No such file or directory: '${e}'`,path:e})];for(const e of r)o.push({path:p.normalize(e),content:JSON.parse(i.readFileSync(e,"utf-8"))})}catch(e){return[y.create(e)]}return s(o,(t=>N({createValidator:R(e,{ignoreFormats:c}),schema:d,example:t.content,statistics:r,filePathExample:t.path})))}))}))}function S(e,t){return u({json:t,path:e,resultType:h.pointer})}function k(e,t){const r=S(e,t);return 0===r.length&&J(e),r.length>1?[y.create({type:v.jsonPathNotFound,message:`Path to schema cannot identify unique schema: '${e}'`,path:e})]:r[0]}function T(){const e={[w]:{[j]:new Set},examplesTotal:0,examplesWithoutSchema:0};return Object.defineProperty(e,j,{enumerable:!0,get:()=>e[w][j].size}),e}function M(e,t){try{return n.get(t,e)}catch(e){return}}function N({createValidator:e,schema:t,example:r,statistics:a,filePathExample:o}){const s=[];if(a.examplesTotal++,!t)return a.examplesWithoutSchema++,s;a[w][j].add(t);const n=g(e(),t);return n(r)?s:s.concat(...n.errors.map(y.create)).map((e=>o?(e.exampleFilePath=o,e):e))}function R(e,{ignoreFormats:t}){return f(e,{schemaId:"auto",discriminator:!0,strict:!1,allErrors:!0,formats:t&&t.reduce(((e,t)=>(e[t]=()=>!0,e)),{})})}function V(e,t,r=!1){const a=M(e,t);return r||a||J(e),a}function J(e){throw new A(`Path to schema can't be found: '${e}'`,{params:{path:e}})}e.exports={default:F,validateFile:async function(e,{noAdditionalProperties:t,ignoreFormats:r,allPropertiesRequired:a}={}){let o=null;try{o=await O(e)}catch(e){return P({errors:[y.create(e)]})}return F(o,{noAdditionalProperties:t,ignoreFormats:r,allPropertiesRequired:a})},validateExample:async function(e,t,r,{noAdditionalProperties:a,ignoreFormats:o,allPropertiesRequired:s}={}){let n=null,p=null,l=null;try{n=JSON.parse(i.readFileSync(r,"utf-8")),l=await O(e),l=x.getImplementation(l).prepare(l,{noAdditionalProperties:a,allPropertiesRequired:s}),p=V(k(t,l),l)}catch(e){return P({errors:[y.create(e)]})}return q((e=>N({createValidator:R(l,{ignoreFormats:o}),schema:p,example:n,statistics:e,filePathExample:r})))},validateExamplesByMap:async function(e,t,{cwdToMappingFile:r,noAdditionalProperties:o,ignoreFormats:s,allPropertiesRequired:n}={}){let c=0;const u=l.sync(t,{nonull:!0});let d=[];for(const t of u){let a=null,l=null;try{a=JSON.parse(i.readFileSync(t,"utf-8")),l=await O(e),l=x.getImplementation(l).prepare(l,{noAdditionalProperties:o,allPropertiesRequired:n})}catch(e){d.push(P({errors:[y.create(e)]}));continue}c++,d.push(q((e=>$(l,a,e,{cwdToMappingFile:r,dirPathMapExternalExamples:p.dirname(t),ignoreFormats:s}).map((e=>Object.assign(e,{mapFilePath:p.normalize(t)}))))))}return a(d.reduce(((e,t)=>{return e?(a=t,P({errors:(r=e).errors.concat(a.errors),statistics:Object.entries(r.statistics).reduce(((e,[t,o])=>j===t?([r,a].forEach((t=>{const r=t.statistics[w][j].values();for(let t of r)e[w][j].add(t)})),e):(e[t]=o+a.statistics[t],e)),T())})):t;var r,a}),null),{statistics:{matchingFilePathsMapping:c}})}}},600:(e,t,r)=>{const a=r(273),o=r(474),s=/^3\./;e.exports={getImplementation:function(e){return"string"==typeof e.swagger?a:e.openapi&&e.openapi.match(s)?o:null}}},631:(e,t,r)=>{const{JSONPath:a}=r(940),o=r(258),s=r(804),n=r(402),i="$id",p="$..$ref",l="https://www.npmjs.com/package/openapi-examples-validator/defs.json";e.exports={getValidatorFactory:function(e,t){const r=function(e){const t={[i]:l};return a({path:p,json:e,callback(r){if(!r.startsWith("#"))return;const a=r.substring(1),s=o.get(e,a);o.set(t,a,s)}}),t}(e);return()=>{const e=new s(t);return n(e),e.addSchema(r),e}},compileValidate:function(e,t){const r=function(e){const t=Object.assign({},e);return t.$id="https://www.npmjs.com/package/openapi-examples-validator/schema.json",t}(t);let o;a({path:p,json:r,callback(e,t,r){e.startsWith("#")&&(r.parent[r.parentProperty]=`${l}${e}`)}});try{o=e.compile(r)}catch(e){o=()=>{},o.errors=[e]}return o}}},668:e=>{"use strict";e.exports=require("lodash.flatmap")},694:e=>{"use strict";e.exports=require("json-schema-ref-parser")},711:e=>{"use strict";e.exports=require("lodash.merge")},723:e=>{e.exports={name:"openapi-examples-validator",version:"6.0.3",description:"Validates embedded examples in OpenAPI-JSONs",main:"dist/index.js",engines:{node:">=18"},bin:{"openapi-examples-validator":"dist/cli.js"},"standard-version":{scripts:{postchangelog:"npm run release:create-dockerfile && npm run release:stage-artifacts"}},scripts:{"start-dev":"babel-node src/cli",build:"npm run build:clean && npm run build:webpack","build:clean":"rimraf dist","build:webpack":"webpack --bail --progress --profile --mode production --config ./webpack/config.babel.js",coverage:'rimraf ./coverage && nyc --reporter=lcov --reporter=text -x "dist/**/*" -x "test/**/*.js" npm test',coveralls:"cat ./coverage/lcov.info | coveralls",test:"npm run build && npm run test:mocha","test-mutations":"stryker run","test:mocha":'mocha --require "./test/util/setup-tests" --recursive "./test/specs/**/*.js"',release:"npm run build && standard-version -a","release:create-dockerfile":"npm run build && node etc/src/build-dockerfile.js","release:stage-artifacts":"git add dist/*"},repository:{type:"git",url:"git+https://github.com/codekie/openapi-examples-validator.git"},keywords:["swagger","openapi","json","validate","examples"],author:"Josua Amann",license:"MIT",bugs:{url:"https://github.com/codekie/openapi-examples-validator/issues"},homepage:"https://github.com/codekie/openapi-examples-validator#readme",devDependencies:{"@babel/cli":"^7.27.0","@babel/core":"^7.26.10","@babel/eslint-parser":"^7.27.0","@babel/node":"^7.26.0","@babel/preset-env":"^7.26.9","@babel/register":"^7.25.9","@stryker-mutator/core":"^8.7.1","@stryker-mutator/mocha-runner":"^8.7.1","babel-loader":"^9.2.1",chai:"^4.3.6","chai-string":"^1.6.0","core-js-pure":"^3.41.0",coveralls:"^3.1.1",eslint:"^8.41.0","eslint-webpack-plugin":"^4.2.0","json-loader":"^0.5.7",mocha:"^10.8.2","mocha-lcov-reporter":"^1.3.0",nyc:"^15.1.0",rimraf:"^5.0.1","standard-version":"^9.5.0","stryker-cli":"^1.0.2",webpack:"^5.99.5","webpack-cli":"^5.1.4"},dependencies:{ajv:"^8.17.1","ajv-draft-04":"^1.0.0","ajv-formats":"^2.1.1",commander:"^6.2.1",errno:"^1.0.0",glob:"^8.1.0","json-pointer":"^0.6.2","json-schema-ref-parser":"^9.0.9","jsonpath-plus":"^10.3.0","lodash.clonedeep":"^4.5.0","lodash.flatmap":"^4.5.0","lodash.flatten":"^4.4.0","lodash.merge":"^4.6.2",yaml:"^2.7.1"}}},804:e=>{"use strict";e.exports=require("ajv-draft-04")},858:e=>{"use strict";e.exports=require("commander")},896:e=>{"use strict";e.exports=require("fs")},928:e=>{"use strict";e.exports=require("path")},935:(e,t,r)=>{const{JSONPath:a}=r(940),o=r(285);function s(e,t,r=o.path,s){return a({json:e,path:t,flatten:!0,resultType:r,callback:s})}e.exports={applyCallbackToAllObjectModels:function(e,t,r){const a=new Set;s(e,"$..schema..").forEach((e=>{(function(e){if(!e.match(/\['properties']$/))return;const t=e.match(/(?<!\['properties'])(\['properties']\['properties'])+$/);return!t||t.length%2!=0})(e)||a.add(e)})),function(e,t,r){r.forEach((r=>{s(e,r).forEach((e=>{for(const r of t)r.startsWith(e)&&t.delete(r)}))}))}(e,a,t);for(const t of a){const a=r(t);s(e,t,o.value,((e,t,r)=>{var o;(o=e)&&("object"===o.type||o.properties)&&a(e,t,r)}))}}}},940:e=>{"use strict";e.exports=require("jsonpath-plus")},984:e=>{"use strict";e.exports=require("lodash.clonedeep")}},t={},r=function r(a){var o=t[a];if(void 0!==o)return o.exports;var s=t[a]={exports:{}};return e[a](s,s.exports,r),s.exports}(115);module.exports=r})(); //# sourceMappingURL=cli.js.map