@@ -11,191 +11,180 @@ const { ono } = require("@jsdevtools/ono");
1111const $RefParser = require ( "@apidevtools/json-schema-ref-parser" ) ;
1212const dereference = require ( "@apidevtools/json-schema-ref-parser/lib/dereference" ) ;
1313
14- module . exports = SwaggerParser ;
15-
1614/**
1715 * This class parses a Swagger 2.0 or 3.0 API, resolves its JSON references and their resolved values,
1816 * and provides methods for traversing, dereferencing, and validating the API.
1917 *
2018 * @class
2119 * @augments $RefParser
2220 */
23- function SwaggerParser ( ) {
24- $RefParser . apply ( this , arguments ) ;
25- }
26-
27- util . inherits ( SwaggerParser , $RefParser ) ;
28- SwaggerParser . parse = $RefParser . parse ;
29- SwaggerParser . resolve = $RefParser . resolve ;
30- SwaggerParser . bundle = $RefParser . bundle ;
31- SwaggerParser . dereference = $RefParser . dereference ;
32-
33- /**
34- * Alias {@link $RefParser#schema} as {@link SwaggerParser#api}
35- */
36- Object . defineProperty ( SwaggerParser . prototype , "api" , {
37- configurable : true ,
38- enumerable : true ,
39- get ( ) {
40- return this . schema ;
41- }
42- } ) ;
43-
44- /**
45- * Parses the given Swagger API.
46- * This method does not resolve any JSON references.
47- * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.
48- *
49- * @param {string } [path] - The file path or URL of the JSON schema
50- * @param {object } [api] - The Swagger API object. This object will be used instead of reading from `path`.
51- * @param {ParserOptions } [options] - Options that determine how the API is parsed
52- * @param {Function } [callback] - An error-first callback. The second parameter is the parsed API object.
53- * @returns {Promise } - The returned promise resolves with the parsed API object.
54- */
55- SwaggerParser . prototype . parse = async function ( path , api , options , callback ) {
56- let args = normalizeArgs ( arguments ) ;
57- args . options = new Options ( args . options ) ;
58-
59- try {
60- let schema = await $RefParser . prototype . parse . call ( this , args . path , args . schema , args . options ) ;
61-
62- if ( schema . swagger ) {
63- // Verify that the parsed object is a Swagger API
64- if ( schema . swagger === undefined || schema . info === undefined || schema . paths === undefined ) {
65- throw ono . syntax ( `${ args . path || args . schema } is not a valid Swagger API definition` ) ;
66- }
67- else if ( typeof schema . swagger === "number" ) {
68- // This is a very common mistake, so give a helpful error message
69- throw ono . syntax ( 'Swagger version number must be a string (e.g. "2.0") not a number.' ) ;
70- }
71- else if ( typeof schema . info . version === "number" ) {
72- // This is a very common mistake, so give a helpful error message
73- throw ono . syntax ( 'API version number must be a string (e.g. "1.0.0") not a number.' ) ;
74- }
75- else if ( schema . swagger !== "2.0" ) {
76- throw ono . syntax ( `Unrecognized Swagger version: ${ schema . swagger } . Expected 2.0` ) ;
21+ class SwaggerParser extends $RefParser {
22+
23+ /**
24+ * Parses the given Swagger API.
25+ * This method does not resolve any JSON references.
26+ * It just reads a single file in JSON or YAML format, and parse it as a JavaScript object.
27+ *
28+ * @param {string } [path] - The file path or URL of the JSON schema
29+ * @param {object } [api] - The Swagger API object. This object will be used instead of reading from `path`.
30+ * @param {ParserOptions } [options] - Options that determine how the API is parsed
31+ * @param {Function } [callback] - An error-first callback. The second parameter is the parsed API object.
32+ * @returns {Promise } - The returned promise resolves with the parsed API object.
33+ */
34+ async parse ( path , api , options , callback ) {
35+ let args = normalizeArgs ( arguments ) ;
36+ args . options = new Options ( args . options ) ;
37+
38+ try {
39+ let schema = await super . parse ( args . path , args . schema , args . options ) ;
40+
41+ if ( schema . swagger ) {
42+ // Verify that the parsed object is a Swagger API
43+ if ( schema . swagger === undefined || schema . info === undefined || schema . paths === undefined ) {
44+ throw ono . syntax ( `${ args . path || args . schema } is not a valid Swagger API definition` ) ;
45+ }
46+ else if ( typeof schema . swagger === "number" ) {
47+ // This is a very common mistake, so give a helpful error message
48+ throw ono . syntax ( 'Swagger version number must be a string (e.g. "2.0") not a number.' ) ;
49+ }
50+ else if ( typeof schema . info . version === "number" ) {
51+ // This is a very common mistake, so give a helpful error message
52+ throw ono . syntax ( 'API version number must be a string (e.g. "1.0.0") not a number.' ) ;
53+ }
54+ else if ( schema . swagger !== "2.0" ) {
55+ throw ono . syntax ( `Unrecognized Swagger version: ${ schema . swagger } . Expected 2.0` ) ;
56+ }
7757 }
78- }
79- else {
80- let supportedVersions = [ "3.0.0" , "3.0.1" , "3.0.2" , "3.0.3" , "3.1.0" ] ;
58+ else {
59+ let supportedVersions = [ "3.0.0" , "3.0.1" , "3.0.2" , "3.0.3" , "3.1.0" ] ;
8160
82- // Verify that the parsed object is a Openapi API
83- if ( schema . openapi === undefined || schema . info === undefined ) {
84- throw ono . syntax ( `${ args . path || args . schema } is not a valid Openapi API definition` ) ;
85- }
86- else if ( schema . paths === undefined ) {
87- if ( schema . openapi === "3.1.0" ) {
88- if ( schema . webhooks === undefined ) {
61+ // Verify that the parsed object is a Openapi API
62+ if ( schema . openapi === undefined || schema . info === undefined ) {
63+ throw ono . syntax ( `${ args . path || args . schema } is not a valid Openapi API definition` ) ;
64+ }
65+ else if ( schema . paths === undefined ) {
66+ if ( schema . openapi === "3.1.0" ) {
67+ if ( schema . webhooks === undefined ) {
68+ throw ono . syntax ( `${ args . path || args . schema } is not a valid Openapi API definition` ) ;
69+ }
70+ }
71+ else {
8972 throw ono . syntax ( `${ args . path || args . schema } is not a valid Openapi API definition` ) ;
9073 }
9174 }
92- else {
93- throw ono . syntax ( `${ args . path || args . schema } is not a valid Openapi API definition` ) ;
75+ else if ( typeof schema . openapi === "number" ) {
76+ // This is a very common mistake, so give a helpful error message
77+ throw ono . syntax ( 'Openapi version number must be a string (e.g. "3.0.0") not a number.' ) ;
9478 }
95- }
96- else if ( typeof schema . openapi === "number" ) {
97- // This is a very common mistake, so give a helpful error message
98- throw ono . syntax ( 'Openapi version number must be a string (e.g. "3.0.0") not a number.' ) ;
99- }
100- else if ( typeof schema . info . version === "number" ) {
101- // This is a very common mistake, so give a helpful error message
102- throw ono . syntax ( 'API version number must be a string (e.g. "1.0.0") not a number.' ) ;
103- }
104- else if ( supportedVersions . indexOf ( schema . openapi ) === - 1 ) {
105- throw ono . syntax (
106- `Unsupported OpenAPI version: ${ schema . openapi } . ` +
107- `Swagger Parser only supports versions ${ supportedVersions . join ( ", " ) } `
108- ) ;
79+ else if ( typeof schema . info . version === "number" ) {
80+ // This is a very common mistake, so give a helpful error message
81+ throw ono . syntax ( 'API version number must be a string (e.g. "1.0.0") not a number.' ) ;
82+ }
83+ else if ( supportedVersions . indexOf ( schema . openapi ) === - 1 ) {
84+ throw ono . syntax (
85+ `Unsupported OpenAPI version: ${ schema . openapi } . ` +
86+ `Swagger Parser only supports versions ${ supportedVersions . join ( ", " ) } `
87+ ) ;
88+ }
89+
90+ // This is an OpenAPI v3 schema, check if the "servers" have any relative paths and
91+ // fix them if the content was pulled from a web resource
92+ util . fixOasRelativeServers ( schema , args . path ) ;
10993 }
11094
111- // This is an OpenAPI v3 schema, check if the "servers" have any relative paths and
112- // fix them if the content was pulled from a web resource
113- util . fixOasRelativeServers ( schema , args . path ) ;
95+ // Looks good!
96+ return maybe ( args . callback , Promise . resolve ( schema ) ) ;
97+ }
98+ catch ( err ) {
99+ return maybe ( args . callback , Promise . reject ( err ) ) ;
114100 }
115-
116- // Looks good!
117- return maybe ( args . callback , Promise . resolve ( schema ) ) ;
118- }
119- catch ( err ) {
120- return maybe ( args . callback , Promise . reject ( err ) ) ;
121101 }
122- } ;
123-
124- /**
125- * Parses, dereferences, and validates the given Swagger API.
126- * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
127- *
128- * @param {string } [path] - The file path or URL of the JSON schema
129- * @param {object } [api] - The Swagger API object. This object will be used instead of reading from `path`.
130- * @param {ParserOptions } [options] - Options that determine how the API is parsed, dereferenced, and validated
131- * @param {Function } [callback] - An error-first callback. The second parameter is the parsed API object.
132- * @returns {Promise } - The returned promise resolves with the parsed API object.
133- */
134- SwaggerParser . validate = function ( path , api , options , callback ) {
135- let Class = this ; // eslint-disable-line consistent-this
136- let instance = new Class ( ) ;
137- return instance . validate . apply ( instance , arguments ) ;
138- } ;
139102
140- /**
141- * Parses, dereferences, and validates the given Swagger API.
142- * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
143- *
144- * @param {string } [path] - The file path or URL of the JSON schema
145- * @param {object } [api] - The Swagger API object. This object will be used instead of reading from `path`.
146- * @param {ParserOptions } [options] - Options that determine how the API is parsed, dereferenced, and validated
147- * @param {Function } [callback] - An error-first callback. The second parameter is the parsed API object.
148- * @returns {Promise } - The returned promise resolves with the parsed API object.
149- */
150- SwaggerParser . prototype . validate = async function ( path , api , options , callback ) {
151- let me = this ;
152- let args = normalizeArgs ( arguments ) ;
153- args . options = new Options ( args . options ) ;
154-
155- // ZSchema doesn't support circular objects, so don't dereference circular $refs yet
156- // (see https://github.com/zaggino/z-schema/issues/137)
157- let circular$RefOption = args . options . dereference . circular ;
158- args . options . validate . schema && ( args . options . dereference . circular = "ignore" ) ;
159-
160- try {
161- await this . dereference ( args . path , args . schema , args . options ) ;
162-
163- // Restore the original options, now that we're done dereferencing
164- args . options . dereference . circular = circular$RefOption ;
165-
166- if ( args . options . validate . schema ) {
167- // Validate the API against the Swagger schema
168- // NOTE: This is safe to do, because we haven't dereferenced circular $refs yet
169- validateSchema ( me . api ) ;
170-
171- if ( me . $refs . circular ) {
172- if ( circular$RefOption === true ) {
173- // The API has circular references,
174- // so we need to do a second-pass to fully-dereference it
175- dereference ( me , args . options ) ;
176- }
177- else if ( circular$RefOption === false ) {
178- // The API has circular references, and they're not allowed, so throw an error
179- throw ono . reference ( "The API contains circular references" ) ;
103+ /**
104+ * Parses, dereferences, and validates the given Swagger API.
105+ * Depending on the options, validation can include JSON Schema validation and/or Swagger Spec validation.
106+ *
107+ * @param {string } [path] - The file path or URL of the JSON schema
108+ * @param {object } [api] - The Swagger API object. This object will be used instead of reading from `path`.
109+ * @param {ParserOptions } [options] - Options that determine how the API is parsed, dereferenced, and validated
110+ * @param {Function } [callback] - An error-first callback. The second parameter is the parsed API object.
111+ * @returns {Promise } - The returned promise resolves with the parsed API object.
112+ */
113+ async validate ( path , api , options , callback ) {
114+ let me = this ;
115+ let args = normalizeArgs ( arguments ) ;
116+ args . options = new Options ( args . options ) ;
117+
118+ // ZSchema doesn't support circular objects, so don't dereference circular $refs yet
119+ // (see https://github.com/zaggino/z-schema/issues/137)
120+ let circular$RefOption = args . options . dereference . circular ;
121+ args . options . validate . schema && ( args . options . dereference . circular = "ignore" ) ;
122+
123+ try {
124+ await this . dereference ( args . path , args . schema , args . options ) ;
125+
126+ // Restore the original options, now that we're done dereferencing
127+ args . options . dereference . circular = circular$RefOption ;
128+
129+ if ( args . options . validate . schema ) {
130+ // Validate the API against the Swagger schema
131+ // NOTE: This is safe to do, because we haven't dereferenced circular $refs yet
132+ validateSchema ( me . api ) ;
133+
134+ if ( me . $refs . circular ) {
135+ if ( circular$RefOption === true ) {
136+ // The API has circular references,
137+ // so we need to do a second-pass to fully-dereference it
138+ dereference ( me , args . options ) ;
139+ }
140+ else if ( circular$RefOption === false ) {
141+ // The API has circular references, and they're not allowed, so throw an error
142+ throw ono . reference ( "The API contains circular references" ) ;
143+ }
180144 }
181145 }
182- }
183146
184- if ( args . options . validate . spec ) {
185- // Validate the API against the Swagger spec
186- validateSpec ( me . api ) ;
187- }
147+ if ( args . options . validate . spec ) {
148+ // Validate the API against the Swagger spec
149+ validateSpec ( me . api ) ;
150+ }
188151
189- return maybe ( args . callback , Promise . resolve ( me . schema ) ) ;
152+ return maybe ( args . callback , Promise . resolve ( me . schema ) ) ;
153+ }
154+ catch ( err ) {
155+ return maybe ( args . callback , Promise . reject ( err ) ) ;
156+ }
190157 }
191- catch ( err ) {
192- return maybe ( args . callback , Promise . reject ( err ) ) ;
158+ }
159+
160+
161+ /**
162+ * Alias {@link $RefParser#schema} as {@link SwaggerParser#api}
163+ */
164+ Object . defineProperty ( SwaggerParser . prototype , "api" , {
165+ configurable : true ,
166+ enumerable : true ,
167+ get ( ) {
168+ return this . schema ;
193169 }
194- } ;
170+ } ) ;
195171
196172/**
197173 * The Swagger object
198174 * https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
199175 *
200176 * @typedef {{swagger: string, info: {}, paths: {}} } SwaggerObject
201177 */
178+
179+ const defaultInstance = new SwaggerParser ( ) ;
180+ const defaultExport = SwaggerParser ;
181+
182+ defaultExport . validate = ( ...args ) => { return defaultInstance . validate ( ...args ) ; } ;
183+ defaultExport . dereference = ( ...args ) => { return defaultInstance . dereference ( ...args ) ; } ;
184+ defaultExport . bundle = ( ...args ) => { return defaultInstance . bundle ( ...args ) ; } ;
185+ defaultExport . parse = ( ...args ) => { return defaultInstance . parse ( ...args ) ; } ;
186+ defaultExport . resolve = ( ...args ) => { return defaultInstance . resolve ( ...args ) ; } ;
187+ defaultExport . default = defaultExport ;
188+ defaultExport . SwaggerParser = defaultExport ;
189+
190+ module . exports = defaultExport ;
0 commit comments