Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/apidom-reference/src/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ 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';

/**
* Parses the given file's contents, using the configured parser plugins.
*/
const parseFile = async (file: IFile, options: IReferenceOptions): Promise<ParseResultElement> => {
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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,12 @@ const ApiDesignSystemsJsonParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,12 @@ const ApiDesignSystemsYamlParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ const AsyncApiJson2Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ const AsyncApiYaml2Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,22 @@ const BinaryParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@ const BinaryParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,12 @@ const JsonParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'syntacticAnalysis'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ const OpenApiJson3_0Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ const OpenApiJson3_1Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'syntacticAnalysis', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ const OpenApiYaml3_0Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ const OpenApiYaml3_1Parser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
const parserOpts = pick(['sourceMap', 'refractorOpts'], this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,12 @@ const YamlParser: stampit.Stamp<IParser> = 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<ParseResultElement> {
const source = ArrayBuffer.isView(file.data) ? file.data.toString() : file.data;
const source = file.toString();

try {
return await parse(source, { sourceMap: this.sourceMap });
Expand Down
8 changes: 6 additions & 2 deletions packages/apidom-reference/src/resolve/util.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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<Buffer> => {
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)) {
Expand Down
3 changes: 2 additions & 1 deletion packages/apidom-reference/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -28,6 +28,7 @@ export interface Parser {
sourceMap: boolean;
fileExtensions: string[];
mediaTypes: string[];
decoder: TextDecoder;

canParse(file: File): boolean | Promise<boolean>;
parse(file: File): Promise<ParseResultElement>;
Expand Down
18 changes: 18 additions & 0 deletions packages/apidom-reference/src/util/File.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import stampit from 'stampit';
import { type } from 'ramda';
import { isString } from 'ramda-adjunct';

import * as url from './url';
Expand Down Expand Up @@ -36,6 +37,23 @@ const File: stampit.Stamp<IFile> = 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);
},
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -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 () {
Expand Down Expand Up @@ -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));
});
});

Expand Down
Loading