From e2aee391ce246283c50fd81026dbaa1b3a67d7a6 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Mon, 19 Sep 2022 17:45:06 +0200 Subject: [PATCH 1/5] fix(reference): decode array buffers using TextDecoder Refs #2029 --- packages/apidom-reference/src/parse/parsers/Parser.ts | 6 ++++++ .../index.ts | 4 ++-- .../index.ts | 4 ++-- .../apidom-reference-parser-asyncapi-json-2/index.ts | 4 ++-- .../apidom-reference-parser-asyncapi-yaml-2/index.ts | 4 ++-- .../src/parse/parsers/apidom-reference-parser-json/index.ts | 4 ++-- .../apidom-reference-parser-openapi-json-3-0/index.ts | 4 ++-- .../apidom-reference-parser-openapi-json-3-1/index.ts | 4 ++-- .../apidom-reference-parser-openapi-yaml-3-0/index.ts | 4 ++-- .../apidom-reference-parser-openapi-yaml-3-1/index.ts | 4 ++-- .../parse/parsers/apidom-reference-parser-yaml-1-2/index.ts | 4 ++-- packages/apidom-reference/src/types.ts | 1 + 12 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/apidom-reference/src/parse/parsers/Parser.ts b/packages/apidom-reference/src/parse/parsers/Parser.ts index 1185f6ad56..e7e2b2de2e 100644 --- a/packages/apidom-reference/src/parse/parsers/Parser.ts +++ b/packages/apidom-reference/src/parse/parsers/Parser.ts @@ -24,6 +24,10 @@ const Parser = stampit({ * List of supported media types. */ mediaTypes: [], + /** + * Transforms array buffers into strings. + */ + decoder: new TextDecoder('utf-8'), }, init( this: IParser, @@ -32,12 +36,14 @@ const Parser = stampit({ sourceMap = this.sourceMap, fileExtensions = this.fileExtensions, mediaTypes = this.mediaTypes, + decoder = this.decoder, } = {}, ) { this.allowEmpty = allowEmpty; this.sourceMap = sourceMap; this.fileExtensions = fileExtensions; this.mediaTypes = mediaTypes; + this.decoder = decoder; }, methods: { async canParse(): Promise { 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..255a57db5b 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 @@ -27,14 +27,14 @@ const ApiDesignSystemsJsonParser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..c339de5a40 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 @@ -27,14 +27,14 @@ const ApiDesignSystemsYamlParser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..8501074977 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 @@ -23,14 +23,14 @@ const AsyncApiJson2Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..87765a39c6 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 @@ -23,14 +23,14 @@ const AsyncApiYaml2Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; try { const parserOpts = pick(['sourceMap', 'refractorOpts'], this); 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..8ab1c1f2d3 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 @@ -23,14 +23,14 @@ const JsonParser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..9a6d0288e4 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 @@ -24,14 +24,14 @@ const OpenApiJson3_0Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..6960d4a612 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 @@ -24,14 +24,14 @@ const OpenApiJson3_1Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..474d547758 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 @@ -24,14 +24,14 @@ const OpenApiYaml3_0Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..821a4ed471 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 @@ -24,14 +24,14 @@ const OpenApiYaml3_1Parser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; 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..66ebf7d34d 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 @@ -22,14 +22,14 @@ const YamlParser: stampit.Stamp = stampit(Parser, { if (hasSupportedMediaType) return true; if (!hasSupportedMediaType) { if (ArrayBuffer.isView(file.data)) { - return detect(file.data.toString()); + return detect(this.decoder.decode(file.data)); } return detect(file.data); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data; + const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : file.data; try { return await parse(source, { sourceMap: this.sourceMap }); diff --git a/packages/apidom-reference/src/types.ts b/packages/apidom-reference/src/types.ts index e4241cd69b..81d78326b2 100644 --- a/packages/apidom-reference/src/types.ts +++ b/packages/apidom-reference/src/types.ts @@ -28,6 +28,7 @@ export interface Parser { sourceMap: boolean; fileExtensions: string[]; mediaTypes: string[]; + decoder: TextDecoder; canParse(file: File): boolean | Promise; parse(file: File): Promise; From b12d8f3f23a74bd74e85cce3922f23181f1e10b0 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Tue, 20 Sep 2022 10:07:04 +0200 Subject: [PATCH 2/5] fix: tests --- packages/apidom-reference/src/parse/index.ts | 4 +-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../index-browser.ts | 23 +++++------- .../index-node.ts | 7 ++-- .../apidom-reference-parser-json/index.ts | 7 ++-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../index.ts | 7 ++-- .../apidom-reference-parser-yaml-1-2/index.ts | 7 ++-- packages/apidom-reference/src/resolve/util.ts | 8 +++-- packages/apidom-reference/src/types.ts | 2 +- packages/apidom-reference/src/util/File.ts | 18 ++++++++++ .../index.ts | 30 +++++++--------- .../index.ts | 36 +++++++++---------- .../index.ts | 30 +++++++--------- .../index.ts | 34 ++++++++---------- .../apidom-reference-parser-json/index.ts | 27 +++++++------- .../index.ts | 30 +++++++--------- .../index.ts | 30 +++++++--------- .../index.ts | 30 +++++++--------- .../index.ts | 30 +++++++--------- .../apidom-reference-parser-yaml/index.ts | 27 +++++++------- 26 files changed, 196 insertions(+), 240 deletions(-) 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 255a57db5b..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 c339de5a40..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 8501074977..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 87765a39c6..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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..70708452b1 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 @@ -21,13 +21,12 @@ const BinaryParser: stampit.Stamp = stampit(Parser, { this.fileExtensions.length === 0 ? true : this.fileExtensions.includes(file.extension); if (!hasSupportedFileExtension) return false; - return typeof file.data === 'string' || ArrayBuffer.isView(file.data); + return typeof file.data === 'string' || Buffer.isBuffer(file.data); }, async parse(file: IFile): Promise { try { - const base64String = Buffer.isBuffer(file.data) - ? file.data.toString('base64') - : Buffer.from(file.data).toString('base64'); + // @ts-ignore + const base64String = 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 8ab1c1f2d3..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 9a6d0288e4..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 6960d4a612..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 474d547758..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 821a4ed471..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 66ebf7d34d..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(this.decoder.decode(file.data)); - } - return detect(file.data); + return detect(file.toString()); } return false; }, async parse(file: IFile): Promise { - const source = ArrayBuffer.isView(file.data) ? this.decoder.decode(file.data) : 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 81d78326b2..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; } 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-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)); }); }); From 33bbe54d88a798bb9e7322acf490155d7d7c50f5 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Tue, 20 Sep 2022 10:14:12 +0200 Subject: [PATCH 3/5] refactor: remove decoder --- packages/apidom-reference/src/parse/parsers/Parser.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/apidom-reference/src/parse/parsers/Parser.ts b/packages/apidom-reference/src/parse/parsers/Parser.ts index e7e2b2de2e..1185f6ad56 100644 --- a/packages/apidom-reference/src/parse/parsers/Parser.ts +++ b/packages/apidom-reference/src/parse/parsers/Parser.ts @@ -24,10 +24,6 @@ const Parser = stampit({ * List of supported media types. */ mediaTypes: [], - /** - * Transforms array buffers into strings. - */ - decoder: new TextDecoder('utf-8'), }, init( this: IParser, @@ -36,14 +32,12 @@ const Parser = stampit({ sourceMap = this.sourceMap, fileExtensions = this.fileExtensions, mediaTypes = this.mediaTypes, - decoder = this.decoder, } = {}, ) { this.allowEmpty = allowEmpty; this.sourceMap = sourceMap; this.fileExtensions = fileExtensions; this.mediaTypes = mediaTypes; - this.decoder = decoder; }, methods: { async canParse(): Promise { From 6d4d8f32710b3cdb84f68d0d1121693f8bcac658 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Tue, 20 Sep 2022 10:55:40 +0200 Subject: [PATCH 4/5] refactor: simplify --- .../index-node.ts | 12 +- .../index-browser.ts | 122 ++++++++++++++++++ .../{index.ts => index-node.ts} | 30 ++--- 3 files changed, 144 insertions(+), 20 deletions(-) create mode 100644 packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/index-browser.ts rename packages/apidom-reference/test/parse/parsers/apidom-reference-parser-binary/{index.ts => index-node.ts} (81%) 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 70708452b1..126a4c3fc3 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,13 +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' || Buffer.isBuffer(file.data); + return hasSupportedFileExtension; }, async parse(file: IFile): Promise { + let base64String: string; + try { // @ts-ignore - const base64String = Buffer.from(file.data).toString('base64'); + base64String = Buffer.from(file.data).toString('base64'); + } catch { + base64String = Buffer.from(file.data.toString()).toString('base64'); + } + + try { const parseResultElement = new ParseResultElement(); if (base64String.length !== 0) { 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'))); }); }); From 2d5a0e5d099ff4641a2d69f75ff8f968a2245898 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Tue, 20 Sep 2022 10:57:54 +0200 Subject: [PATCH 5/5] test: fix --- .../parse/parsers/apidom-reference-parser-binary/index-node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 126a4c3fc3..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 @@ -29,7 +29,7 @@ const BinaryParser: stampit.Stamp = stampit(Parser, { // @ts-ignore base64String = Buffer.from(file.data).toString('base64'); } catch { - base64String = Buffer.from(file.data.toString()).toString('base64'); + base64String = Buffer.from(file.toString()).toString('base64'); } try {