Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Upgrade AsyncAPI Parser #112

Merged
merged 3 commits into from
Aug 10, 2020
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
1,764 changes: 645 additions & 1,119 deletions library/package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,17 @@
"build": "tsc && npm run copyCss",
"test": "jest --detectOpenHandles",
"testWatch": "jest --detectOpenHandles --watch",
"copyCss": "cp -r ./src/styles ./lib/styles",
"copyCss": "cp -r ./src/styles ./lib",
"prepare": "npm run build",
"prepack": "cp ../README.md ./README.md && cp ../LICENSE ./LICENSE",
"postpack": "rm -rf ./README.md && rm -rf ./LICENSE",
"get-version": "echo $npm_package_version"
},
"dependencies": {
"@asyncapi/parser": "0.16.2",
"@asyncapi/parser": "^0.33.0",
"constate": "^1.2.0",
"dompurify": "^1.0.11",
"json-schema-ref-parser": "^9.0.6",
"markdown-it": "^9.1.0",
"merge": "^1.2.1",
"openapi-sampler": "^1.0.0-beta.15",
Expand Down
4 changes: 2 additions & 2 deletions library/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export const CONTENT_TYPES_SITE =
export const COLLAPSE_ALL_TEXT = 'Collapse All';
export const EXPAND_ALL_TEXT = 'Expand All';

export const UNSUPPORTED_SCHEMA_VERSION =
'AsyncAPI version is unsupported, use version 2.0 or higher';
export const VALIDATION_ERRORS_TYPE =
'https://github.com/asyncapi/parser-js/validation-errors';
export const SERVERS = 'Servers';

export const ONE_OF_PAYLOADS_TEXT = 'One of those payloads:';
Expand Down
4 changes: 2 additions & 2 deletions library/src/containers/AsyncApi/AsyncApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
AsyncAPI,
isFetchingSchemaInterface,
NullableAsyncApi,
ParserError,
ErrorObject,
AsyncApiProps,
PropsSchema,
} from '../../types';
Expand All @@ -24,7 +24,7 @@ import { SchemasComponent } from '../Schemas/Schemas';

interface AsyncAPIState {
validatedSchema: NullableAsyncApi;
error?: ParserError;
error?: ErrorObject;
}

const defaultAsyncApi: AsyncAPI = {
Expand Down
43 changes: 21 additions & 22 deletions library/src/containers/Error/Error.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,64 @@
import React from 'react';
import { ErrorObject } from 'ajv';

import { bemClasses } from '../../helpers';
import { ParserError } from '../../types';
import { Toggle } from '../../components';
import { ERROR_TEXT } from '../../constants';
import { ErrorObject, ValidationError } from '../../types';

const renderErrors = (
error: ParserError['validationError'],
): React.ReactNode => {
if (!error) {
const renderErrors = (errors: ValidationError[]): React.ReactNode => {
if (!errors) {
return null;
}

return error
.map((singleError: ErrorObject, index: number) => {
const formattedError = formatErrors(singleError);
return errors
.map((singleError: ValidationError, index: number) => {
const formattedError = formatError(singleError);

if (!formattedError) {
return null;
}
return (
<code className={bemClasses.element(`error-content-code`)} key={index}>
{formattedError}
</code>
<div>
<code
className={bemClasses.element(`error-content-code`)}
key={index}
>
{formattedError}
</code>
</div>
);
})
.filter(Boolean);
};

export const formatErrors = (singleError: ErrorObject): string => {
const { message, dataPath, params, keyword } = singleError;

const info = Object.values(params)[0];
return `${dataPath} ${message}${keyword === 'type' ? '' : `: ${info}`}`;
export const formatError = (singleError: ValidationError): string => {
return singleError.title;
};

interface Props {
error: ParserError;
error: ErrorObject;
}

export const ErrorComponent: React.FunctionComponent<Props> = ({ error }) => {
if (!error) {
return null;
}
const className = `error`;
const { message, validationError } = error;
const { title, validationErrors } = error;

const header = (
<h2>
{ERROR_TEXT}: {message}
{ERROR_TEXT}: {title}
</h2>
);

return (
<section className={bemClasses.element(className)}>
<Toggle header={header} className={className}>
{!!validationError && (
{validationErrors && validationErrors.length && (
<div className={bemClasses.element(`${className}-body`)}>
<pre className={bemClasses.element(`${className}-body-pre`)}>
{renderErrors(validationError)}
{renderErrors(validationErrors)}
</pre>
</div>
)}
Expand Down
66 changes: 0 additions & 66 deletions library/src/containers/Error/__tests__/error.test.ts

This file was deleted.

48 changes: 0 additions & 48 deletions library/src/helpers/__tests__/parser.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import {
ParserErrorUnsupportedVersion,
ParserErrorNoJS,
} from '@asyncapi/parser';
import { Options as ParserOptions } from 'json-schema-ref-parser';

import { Parser } from '../parser';
Expand All @@ -28,28 +24,6 @@ const mockParseURLErr = <T extends Error>(err: T) =>
describe('Parser', () => {
describe('parse', () => {
const parseURL = mockParseURLErr(new Error('not implemented'));
test.each`
error | desc
${new ParserErrorUnsupportedVersion('err')} | ${'ParserErrorUnsupportedVersion is thrown'}
${new ParserErrorNoJS('test error')} | ${'ParserErrorNoJS is thrown'}
${new Error('other error')} | ${'other error'}
${{
message: 'version',
parsedJSON: {
asyncapi: '1',
},
}} | ${'invalid version is returned'}
`(
'should return error when $desc',
async <R extends Error, T extends { error: R; desc: string }>(err: T) => {
const parse = mockParseErr(err.error);
const parser = new Parser(parse, parseURL);
await parser.parse('mocked').then(result => {
expect(result.error).toBeTruthy();
expect(result.data).toBeFalsy();
});
},
);

test('should return no errors and data when doc is valid', async () => {
const doc: AsyncAPI = (validDoc as any) as AsyncAPI;
Expand All @@ -64,28 +38,6 @@ describe('Parser', () => {

describe('parseURL', () => {
const parse = mockParseErr(new Error('not implemented'));
test.each`
error | desc
${new ParserErrorUnsupportedVersion('err')} | ${'ParserErrorUnsupportedVersion is thrown'}
${new ParserErrorNoJS('test error')} | ${'ParserErrorNoJS is thrown'}
${new Error('other error')} | ${'other error'}
${{
message: 'version',
parsedJSON: {
asyncapi: '1',
},
}} | ${'invalid version is returned'}
`(
'should return error when $desc',
async <R extends Error, T extends { error: R; desc: string }>(err: T) => {
const parseURL = mockParseURLErr(err.error);
const parser = new Parser(parse, parseURL);
await parser.parseFromUrl({ url: 'mocked' }).then(result => {
expect(result.error).toBeTruthy();
expect(result.data).toBeFalsy();
});
},
);

test('should return no errors and data when doc is valid', async () => {
const doc: AsyncAPI = (validDoc as any) as AsyncAPI;
Expand Down
28 changes: 7 additions & 21 deletions library/src/helpers/parser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import {
ParserErrorUnsupportedVersion,
ParserErrorNoJS,
} from '@asyncapi/parser';
import { Options as ParserOptions } from 'json-schema-ref-parser';

import { ParserReturn, FetchingSchemaInterface } from '../types';
import { ErrorObject, ParserReturn, FetchingSchemaInterface } from '../types';

import { UNSUPPORTED_SCHEMA_VERSION } from '../constants';
import { VALIDATION_ERRORS_TYPE } from '../constants';

type ParseDocument = (
content: string | any,
Expand Down Expand Up @@ -56,25 +52,15 @@ export class Parser {
}
}

private handleError = (err: any): ParserReturn => {
if (
err instanceof ParserErrorUnsupportedVersion ||
err instanceof ParserErrorNoJS
) {
return { data: null, error: { message: err.message } };
}

if (err.parsedJSON && err.parsedJSON.asyncapi.startsWith('1')) {
private handleError = (err: ErrorObject): ParserReturn => {
if (err.type === VALIDATION_ERRORS_TYPE) {
return {
data: null,
error: { message: UNSUPPORTED_SCHEMA_VERSION },
data: err.parsedJSON || null,
error: err,
};
}

return {
data: err.parsedJSON || null,
error: { message: err.message, validationError: err.errors },
};
return { data: null, error: err };
};

private extractDocument = (data: any): ParserReturn => {
Expand Down
44 changes: 36 additions & 8 deletions library/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ErrorObject } from 'ajv';
import { ConfigInterface } from './config';

// Helpers
Expand Down Expand Up @@ -374,7 +373,7 @@ export type NullableAsyncApi = AsyncAPI | null;

export interface AsyncApiState {
validatedSchema: NullableAsyncApi;
error?: ParserError;
error?: ErrorObject;
}

export function isFetchingSchemaInterface(
Expand All @@ -388,14 +387,9 @@ export interface FetchingSchemaInterface {
requestOptions?: RequestInit;
}

export interface ParserError {
message: string;
validationError?: ErrorObject[] | null;
}

export interface ParserReturn {
data: NullableAsyncApi;
error?: ParserError;
error?: ErrorObject;
}

export type TableColumnName = string;
Expand All @@ -406,3 +400,37 @@ export interface Identifier {
id: string;
toKebabCase?: boolean;
}

export interface ValidationError {
title: string;
jsonPointer: string;
startLine: number;
startColumn: number;
startOffset: number;
endLine: number;
endColumn: number;
endOffset: number;
}

export interface ErrorObject {
type: string;
title: string;
detail?: string;
parsedJSON?: any;
validationErrors?: ValidationError[];
location?: {
startLine: number;
startColumn: number;
startOffset: number;
};
refs?: {
title: string;
jsonPointer: string;
startLine: number;
startColumn: number;
startOffset: number;
endLine: number;
endColumn: number;
endOffset: number;
}[];
}
Loading