From 604c268199d6e3b6e63fcb02f908fc5dded314cd Mon Sep 17 00:00:00 2001 From: Viacheslav Turovskyi Date: Sat, 17 Aug 2024 09:35:15 +0000 Subject: [PATCH] remove `Parser` --- src/document.ts | 2 +- src/index.ts | 33 +-- src/parser.ts | 2 +- src/spec-types.ts | 458 ++++++++++++++++++++++++++++++++++++++++ src/types.ts | 8 - src/util.ts | 2 +- tests/lib/index.spec.ts | 12 +- 7 files changed, 465 insertions(+), 52 deletions(-) create mode 100644 src/spec-types.ts delete mode 100644 src/types.ts diff --git a/src/document.ts b/src/document.ts index 7ba12f0..2d48f6c 100644 --- a/src/document.ts +++ b/src/document.ts @@ -1,6 +1,6 @@ import yaml from 'js-yaml'; -import type { AsyncAPIObject } from './types'; +import type { AsyncAPIObject } from './spec-types'; /** * @class diff --git a/src/index.ts b/src/index.ts index fd0eed1..b3ee3d0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ import path from 'path'; import { merge } from 'lodash'; -import { Parser } from '@asyncapi/parser'; import { resolve, versionCheck, @@ -10,8 +9,8 @@ import { import { Document } from './document'; -import type { AsyncAPIObject, Options } from './types'; -export type { AsyncAPIObject, Options } from './types'; +import type { AsyncAPIObject, Options } from './spec-types'; +export type { AsyncAPIObject, Options } from './spec-types'; // remember the directory where execution of the program started const originDir = String(process.cwd()); @@ -93,9 +92,6 @@ export default async function bundle( options: Options = {} ) { let bundledDocument: any = {}; - let validationResult: any = []; - - const parser = new Parser(); // if one string was passed, convert it to an array if (typeof files === 'string') { @@ -129,31 +125,6 @@ export default async function bundle( // properties into a familiar form. bundledDocument = orderPropsAccToAsyncAPISpec(bundledDocument); - // Option `noValidation: true` is used by the testing system, which - // intentionally feeds Bundler wrong AsyncAPI Documents, thus it is not - // documented. - if (!options.noValidation) { - validationResult = await parser.validate( - JSON.parse(JSON.stringify(bundledDocument)) - ); - } - - // If Parser's `validate()` function returns a non-empty array with at least - // one `severity: 0`, that means there was at least one error during - // validation, not a `warning: 1`, `info: 2`, or `hint: 3`. Thus, array's - // elements with `severity: 0` are outputted as a list of remarks, and the - // program throws. - if ( - validationResult.length !== 0 && - validationResult.map((element: any) => element.severity).includes(0) - ) { - console.log( - 'Validation of the resulting AsyncAPI Document failed.\nList of remarks:\n', - validationResult.filter((element: any) => element.severity === 0) - ); - throw new Error(); - } - // return to the starting directory before finishing the execution if (options.baseDir) { process.chdir(originDir); diff --git a/src/parser.ts b/src/parser.ts index b1b1f20..443ce7b 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,7 +1,7 @@ import $RefParser from '@apidevtools/json-schema-ref-parser'; import type { ParserOptions as $RefParserOptions } from '@apidevtools/json-schema-ref-parser'; -import type { AsyncAPIObject, Options as BundlerOptions } from './types'; +import type { AsyncAPIObject, Options as BundlerOptions } from './spec-types'; let RefParserOptions: $RefParserOptions; diff --git a/src/spec-types.ts b/src/spec-types.ts new file mode 100644 index 0000000..59c8520 --- /dev/null +++ b/src/spec-types.ts @@ -0,0 +1,458 @@ +import type { JSONSchema7Version, JSONSchema7TypeName, JSONSchema7Type } from 'json-schema'; + +export type AsyncAPIVersion = string; +export type Identifier = string; +export type DefaultContentType = string; + +export interface AsyncAPIObject extends SpecificationExtensions { + asyncapi: AsyncAPIVersion; + id?: Identifier; + info: InfoObject; + defaultContentType?: DefaultContentType; + servers?: ServersObject; + channels: ChannelsObject; + components?: ComponentsObject; + tags?: TagsObject; + externalDocs?: ExternalDocumentationObject; +} + +export interface InfoObject extends SpecificationExtensions { + title: string; + version: string; + description?: string; + termsOfService?: string; + contact?: ContactObject; + license?: LicenseObject; +} + +export interface ContactObject extends SpecificationExtensions { + name?: string; + url?: string; + email?: string; +} + +export interface LicenseObject extends SpecificationExtensions { + name: string; + url?: string; +} + +export type ServersObject = Record; + +export interface ServerObject extends SpecificationExtensions { + url: string; + protocol: string; + protocolVersion?: string; + description?: string; + variables?: Record; + security?: Array; + bindings?: ServerBindingsObject | ReferenceObject; +} + +export interface ServerVariableObject extends SpecificationExtensions { + enum?: Array; + default?: string; + description?: string; + examples?: Array; +} + +export interface ServerBindingsObject extends SpecificationExtensions { + http?: Binding; + ws?: Binding; + kafka?: Binding; + anypointmq?: Binding; + amqp?: Binding; + amqp1?: Binding; + mqtt?: Binding; + mqtt5?: Binding; + nats?: Binding; + jms?: Binding; + sns?: Binding; + sqs?: Binding; + stomp?: Binding; + redis?: Binding; + mercure?: Binding; + ibmmq?: Binding; +} + +export type ChannelsObject = Record; + +export interface ChannelObject extends SpecificationExtensions { + description?: string; + servers?: Array; + subscribe?: OperationObject; + publish?: OperationObject; + parameters?: ParametersObject; + bindings?: ChannelBindingsObject | ReferenceObject; +} + +export interface ChannelBindingsObject extends SpecificationExtensions { + http?: Binding; + ws?: Binding; + kafka?: Binding; + anypointmq?: Binding; + amqp?: Binding; + amqp1?: Binding; + mqtt?: Binding; + mqtt5?: Binding; + nats?: Binding; + jms?: Binding; + sns?: Binding; + sqs?: Binding; + stomp?: Binding; + redis?: Binding; + mercure?: Binding; + ibmmq?: Binding; +} + +export interface OperationObject extends OperationTraitObject, SpecificationExtensions { + message?: MessageObject | ReferenceObject | { oneOf: Array }; + traits?: Array; +} + +export interface OperationTraitObject extends SpecificationExtensions { + operationId?: string; + summary?: string; + description?: string; + security?: Array; + tags?: TagsObject; + externalDocs?: ExternalDocumentationObject; + bindings?: OperationBindingsObject | ReferenceObject; +} + +export interface OperationBindingsObject extends SpecificationExtensions { + http?: Binding; + ws?: Binding; + kafka?: Binding; + anypointmq?: Binding; + amqp?: Binding; + amqp1?: Binding; + mqtt?: Binding; + mqtt5?: Binding; + nats?: Binding; + jms?: Binding; + sns?: Binding; + sqs?: Binding; + stomp?: Binding; + redis?: Binding; + mercure?: Binding; + ibmmq?: Binding; +} + +export type ParametersObject = Record; + +export interface ParameterObject extends SpecificationExtensions { + description?: string; + schema?: SchemaObject; + location?: string; +} + +export interface MessageObject extends MessageTraitObject, SpecificationExtensions { + payload?: any; + traits?: Array; +} + +export interface MessageTraitObject extends SpecificationExtensions { + messageId?: string; + headers?: SchemaObject; + correlationId?: CorrelationIDObject | ReferenceObject; + schemaFormat?: string; + contentType?: string; + name?: string; + title?: string; + summary?: string; + description?: string; + tags?: TagsObject; + externalDocs?: ExternalDocumentationObject; + bindings?: MessageBindingsObject | ReferenceObject; + examples?: Array; +} + +export interface MessageExampleObject extends SpecificationExtensions { + name?: string; + summary?: string; + headers?: Record; + payload?: any; +} + +export interface MessageBindingsObject extends SpecificationExtensions { + http?: Binding; + ws?: Binding; + kafka?: Binding; + anypointmq?: Binding; + amqp?: Binding; + amqp1?: Binding; + mqtt?: Binding; + mqtt5?: Binding; + nats?: Binding; + jms?: Binding; + sns?: Binding; + sqs?: Binding; + stomp?: Binding; + redis?: Binding; + mercure?: Binding; + ibmmq?: Binding; +} + +export type TagsObject = Array; + +export interface TagObject extends SpecificationExtensions { + name: string; + description?: string; + externalDocs?: ExternalDocumentationObject; +} + +export interface ExternalDocumentationObject extends SpecificationExtensions { + url: string; + description?: string; +} + +export interface ComponentsObject extends SpecificationExtensions { + channels?: Record; + servers?: Record; + schemas?: Record; + messages?: Record; + securitySchemes?: Record; + parameters?: Record; + serverVariables?: Record; + correlationIds?: Record; + operationTraits?: Record; + messageTraits?: Record; + serverBindings?: Record; + channelBindings?: Record; + operationBindings?: Record; + messageBindings?: Record; +} + +export type SchemaObject = AsyncAPISchemaObject | ReferenceObject; + +export type AsyncAPISchemaObject = AsyncAPISchemaDefinition | boolean; +export interface AsyncAPISchemaDefinition extends SpecificationExtensions { + $id?: string; + $schema?: JSONSchema7Version; + $comment?: string; + + type?: JSONSchema7TypeName | JSONSchema7TypeName[]; + enum?: JSONSchema7Type[]; + const?: JSONSchema7Type; + + multipleOf?: number; + maximum?: number; + exclusiveMaximum?: number; + minimum?: number; + exclusiveMinimum?: number; + + maxLength?: number; + minLength?: number; + pattern?: string; + + items?: AsyncAPISchemaObject | AsyncAPISchemaObject[]; + additionalItems?: AsyncAPISchemaObject; + maxItems?: number; + minItems?: number; + uniqueItems?: boolean; + contains?: AsyncAPISchemaObject; + + maxProperties?: number; + minProperties?: number; + required?: string[]; + properties?: { + [key: string]: AsyncAPISchemaObject; + }; + patternProperties?: { + [key: string]: AsyncAPISchemaObject; + }; + additionalProperties?: AsyncAPISchemaObject; + dependencies?: { + [key: string]: AsyncAPISchemaObject | string[]; + }; + propertyNames?: AsyncAPISchemaObject; + + if?: AsyncAPISchemaObject; + then?: AsyncAPISchemaObject; + else?: AsyncAPISchemaObject; + + allOf?: AsyncAPISchemaObject[]; + anyOf?: AsyncAPISchemaObject[]; + oneOf?: AsyncAPISchemaObject[]; + not?: AsyncAPISchemaObject; + + format?: string; + + contentMediaType?: string; + contentEncoding?: string; + + definitions?: { + [key: string]: AsyncAPISchemaObject; + }; + + title?: string; + description?: string; + default?: JSONSchema7Type; + readOnly?: boolean; + writeOnly?: boolean; + examples?: Array; + + discriminator?: string; + externalDocs?: ExternalDocumentationObject; + deprecated?: boolean; + [keyword: string]: any; +} + +export interface SecuritySchemeObject extends SpecificationExtensions { + type: SecuritySchemeType; + description?: string; + name?: string; + in?: 'user' | 'password' | 'query' | 'header' | 'cookie'; + scheme?: string; + bearerFormat?: string; + flows?: OAuthFlowsObject; + openIdConnectUrl?: string; +} + +export type SecuritySchemeType = + | 'userPassword' + | 'apiKey' + | 'X509' + | 'symmetricEncryption' + | 'asymmetricEncryption' + | 'httpApiKey' + | 'http' + | 'oauth2' + | 'openIdConnect' + | 'plain' + | 'scramSha256' + | 'scramSha512' + | 'gssapi'; + +export type SecuritySchemaLocation = + | 'user' + | 'password' + | 'query' + | 'header' + | 'header' + | 'cookie'; + +export interface SecuritySchemeObjectBase extends SpecificationExtensions { + description?: string; +} + +export interface SecuritySchemeObjectUserPassword extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'userPassword'; +} + +export interface SecuritySchemeObjectApiKey extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'apiKey'; + in: 'user' | 'password'; +} + +export interface SecuritySchemeObjectX509 extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'X509'; +} + +export interface SecuritySchemeObjectSymetricEncryption extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'symmetricEncryption'; +} + +export interface SecuritySchemeObjectAsymetricEncryption extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'asymmetricEncryption'; +} + +export interface SecuritySchemeObjectHttpApiKey extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'httpApiKey'; + name: string; + in: 'query' | 'header' | 'cookie'; +} + +export interface SecuritySchemeObjectHttp extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'http'; + scheme: string; + bearerFormat?: string; +} + +export interface SecuritySchemeObjectOauth2 extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'oauth2'; + flows: OAuthFlowsObject; +} + +export interface SecuritySchemeObjectOpenIdConnect extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'openIdConnect'; + openIdConnectUrl: string; +} + +export interface SecuritySchemeObjectPlain extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'plain'; +} + +export interface SecuritySchemeObjectScramSha256 extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'scramSha256'; +} + +export interface SecuritySchemeObjectScramSha512 extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'scramSha512'; +} + +export interface SecuritySchemeObjectGssapi extends SecuritySchemeObjectBase, SpecificationExtensions { + type: 'gssapi'; +} + +export interface OAuthFlowsObject extends SpecificationExtensions { + implicit?: OAuthFlowObjectImplicit; + password?: OAuthFlowObjectPassword; + clientCredentials?: OAuthFlowObjectClientCredentials; + authorizationCode?: OAuthFlowObjectAuthorizationCode; +} + +export type OAuthFlowObject = + & OAuthFlowObjectImplicit + & OAuthFlowObjectPassword + & OAuthFlowObjectClientCredentials + & OAuthFlowObjectAuthorizationCode; + +export interface OAuthFlowObjectBase extends SpecificationExtensions { + refreshUrl?: string; + scopes: Record; +} + +export interface OAuthFlowObjectImplicit extends OAuthFlowObjectBase, SpecificationExtensions { + authorizationUrl: string; +} + +export interface OAuthFlowObjectPassword extends OAuthFlowObjectBase, SpecificationExtensions { + tokenUrl: string; +} + +export interface OAuthFlowObjectClientCredentials extends OAuthFlowObjectBase, SpecificationExtensions { + tokenUrl: string; +} + +export interface OAuthFlowObjectAuthorizationCode extends OAuthFlowObjectBase, SpecificationExtensions { + authorizationUrl: string; + tokenUrl: string; +} + +export type SecurityRequirementObject = Record>; + +export interface CorrelationIDObject extends SpecificationExtensions { + location: string; + description?: string; +} + +export interface Binding { + bindingVersion?: string; +} + +export interface SpecificationExtensions { + [extension: `x-${string}`]: SpecificationExtension; +} + +export type SpecificationExtension = T; + +export interface ReferenceObject { + $ref: string; +} + +export interface Options { + base?: string; + baseDir?: string; + xOrigin?: boolean; +} diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 8409f5a..0000000 --- a/src/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type { AsyncAPIObject } from '@asyncapi/parser/esm/types'; - -export interface Options { - base?: string; - baseDir?: string; - xOrigin?: boolean; - noValidation?: boolean; // used by the testing system, thus not documented -} diff --git a/src/util.ts b/src/util.ts index 7520543..94e57cd 100644 --- a/src/util.ts +++ b/src/util.ts @@ -6,7 +6,7 @@ import structuredClone from '@ungap/structured-clone'; import { parse } from './parser'; import { ParserError } from './errors'; -import type { AsyncAPIObject, Options } from './types'; +import type { AsyncAPIObject, Options } from './spec-types'; /** * @private diff --git a/tests/lib/index.spec.ts b/tests/lib/index.spec.ts index 4b3ac43..c2329e8 100644 --- a/tests/lib/index.spec.ts +++ b/tests/lib/index.spec.ts @@ -15,7 +15,6 @@ describe('[integration testing] bundler should ', () => { const files = ['./tests/camera.yml', './tests/audio.yml']; const response = await bundle(files, { base: path.resolve(process.cwd(), './tests/base.yml'), - noValidation: true, }); expect(response).toBeDefined(); }); @@ -29,7 +28,6 @@ describe('[integration testing] bundler should ', () => { expect( await bundle(files, { xOrigin: true, - noValidation: true, }) ).resolves; }); @@ -43,7 +41,6 @@ describe('[integration testing] bundler should ', () => { expect( await bundle(files, { xOrigin: true, - noValidation: true, }) ).resolves; }); @@ -56,7 +53,6 @@ describe('[integration testing] bundler should ', () => { xOrigin: true, base: 'base.yml', baseDir: path.resolve(process.cwd(), './tests'), - noValidation: true, }); }).rejects.toThrow(JSONParserError); }); @@ -71,7 +67,6 @@ describe('[integration testing] bundler should ', () => { await bundle(files, { base: path.resolve(process.cwd(), './tests/base-option/base.yaml'), xOrigin: true, - noValidation: true, }) ).resolves; }); @@ -79,7 +74,7 @@ describe('[integration testing] bundler should ', () => { test('should be able to change the baseDir folder', async () => { const files = ['main.yaml']; expect( - await bundle(files, { baseDir: './tests/specfiles', noValidation: true }) + await bundle(files, { baseDir: './tests/specfiles' }) ).resolves; }); @@ -303,7 +298,6 @@ describe('[integration testing] bundler should ', () => { const document = await bundle(files, { base: 'asyncapi/index.yaml', baseDir: path.resolve(process.cwd(), 'tests/nested-dirs-mixed'), - noValidation: true, }); expect(document.json()).toMatchObject(resultingObject); @@ -380,9 +374,7 @@ describe('[integration testing] bundler should ', () => { const files = 'tests/gh-185.yaml'; - const document = await bundle(files, { - noValidation: true, - }); + const document = await bundle(files); expect(document.json()).toMatchObject(resultingObject); });