diff --git a/src/index.ts b/src/index.ts index 50b0fd8..f357e84 100644 --- a/src/index.ts +++ b/src/index.ts @@ -76,7 +76,7 @@ import { resolveV3Document } from './v3/parser'; export default async function bundle(files: string[], options: any = {}) { if (typeof options.base !== 'undefined') { options.base = toJS(options.base); - await parse(options.base); + await parse(options.base, options); } const parsedJsons = files.map(file => toJS(file)) as AsyncAPIObject[]; @@ -89,15 +89,13 @@ export default async function bundle(files: string[], options: any = {}) { let resolvedJsons; if (majorVersion === 3) { - resolvedJsons = await resolveV3Document(parsedJsons); + resolvedJsons = await resolveV3Document(parsedJsons, options); } else { /** * Bundle all external references for each file. * @private */ - resolvedJsons = await resolve(parsedJsons, { - referenceIntoComponents: options.referenceIntoComponents, - }); + resolvedJsons = await resolve(parsedJsons, options); } return new Document(resolvedJsons as AsyncAPIObject[], options.base); diff --git a/src/parser.ts b/src/parser.ts index 7f122be..f4d23d0 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -11,37 +11,44 @@ const parser = new Parser(); * @param {Object[]} JSONSchema * @private */ -export async function parse(JSONSchema: AsyncAPIObject) { +export async function parse(JSONSchema: AsyncAPIObject, options: any = {}) { + let validationResult: any[] = []; addXOrigins(JSONSchema); const dereferencedJSONSchema = await $RefParser.dereference(JSONSchema, { dereference: { circular: false, - // excludedPathMatcher: (path: string): boolean => { - // return ( - // // prettier-ignore - // !!(/#\/channels\/[a-zA-Z0-9]*\/servers/).exec(path) || - // !!(/#\/operations\/[a-zA-Z0-9]*\/channel/).exec(path) || - // !!(/#\/operations\/[a-zA-Z0-9]*\/messages/).exec(path) || - // !!(/#\/operations\/[a-zA-Z0-9]*\/reply\/channel/).exec(path) || - // !!(/#\/operations\/[a-zA-Z0-9]*\/reply\/messages/).exec(path) || - // !!(/#\/components\/channels\/[a-zA-Z0-9]*\/servers/).exec(path) || - // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/channel/).exec(path) || - // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/messages/).exec(path) || - // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/reply\/channel/).exec( - // path - // ) || - // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/reply\/messages/).exec( - // path - // ) - // ); - // }, + excludedPathMatcher: (path: string): boolean => { + return ( + // prettier-ignore + !!(/#\/[a-zA-Z0-9]*/).exec(path)// || + // !!(/#\/channels\/[a-zA-Z0-9]*\/servers/).exec(path) || + // !!(/#\/operations\/[a-zA-Z0-9]*\/channel/).exec(path) || + // !!(/#\/operations\/[a-zA-Z0-9]*\/messages/).exec(path) || + // !!(/#\/operations\/[a-zA-Z0-9]*\/reply\/channel/).exec(path) || + // !!(/#\/operations\/[a-zA-Z0-9]*\/reply\/messages/).exec(path) || + // !!(/#\/components\/channels\/[a-zA-Z0-9]*\/servers/).exec(path) || + // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/channel/).exec(path) || + // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/messages/).exec(path) || + // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/reply\/channel/).exec( + // path + // ) || + // !!(/#\/components\/operations\/[a-zA-Z0-9]*\/reply\/messages/).exec( + // path + // ) + ); + }, }, }); - const result = await parser.validate( - JSON.parse(JSON.stringify(dereferencedJSONSchema)) - ); + // Option `noValidation: true` is used by the testing system, which + // intentionally feeds Bundler wrong AsyncAPI Documents, thus it is not + // documented. + if (!options.noValidation) { + validationResult = await parser.validate( + JSON.parse(JSON.stringify(dereferencedJSONSchema)) + ); + } // If Parser's `validate()` function returns a non-empty array with at least // one `severity: 0`, that means there was at least one error during @@ -49,15 +56,15 @@ export async function parse(JSONSchema: AsyncAPIObject) { // elements with `severity: 0` are outputted as a list of remarks, and the // program exits without doing anything further. if ( - result.length !== 0 && - result.map(element => element.severity).includes(0) + validationResult.length !== 0 && + validationResult.map(element => element.severity).includes(0) ) { console.log( 'Validation of the resulting AsyncAPI Document failed.\nList of remarks:\n', - result.filter(element => element.severity === 0) + validationResult.filter(element => element.severity === 0) ); throw new Error(); } - return result; + return dereferencedJSONSchema; } diff --git a/src/util.ts b/src/util.ts index 18efe47..637932c 100644 --- a/src/util.ts +++ b/src/util.ts @@ -65,7 +65,7 @@ export const resolve = async ( // await parse(asyncapiDocument); // } addXOrigins(asyncapiDocument); // eslint-disable-line @typescript-eslint/no-use-before-define - await parse(asyncapiDocument); + await parse(asyncapiDocument, options); // const bundledAsyncAPIDocument = await $RefParser.bundle(asyncapiDocument); docs.push(asyncapiDocument); } diff --git a/src/v3/parser.ts b/src/v3/parser.ts index 83192d1..ade2c82 100644 --- a/src/v3/parser.ts +++ b/src/v3/parser.ts @@ -6,7 +6,9 @@ import { AsyncAPIObject } from 'spec-types'; const parser = new Parser(); -export async function parse(JSONSchema: AsyncAPIObject) { +export async function parse(JSONSchema: AsyncAPIObject, options: any = {}) { + let validationResult: any[] = []; + addXOrigins(JSONSchema); const dereferencedJSONSchema = await $RefParser.dereference(JSONSchema, { @@ -15,6 +17,7 @@ export async function parse(JSONSchema: AsyncAPIObject) { excludedPathMatcher: (path: string): boolean => { return ( // prettier-ignore + !!(/#\/[a-zA-Z0-9]*/).exec(path) || !!(/#\/channels\/[a-zA-Z0-9]*\/servers/).exec(path) || !!(/#\/operations\/[a-zA-Z0-9]*\/channel/).exec(path) || !!(/#\/operations\/[a-zA-Z0-9]*\/messages/).exec(path) || @@ -34,30 +37,38 @@ export async function parse(JSONSchema: AsyncAPIObject) { }, }); - const result = await parser.validate( - JSON.parse(JSON.stringify(dereferencedJSONSchema)) - ); - + // Option `noValidation: true` is used by the testing system, which + // intentionally feeds Bundler wrong AsyncAPI Documents, thus it is not + // documented. + if (!options.noValidation) { + validationResult = await parser.validate( + JSON.parse(JSON.stringify(dereferencedJSONSchema)) + ); + } + // If Parser's `validate()` function returns a non-empty array with at least // one `severity: 0`, that means there was at least one error during // validation, not a `warning: 1`, `info: 2`, or `hint: 3`. Thus, array's // elements with `severity: 0` are outputted as a list of remarks, and the // program exits without doing anything further. if ( - result.length !== 0 && - result.map(element => element.severity).includes(0) + validationResult.length !== 0 && + validationResult.map(element => element.severity).includes(0) ) { console.log( 'Validation of the resulting AsyncAPI Document failed.\nList of remarks:\n', - result.filter(element => element.severity === 0) + validationResult.filter(element => element.severity === 0) ); throw new Error(); } - return result; + return dereferencedJSONSchema; } -export async function resolveV3Document(asyncapiDocuments: AsyncAPIObject[]) { +export async function resolveV3Document( + asyncapiDocuments: AsyncAPIObject[], + options: any = {} +) { const docs = []; // Graceful `return` doesn't stop Bundler from writing an invalid @@ -65,7 +76,7 @@ export async function resolveV3Document(asyncapiDocuments: AsyncAPIObject[]) { // terminated through `try...catch`, which is a forced decision. try { for (const asyncapiDocument of asyncapiDocuments) { - await parse(asyncapiDocument); + await parse(asyncapiDocument, options); docs.push(asyncapiDocument); } } catch (e) {} // eslint-disable-line no-empty diff --git a/tests/lib/index.spec.ts b/tests/lib/index.spec.ts index b70fb6a..7ceb64e 100644 --- a/tests/lib/index.spec.ts +++ b/tests/lib/index.spec.ts @@ -16,7 +16,7 @@ describe('[integration testing] bundler should ', () => { path.resolve(process.cwd(), './tests/base.yml'), 'utf-8' ), - validate: false, + noValidation: true, } ); @@ -36,6 +36,7 @@ describe('[integration testing] bundler should ', () => { ), { referenceIntoComponents: false, + noValidation: true, } ) ).resolves; @@ -54,6 +55,7 @@ describe('[integration testing] bundler should ', () => { ), { referenceIntoComponents: false, + noValidation: true, } ) ).resolves; @@ -65,7 +67,7 @@ describe('[integration testing] bundler should ', () => { expect( await bundle( files.map(file => fs.readFileSync(path.resolve(process.cwd(), file), 'utf-8')), - { referenceIntoComponents: false, base: fs.readFileSync(path.resolve(process.cwd(), './tests/base-option/base.yaml'), 'utf-8') } + { referenceIntoComponents: false, base: fs.readFileSync(path.resolve(process.cwd(), './tests/base-option/base.yaml'), 'utf-8'), noValidation: true, } ) ).resolves; @@ -76,7 +78,7 @@ describe('[integration testing] bundler should ', () => { expect( await bundle( files.map(file => fs.readFileSync(path.resolve(process.cwd(), file), 'utf-8')), - {baseDir: './tests/specfiles'} + {baseDir: './tests/specfiles', noValidation: true} ) ).resolves })