diff --git a/packages/apidom-reference/src/parse/index.ts b/packages/apidom-reference/src/parse/index.ts index b49a749307..6005604df2 100644 --- a/packages/apidom-reference/src/parse/index.ts +++ b/packages/apidom-reference/src/parse/index.ts @@ -4,7 +4,7 @@ import { ParseResultElement } from '@swagger-api/apidom-core'; import * as url from '../util/url'; import File from '../util/File'; import * as plugins from '../util/plugins'; -import { ReferenceOptions as IReferenceOptions, File as IFile } from '../types'; +import { ReferenceOptions as IReferenceOptions, File as IFile, Parser as IParser } from '../types'; import { ParserError, UnmatchedResolverError } from '../util/errors'; import { readFile } from '../resolve/util'; @@ -12,7 +12,7 @@ import { readFile } from '../resolve/util'; * Parses the given file's contents, using the configured parser plugins. */ const parseFile = async (file: IFile, options: IReferenceOptions): Promise => { - const parsers = await plugins.filter('canParse', file, options.parse.parsers); + const parsers: IParser[] = await plugins.filter('canParse', file, options.parse.parsers); // we couldn't find any parser for this File if (isEmpty(parsers)) { diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts index 3a53845b3c..33a9ceb7eb 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts @@ -26,15 +26,12 @@ const ApiDesignSystemsJsonParser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts index 0b67f64aeb..98329128f3 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts @@ -26,15 +26,12 @@ const ApiDesignSystemsYamlParser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts index 4212d5d50e..1f150354af 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts @@ -22,15 +22,12 @@ const AsyncApiJson2Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts index a6a7660713..e3495c24ee 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts @@ -22,15 +22,12 @@ const AsyncApiYaml2Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-browser.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-browser.ts index 2533a5956b..108b3d35e8 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-browser.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-browser.ts @@ -19,27 +19,22 @@ const BinaryParser: stampit.Stamp = stampit(Parser, { const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension); - if (!hasSupportedFileExtension) return false; - return typeof file.data === 'string' || ArrayBuffer.isView(file.data); + return hasSupportedFileExtension; }, async parse(file: IFile): Promise { try { - let base64String: string; - /** * More information about binary strings and btoa function in following link: * https://developer.mozilla.org/en-US/docs/Web/API/btoa + * + * @example + * ArrayBuffer to base64 conversion: + * + * const binaryString = String.fromCharCode.apply(null, file.data); + * base64String = btoa(binaryString); */ - if (ArrayBuffer.isView(file.data)) { - // @ts-ignore - const binaryString = String.fromCharCode.apply(null, file.data); - base64String = btoa(binaryString); - } else if (typeof file.data === 'string') { - const binaryString = unescape(encodeURIComponent(file.data)); - base64String = btoa(binaryString); - } else { - throw new TypeError('file.data is of invalid type. Only Buffer and string is allowed.'); - } + const binaryString = unescape(encodeURIComponent(file.toString())); + const base64String = btoa(binaryString); const parseResultElement = new ParseResultElement(); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-node.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-node.ts index a345a011d9..75453418cc 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-node.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-binary/index-node.ts @@ -20,14 +20,19 @@ const BinaryParser: stampit.Stamp = stampit(Parser, { const hasSupportedFileExtension = this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension); - if (!hasSupportedFileExtension) return false; - return typeof file.data === 'string' || ArrayBuffer.isView(file.data); + return hasSupportedFileExtension; }, async parse(file: IFile): Promise { + let base64String: string; + + try { + // @ts-ignore + base64String = Buffer.from(file.data).toString('base64'); + } catch { + base64String = Buffer.from(file.toString()).toString('base64'); + } + try { - const base64String = Buffer.isBuffer(file.data) - ? file.data.toString('base64') - : Buffer.from(file.data).toString('base64'); const parseResultElement = new ParseResultElement(); if (base64String.length !== 0) { diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-json/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-json/index.ts index b9dbd90bcb..d7c2cdc31b 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-json/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-json/index.ts @@ -22,15 +22,12 @@ const JsonParser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'syntacticAnalysis'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts index 97e7263f96..45635068e8 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts @@ -23,15 +23,12 @@ const OpenApiJson3_0Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts index 4411734bdb..03ec0bef2f 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts @@ -23,15 +23,12 @@ const OpenApiJson3_1Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts index 6f862aef51..6aa8c83245 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts @@ -23,15 +23,12 @@ const OpenApiYaml3_0Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts index a34fe97149..4861968ba2 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts @@ -23,15 +23,12 @@ const OpenApiYaml3_1Parser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { const parserOpts = pick(['sourceMap', 'refractorOpts'], this); diff --git a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-yaml-1-2/index.ts b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-yaml-1-2/index.ts index 7ad3cd21d5..a43d20676a 100644 --- a/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-yaml-1-2/index.ts +++ b/packages/apidom-reference/src/parse/parsers/apidom-reference-parser-yaml-1-2/index.ts @@ -21,15 +21,12 @@ const YamlParser: stampit.Stamp = stampit(Parser, { if (!hasSupportedFileExtension) return false; if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { - if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = file.toString(); try { return await parse(source, { sourceMap: this.sourceMap }); diff --git a/packages/apidom-reference/src/resolve/util.ts b/packages/apidom-reference/src/resolve/util.ts index 513d2005ce..f37ed02b48 100644 --- a/packages/apidom-reference/src/resolve/util.ts +++ b/packages/apidom-reference/src/resolve/util.ts @@ -1,6 +1,10 @@ import { isEmpty } from 'ramda'; -import { File as IFile, ReferenceOptions as IReferenceOptions } from '../types'; +import { + File as IFile, + ReferenceOptions as IReferenceOptions, + Resolver as IResolver, +} from '../types'; import * as plugins from '../util/plugins'; import { ResolverError, UnmatchedResolverError } from '../util/errors'; @@ -9,7 +13,7 @@ import { ResolverError, UnmatchedResolverError } from '../util/errors'; */ // eslint-disable-next-line import/prefer-default-export export const readFile = async (file: IFile, options: IReferenceOptions): Promise => { - const resolvers = await plugins.filter('canRead', file, options.resolve.resolvers); + const resolvers: IResolver[] = await plugins.filter('canRead', file, options.resolve.resolvers); // we couldn't find any resolver for this File if (isEmpty(resolvers)) { diff --git a/packages/apidom-reference/src/types.ts b/packages/apidom-reference/src/types.ts index e4241cd69b..f114137bbf 100644 --- a/packages/apidom-reference/src/types.ts +++ b/packages/apidom-reference/src/types.ts @@ -3,7 +3,7 @@ import { ParseResultElement, Element } from '@swagger-api/apidom-core'; export interface File { uri: string; mediaType: string; - data: Buffer | string; + data: Buffer | DataView | ArrayBuffer | string; parseResult: ParseResultElement; readonly extension: string; } @@ -28,6 +28,7 @@ export interface Parser { sourceMap: boolean; fileExtensions: string[]; mediaTypes: string[]; + decoder: TextDecoder; canParse(file: File): boolean | Promise; parse(file: File): Promise; diff --git a/packages/apidom-reference/src/util/File.ts b/packages/apidom-reference/src/util/File.ts index 9a62a6b29f..02f0364f15 100644 --- a/packages/apidom-reference/src/util/File.ts +++ b/packages/apidom-reference/src/util/File.ts @@ -1,4 +1,5 @@ import stampit from 'stampit'; +import { type } from 'ramda'; import { isString } from 'ramda-adjunct'; import * as url from './url'; @@ -36,6 +37,23 @@ const File: stampit.Stamp = stampit({ } return ''; }, + + toString(): string { + if (typeof this.data === 'string') { + return this.data; + } + + if ( + this.data instanceof ArrayBuffer || + ['ArrayBuffer'].includes(type(this.data)) || + ArrayBuffer.isView(this.data) + ) { + const textDecoder = new TextDecoder('utf-8'); + return textDecoder.decode(this.data as Buffer | DataView | ArrayBuffer); + } + + return String(this.data); + }, }, }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts index 1e0d7e7fe0..143ce13b52 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-json/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-api-design-systems-json'; import File from '../../../../src/util/File'; import ApiDesignSystemsJsonParser from '../../../../src/parse/parsers/apidom-reference-parser-api-design-systems-json'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('ApiDesignSystemsJsonParser', function () { @@ -131,21 +130,18 @@ describe('parsers', function () { }); context('given data that is not an API Design Systems JSON data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.json', - data: 1, - mediaType: mediaTypes.latest(), - }); - const parser = ApiDesignSystemsJsonParser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.json"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.json', + data: 1, + mediaType: mediaTypes.latest(), + }); + const parser = ApiDesignSystemsJsonParser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts index d3eb4926cb..0ef5a43c79 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-api-design-systems-yaml/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-api-design-systems-yaml'; import File from '../../../../src/util/File'; import ApiDesignSystemsYamlParser from '../../../../src/parse/parsers/apidom-reference-parser-api-design-systems-yaml'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('ApiDesignSystemsYamlParser', function () { @@ -152,21 +151,18 @@ describe('parsers', function () { }); context('given data that is not an API Design Systems YAML data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.yaml', - data: 1, - mediaType: mediaTypes.latest(), - }); - const parser = ApiDesignSystemsYamlParser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.yaml"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.yaml', + data: 1, + mediaType: mediaTypes.latest(), + }); + const parser = ApiDesignSystemsYamlParser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); @@ -178,10 +174,10 @@ describe('parsers', function () { mediaType: mediaTypes.latest(), }); const parser = ApiDesignSystemsYamlParser(); - const parsceResult = await parser.parse(file); + const parseResult = await parser.parse(file); - assert.isTrue(isParseResultElement(parsceResult)); - assert.isTrue(parsceResult.isEmpty); + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(parseResult.isEmpty); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts index 06c94463c1..27815634a3 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-json-2/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-asyncapi-json-2'; import File from '../../../../src/util/File'; import AsyncApiJson2Parser from '../../../../src/parse/parsers/apidom-reference-parser-asyncapi-json-2'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('AsyncApiJson2Parser', function () { @@ -129,21 +128,18 @@ describe('parsers', function () { }); context('given data that is not an AsyncApi 2.4.0 JSON data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.json', - data: 1, - mediaType: mediaTypes.latest(), - }); - const parser = AsyncApiJson2Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.json"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.json', + data: 1, + mediaType: mediaTypes.latest(), + }); + const parser = AsyncApiJson2Parser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts index dc9c89eb5a..307e64329d 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-asyncapi-yaml-2/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-asyncapi-yaml-2'; import File from '../../../../src/util/File'; import AsyncApiYaml2Parser from '../../../../src/parse/parsers/apidom-reference-parser-asyncapi-yaml-2'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('AsyncApiYaml2Parser', function () { @@ -153,20 +152,17 @@ describe('parsers', function () { context('given data that is not an AsyncApi 2.4.0 YAML data', function () { specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.yaml', - data: 1, - mediaType: mediaTypes.latest(), - }); - const parser = AsyncApiYaml2Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.yaml"'); - } + const file = File({ + uri: '/path/to/file.yaml', + data: 1, + mediaType: mediaTypes.latest(), + }); + const parser = AsyncApiYaml2Parser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); @@ -178,10 +174,10 @@ describe('parsers', function () { mediaType: mediaTypes.latest(), }); const parser = AsyncApiYaml2Parser(); - const parsceResult = await parser.parse(file); + const parseResult = await parser.parse(file); - assert.isTrue(isParseResultElement(parsceResult)); - assert.isTrue(parsceResult.isEmpty); + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(parseResult.isEmpty); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-browser.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-browser.ts new file mode 100644 index 0000000000..4c2b92e025 --- /dev/null +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-browser.ts @@ -0,0 +1,122 @@ +import { Buffer } from 'node:buffer'; +import { assert } from 'chai'; +import { StringElement, isParseResultElement, isStringElement } from '@swagger-api/apidom-core'; + +import File from '../../../../src/util/File'; +import BinaryParser from '../../../../src/parse/parsers/apidom-reference-parser-binary/index-browser'; + +const textEncoder = new TextEncoder(); + +describe('parsers', function () { + context('BinaryParser - browser', function () { + context('canParse', function () { + context('given file with .bin extension', function () { + specify('should return true', async function () { + const file = File({ uri: '/path/to/file.bin', data: textEncoder.encode('data') }); + const parser = BinaryParser(); + + assert.isTrue(await parser.canParse(file)); + }); + }); + + context('given file with unknown extension', function () { + specify('should return true', async function () { + const file = File({ uri: '/path/to/file.bin', data: textEncoder.encode('data') }); + const parser = BinaryParser(); + + assert.isTrue(await parser.canParse(file)); + }); + }); + + context('given file with no extension', function () { + specify('should return true', async function () { + const file = File({ uri: '/path/to/file', data: textEncoder.encode('data') }); + const parser = BinaryParser(); + + assert.isTrue(await parser.canParse(file)); + }); + }); + + context('given file with string data', function () { + specify('should return true', async function () { + const file = File({ uri: '/path/to/file.bin', data: 'data' }); + const parser = BinaryParser(); + + assert.isTrue(await parser.canParse(file)); + }); + }); + + context('given file with no data', function () { + specify('should return true', async function () { + const file = File({ uri: '/path/to/file.bin', data: '' }); + const parser = BinaryParser(); + + assert.isTrue(await parser.canParse(file)); + }); + }); + }); + + context('parse', function () { + context('given string data', function () { + specify('should return parse result', async function () { + const file = File({ uri: '/path/to/file.bin', data: 'data' }); + const parser = BinaryParser(); + const result = await parser.parse(file); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(isStringElement(result.result)); + assert.isTrue(result.result?.equals(Buffer.from('data').toString('base64'))); + }); + }); + + context('given generic JSON data as buffer', function () { + specify('should return parse result', async function () { + const file = File({ uri: '/path/to/file.bin', data: textEncoder.encode('data') }); + const parser = BinaryParser(); + const result = await parser.parse(file); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(isStringElement(result.result)); + // @ts-ignore + assert.isTrue(result.result?.equals(Buffer.from(file.data).toString('base64'))); + }); + }); + + context('given data that is not recognized', function () { + specify('should coerce to string and parse', async function () { + const file = File({ uri: '/path/to/file.bin', data: 1 }); + const parser = BinaryParser(); + const result = await parser.parse(file); + const stringElement: StringElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(stringElement.equals(Buffer.from(String(file.data)).toString('base64'))); + }); + }); + + context('allowEmpty', function () { + context('given allowEmpty enabled and empty file provided', function () { + specify('should return empty parse result', async function () { + const file = File({ uri: '/path/to/file.json', data: '' }); + const parser = BinaryParser({ allowEmpty: true }); + const result = await parser.parse(file); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(result.isEmpty); + }); + }); + + context('given allowEmpty disabled and empty file provided', function () { + specify('should return empty parse result', async function () { + const file = File({ uri: '/path/to/file.json', data: '' }); + const parser = BinaryParser({ allowEmpty: false }); + const result = await parser.parse(file); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(result.isEmpty); + }); + }); + }); + }); + }); +}); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-node.ts similarity index 81% rename from packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index.ts rename to packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-node.ts index c8e916431a..18294c6cc8 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-node.ts @@ -1,13 +1,12 @@ import { Buffer } from 'node:buffer'; import { assert } from 'chai'; -import { isParseResultElement, isStringElement } from '@swagger-api/apidom-core'; +import { StringElement, isParseResultElement, isStringElement } from '@swagger-api/apidom-core'; import File from '../../../../src/util/File'; import BinaryParser from '../../../../src/parse/parsers/apidom-reference-parser-binary/index-node'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { - context('BinaryParser', function () { + context('BinaryParser - node', function () { context('canParse', function () { context('given file with .bin extension', function () { specify('should return true', async function () { @@ -46,11 +45,11 @@ describe('parsers', function () { }); context('given file with no data', function () { - specify('should return false', async function () { - const file = File({ uri: '/path/to/file.bin' }); + specify('should return true', async function () { + const file = File({ uri: '/path/to/file.bin', data: '' }); const parser = BinaryParser(); - assert.isFalse(await parser.canParse(file)); + assert.isTrue(await parser.canParse(file)); }); }); }); @@ -81,17 +80,14 @@ describe('parsers', function () { }); context('given data that is not recognized', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ uri: '/path/to/file.bin', data: 1 }); - const parser = BinaryParser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.bin"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ uri: '/path/to/file.bin', data: 1 }); + const parser = BinaryParser(); + const result = await parser.parse(file); + const stringElement: StringElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(stringElement.equals(Buffer.from(String(file.data)).toString('base64'))); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-json/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-json/index.ts index 03a6ee385e..fa97a8daad 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-json/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-json/index.ts @@ -1,10 +1,14 @@ import { Buffer } from 'node:buffer'; import { assert } from 'chai'; -import { ObjectElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { + NumberElement, + ObjectElement, + isParseResultElement, + isSourceMapElement, +} from '@swagger-api/apidom-core'; import File from '../../../../src/util/File'; import JsonParser from '../../../../src/parse/parsers/apidom-reference-parser-json'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('JsonParser', function () { @@ -89,17 +93,14 @@ describe('parsers', function () { }); context('given data that is not a generic JSON data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ uri: '/path/to/file.json', data: 1 }); - const parser = JsonParser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.json"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ uri: '/path/to/file.json', data: 1 }); + const parser = JsonParser(); + const result = await parser.parse(file); + const numberElement: NumberElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts index 06f815fde4..e9055afdb9 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-0/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-0'; import File from '../../../../src/util/File'; import OpenApiJson3_0Parser from '../../../../src/parse/parsers/apidom-reference-parser-openapi-json-3-0'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('OpenApiJson3_0Parser', function () { @@ -129,21 +128,18 @@ describe('parsers', function () { }); context('given data that is not an OpenApi 3.1.x JSON data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.json', - data: 1, - mediaType: mediaTypes.latest('json'), - }); - const parser = OpenApiJson3_0Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.json"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.json', + data: 1, + mediaType: mediaTypes.latest('json'), + }); + const parser = OpenApiJson3_0Parser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts index 92a0d711d3..e9473ba2d9 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-json-3-1/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-json-3-1'; import File from '../../../../src/util/File'; import OpenApiJson3_1Parser from '../../../../src/parse/parsers/apidom-reference-parser-openapi-json-3-1'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('OpenApiJson3_1Parser', function () { @@ -129,21 +128,18 @@ describe('parsers', function () { }); context('given data that is not an OpenApi 3.1.x JSON data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.json', - data: 1, - mediaType: mediaTypes.latest('json'), - }); - const parser = OpenApiJson3_1Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.json"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.json', + data: 1, + mediaType: mediaTypes.latest('json'), + }); + const parser = OpenApiJson3_1Parser(); + const parseResult = await parser.parse(file); + const numberElement: NumberElement = parseResult.get(0); + + assert.isTrue(isParseResultElement(parseResult)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts index 739ffb1cf3..c762938267 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-0/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-yaml-3-0'; import File from '../../../../src/util/File'; import OpenApiYaml3_0Parser from '../../../../src/parse/parsers/apidom-reference-parser-openapi-yaml-3-0'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('OpenApiYaml3_0Parser', function () { @@ -160,21 +159,18 @@ describe('parsers', function () { }); context('given data that is not an OpenApi 3.1.x YAML data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.yaml', - data: 1, - mediaType: mediaTypes.latest('yaml'), - }); - const parser = OpenApiYaml3_0Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.yaml"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.yaml', + data: 1, + mediaType: mediaTypes.latest('yaml'), + }); + const parser = OpenApiYaml3_0Parser(); + const result = await parser.parse(file); + const numberElement: NumberElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts index a0f92260bb..e059b35412 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-openapi-yaml-3-1/index.ts @@ -1,12 +1,11 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; -import { isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { NumberElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; import { mediaTypes } from '@swagger-api/apidom-parser-adapter-openapi-yaml-3-1'; import File from '../../../../src/util/File'; import OpenApiYaml3_1Parser from '../../../../src/parse/parsers/apidom-reference-parser-openapi-yaml-3-1'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('OpenApiYaml3_1Parser', function () { @@ -160,21 +159,18 @@ describe('parsers', function () { }); context('given data that is not an OpenApi 3.1.x YAML data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ - uri: '/path/to/file.yaml', - data: 1, - mediaType: mediaTypes.latest('yaml'), - }); - const parser = OpenApiYaml3_1Parser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.yaml"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ + uri: '/path/to/file.yaml', + data: 1, + mediaType: mediaTypes.latest('yaml'), + }); + const parser = OpenApiYaml3_1Parser(); + const result = await parser.parse(file); + const numberElement: NumberElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(numberElement.equals(1)); }); }); diff --git a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-yaml/index.ts b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-yaml/index.ts index c9be1c1694..ce42e009be 100644 --- a/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-yaml/index.ts +++ b/packages/apidom-reference/test/parse/parsers/apidom-reference-parser-yaml/index.ts @@ -1,10 +1,14 @@ import { Buffer } from 'node:buffer'; import { assert } from 'chai'; -import { ObjectElement, isParseResultElement, isSourceMapElement } from '@swagger-api/apidom-core'; +import { + ObjectElement, + NumberElement, + isParseResultElement, + isSourceMapElement, +} from '@swagger-api/apidom-core'; import File from '../../../../src/util/File'; import YamlParser from '../../../../src/parse/parsers/apidom-reference-parser-yaml-1-2'; -import { ParserError } from '../../../../src/util/errors'; describe('parsers', function () { context('YamlParser', function () { @@ -98,17 +102,14 @@ describe('parsers', function () { }); context('given data that is not a generic YAML data', function () { - specify('should throw ParserError', async function () { - try { - const file = File({ uri: '/path/to/file.yaml', data: 1 }); - const parser = YamlParser(); - await parser.parse(file); - assert.fail('should throw ParserError'); - } catch (error: any) { - assert.instanceOf(error.cause, TypeError); - assert.instanceOf(error, ParserError); - assert.propertyVal(error, 'message', 'Error parsing "/path/to/file.yaml"'); - } + specify('should coerce to string and parse', async function () { + const file = File({ uri: '/path/to/file.yaml', data: 1 }); + const parser = YamlParser(); + const result = await parser.parse(file); + const numberElement: NumberElement = result.get(0); + + assert.isTrue(isParseResultElement(result)); + assert.isTrue(numberElement.equals(1)); }); });