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

refactor: add tests for old api #622

Merged
merged 2 commits into from
Sep 22, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/custom-operations/anonymous-naming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function assignNameToComponentMessages(document: AsyncAPIDocumentInterface) {
function assignNameToAnonymousMessages(document: AsyncAPIDocumentInterface) {
let anonymousMessageCounter = 0;
document.messages().forEach(message => {
if (message.name() === undefined && message.extensions().get(xParserMessageName) === undefined) {
if (message.name() === undefined && message.extensions().get(xParserMessageName)?.value() === undefined) {
setExtension(xParserMessageName, `<anonymous-message-${++anonymousMessageCounter}>`, message);
}
});
Expand Down
4 changes: 2 additions & 2 deletions src/iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export enum SchemaTypesToIterate {

export type TraverseOptions = {
callback: TraverseCallback
schemaTypesToIterate: SchemaTypesToIterate[]
schemaTypesToIterate: Array<`${SchemaTypesToIterate}`>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm lost on this 😆 Is this the preferable way? Or it was a bug?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an interpolation of enum values as union. Feature in the TS 4.1, so you can put schemaTypesToIterate as array of normal string (but with values from enum) or SchemaTypesToIterate signature for given enum value.

seenSchemas: Set<any>
}

Expand All @@ -48,7 +48,7 @@ export type TraverseCallback = (schema: SchemaInterface, propOrIndex: string | n
/**
* Go through each channel and for each parameter, and message payload and headers recursively call the callback for each schema.
*/
export function traverseAsyncApiDocument(doc: AsyncAPIDocumentInterface, callback: TraverseCallback, schemaTypesToIterate: SchemaTypesToIterate[] = []) {
export function traverseAsyncApiDocument(doc: AsyncAPIDocumentInterface, callback: TraverseCallback, schemaTypesToIterate: Array<`${SchemaTypesToIterate}`> = []) {
if (schemaTypesToIterate.length === 0) {
schemaTypesToIterate = Object.values(SchemaTypesToIterate);
}
Expand Down
2 changes: 1 addition & 1 deletion src/models/v2/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class AsyncAPIDocument extends BaseModel<v2.AsyncAPIObject> implements As
}

components(): ComponentsInterface {
return new Components(this._json.components || {});
return this.createModel(Components, this._json.components || {}, { pointer: '/components' });
}

extensions(): ExtensionsInterface {
Expand Down
43 changes: 34 additions & 9 deletions src/old-api/asyncapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { Message } from './message';
import { Schema } from './schema';

import { traverseAsyncApiDocument } from './iterator';
import { xParserCircular } from '../constants';
import { stringify, unstringify } from '../stringify';
import { xParserCircular, xParserSpecStringified, xParserSpecParsed } from '../constants';
import { refReplacer, traverseStringifiedData } from '../stringify';

import type { v2 } from '../spec-types';
import type { Operation } from './operation';
Expand Down Expand Up @@ -154,16 +154,41 @@ export class AsyncAPIDocument extends SpecificationExtensionsModel<v2.AsyncAPIOb
return !!this._json[xParserCircular];
}

traverseSchemas(callback: TraverseCallback, schemaTypesToIterate: SchemaTypesToIterate[]) {
traverseSchemas(callback: TraverseCallback, schemaTypesToIterate: Array<`${SchemaTypesToIterate}`> = []) {
traverseAsyncApiDocument(this, callback, schemaTypesToIterate);
}

static stringify(doc: AsyncAPIDocument, space: number): string | undefined {
return stringify(doc, { space });
static stringify(doc: AsyncAPIDocument, space?: number): string | undefined {
const rawDoc = doc.json();
const copiedDoc = { ...rawDoc };
copiedDoc[xParserSpecStringified] = true;
return JSON.stringify(copiedDoc, refReplacer(), space);
}

static parse(doc: string): AsyncAPIDocument | undefined {
const possibleDocument = unstringify(doc);
return possibleDocument ? new AsyncAPIDocument(possibleDocument.json()) : undefined;
static parse(doc: string | Record<string, any>): AsyncAPIDocument | undefined {
let parsedJSON = doc;
if (typeof doc === 'string') {
parsedJSON = JSON.parse(doc);
} else if (typeof doc === 'object') {
// shall copy
parsedJSON = { ...(parsedJSON as Record<string, any>) };
}

// the `doc` must be an AsyncAPI parsed document
if (typeof parsedJSON !== 'object' || !parsedJSON[xParserSpecParsed]) {
throw new Error('Cannot parse invalid AsyncAPI document');
}
// if the `doc` is not stringified via the `stringify` static method then immediately return a model.
if (!parsedJSON[xParserSpecStringified]) {
return new AsyncAPIDocument(parsedJSON as v2.AsyncAPIObject);
}
// remove `x-parser-spec-stringified` extension
delete parsedJSON[String(xParserSpecStringified)];

const objToPath = new Map();
const pathToObj = new Map();
traverseStringifiedData(parsedJSON, undefined, parsedJSON, objToPath, pathToObj);

return new AsyncAPIDocument(parsedJSON as v2.AsyncAPIObject);
}
}
}
4 changes: 2 additions & 2 deletions src/old-api/iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export enum SchemaTypesToIterate {

export type TraverseOptions = {
callback: TraverseCallback
schemaTypesToIterate: SchemaTypesToIterate[]
schemaTypesToIterate: Array<`${SchemaTypesToIterate}`>;
seenSchemas: Set<any>
}

Expand All @@ -47,7 +47,7 @@ export type TraverseCallback = (schema: Schema, propOrIndex: string | number | n
/**
* Go through each channel and for each parameter, and message payload and headers recursively call the callback for each schema.
*/
export function traverseAsyncApiDocument(doc: AsyncAPIDocument, callback: TraverseCallback, schemaTypesToIterate: SchemaTypesToIterate[] = []) {
export function traverseAsyncApiDocument(doc: AsyncAPIDocument, callback: TraverseCallback, schemaTypesToIterate: Array<`${SchemaTypesToIterate}`> = []) {
if (schemaTypesToIterate.length === 0) {
schemaTypesToIterate = Object.values(SchemaTypesToIterate);
}
Expand Down
10 changes: 6 additions & 4 deletions src/old-api/mixins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,20 @@ export function hasDescription(model: Base<{ description?: string }>) {
return Boolean(model.json('description'));
}

export function description(model: Base<{ description?: string }>): string | undefined {
return model.json('description');
export function description(model: Base<{ description?: string }>): string | null {
const description = model.json('description');
return typeof description === 'string' ? description : null;
}

export function hasExternalDocs(model: Base<{ externalDocs?: v2.ExternalDocumentationObject }>): boolean {
return Object.keys(model.json('externalDocs') || {}).length > 0;
}

export function externalDocs(model: Base<{ externalDocs?: v2.ExternalDocumentationObject }>): ExternalDocs | undefined {
if (hasExternalDocs(model)) {
export function externalDocs(model: Base<{ externalDocs?: v2.ExternalDocumentationObject }>): ExternalDocs | null {
if (typeof model.json('externalDocs') === 'object') {
return new ExternalDocs(model.json('externalDocs') as v2.ExternalDocumentationObject);
}
return null;
}

export const extensionsMixins = {
Expand Down
11 changes: 8 additions & 3 deletions src/old-api/schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SpecificationExtensionsModel, createMapOfType, getMapValue, description, hasDescription, hasExternalDocs, externalDocs } from './mixins';
import { xParserCircular, xParserCircularProps } from '../constants';
import { hasRef } from '../utils';

import type { Base } from './base';
import type { v2 } from '../spec-types';
Expand Down Expand Up @@ -117,15 +118,19 @@ export class Schema extends SpecificationExtensionsModel<v2.AsyncAPISchemaObject
additionalProperties() {
if (typeof this._json === 'boolean') return this._json;
const additionalProperties = this.__get('additionalProperties');
if (typeof additionalProperties === 'boolean') return additionalProperties;
if (additionalProperties === undefined) return true;
return new Schema(additionalProperties as any, { parent: this });
if (additionalProperties === null) return false;
return this.__createChild(additionalProperties);
}

additionalItems() {
if (typeof this._json === 'boolean') return this._json;
const additionalItems = this.__get('additionalItems');
if (typeof additionalItems === 'boolean') return additionalItems;
if (additionalItems === undefined) return true;
return new Schema(additionalItems as any, { parent: this });
if (additionalItems === null) return false;
return this.__createChild(additionalItems);
}

patternProperties() {
Expand Down Expand Up @@ -236,7 +241,7 @@ export class Schema extends SpecificationExtensionsModel<v2.AsyncAPISchemaObject
}

isCircular() {
if (this.ext(xParserCircular)) {
if (hasRef(this._json) || this.ext(xParserCircular)) {
return true;
}

Expand Down
128 changes: 64 additions & 64 deletions src/spec-types/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ export interface ServerVariableObject extends SpecificationExtensions {
}

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;
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<string, ChannelObject>;
Expand All @@ -86,22 +86,22 @@ export interface ChannelObject extends SpecificationExtensions {
}

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;
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 {
Expand All @@ -120,22 +120,22 @@ export interface OperationTraitObject extends SpecificationExtensions {
}

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;
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<string, ParameterObject | ReferenceObject>;
Expand Down Expand Up @@ -175,22 +175,22 @@ export interface MessageExampleObject extends SpecificationExtensions {
}

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;
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<TagObject>;
Expand Down
4 changes: 2 additions & 2 deletions src/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function copy(data: Record<string, any>) {
return unstringifiedData;
}

function refReplacer() {
export function refReplacer() {
const modelPaths = new Map();
const paths = new Map();
let init: unknown = null;
Expand Down Expand Up @@ -90,7 +90,7 @@ function refReplacer() {
}

const refRoot = '$ref:$';
function traverseStringifiedData(parent: any, field: string | undefined, root: any, objToPath: Map<unknown, unknown>, pathToObj: Map<unknown, unknown>) {
export function traverseStringifiedData(parent: any, field: string | undefined, root: any, objToPath: Map<unknown, unknown>, pathToObj: Map<unknown, unknown>) {
let objOrPath = parent;
let path = refRoot;

Expand Down