diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 00000000..16365be9 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1 @@ +sonar.exclusions=test/**/* diff --git a/API.md b/API.md index 894e7c21..9b79e4b8 100644 --- a/API.md +++ b/API.md @@ -10,6 +10,8 @@ user will only interact with this class. here we generate different kind of repo ## Functions
+
findAllComponents(optimizableComponentGroup)
+
findDuplicateComponents(optimizableComponentGroup)
hasParent()
@@ -33,6 +35,8 @@ user will only interact with this class. here we generate different kind of repo
Rules : Object
+
DisableOptimizationFor : Object
+
Options : Object
@@ -76,6 +80,16 @@ This function is used to get the optimized document after seeing the report. | --- | --- | --- | | [Options] | [Options](#Options) | the options are a way to customize the final output. | + + +## findAllComponents(optimizableComponentGroup) ⇒ +**Kind**: global function +**Returns**: A list of optimization report elements. + +| Param | Description | +| --- | --- | +| optimizableComponentGroup | all AsyncAPI Specification-valid components. | + ## findDuplicateComponents(optimizableComponentGroup) ⇒ @@ -84,7 +98,7 @@ This function is used to get the optimized document after seeing the report. | Param | Description | | --- | --- | -| optimizableComponentGroup | components that you want to analyze for duplicates. | +| optimizableComponentGroup | all AsyncAPI Specification-valid components that you want to analyze for duplicates. | @@ -132,7 +146,18 @@ Converts JSON or YAML string object. | --- | --- | --- | | [reuseComponents] | Boolean | whether to reuse components from `components` section or not. Defaults to `true`. | | [removeComponents] | Boolean | whether to remove un-used components from `components` section or not. Defaults to `true`. | -| [moveDuplicatesToComponents] | Boolean | whether to move duplicated components to the `components` section or not. Defaults to `true`. | +| [moveAllToComponents] | Boolean | whether to move all AsyncAPI Specification-valid components to the `components` section or not. Defaults to `true`. | +| [moveDuplicatesToComponents] | Boolean | whether to move duplicated components to the `components` section or not. Defaults to `false`. | + + + +## DisableOptimizationFor : Object +**Kind**: global typedef +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| [schema] | Boolean | whether object `schema` should be excluded from the process of optimization (`true` instructs **not** to add calculated `schemas` to the optimized AsyncAPI Document.) | @@ -144,3 +169,5 @@ Converts JSON or YAML string object. | --- | --- | --- | | [rules] | [Rules](#Rules) | the list of rules that specifies which type of optimizations should be applied. | | [output] | String | specifies which type of output user wants, `'JSON'` or `'YAML'`. Defaults to `'YAML'`; | +| [disableOptimizationFor] | [DisableOptimizationFor](#DisableOptimizationFor) | the list of objects that should be excluded from the process of optimization. | + diff --git a/README.md b/README.md index cb67f30b..08e7de05 100644 --- a/README.md +++ b/README.md @@ -10,228 +10,195 @@ AsyncAPI offers many ways to reuse certain parts of the document like messages o - [Testing](#testing) - [Usage](#usage) - * [Node.js](#nodejs) - * [Generating report](#generating-report) - * [Applying the suggested changes](#applying-the-suggested-changes) + - [Node.js](#nodejs) + - [Generating report](#generating-report) + - [Applying the suggested changes](#applying-the-suggested-changes) - [API documentation](#api-documentation) ## Testing -1) Clone the project - `git clone https://github.com/asyncapi/optimizer.git` -2) Install the dependencies - `npm i` -3) for a quick check you can run `npm run example`. You can open `examples/index.js` modify it or add your own AsyncAPI document for optimization. + +1. Clone the project + `git clone https://github.com/asyncapi/optimizer.git` +2. Install the dependencies + `npm i` +3. for a quick check you can run `npm run example`. You can open `examples/index.js` modify it or add your own AsyncAPI document for optimization. ## Usage ### Node.js ```typescript -import { Optimizer } from '@asyncapi/optimizer'; -import type { Report } from '@asyncapi/optimizer'; +import { Optimizer } from '@asyncapi/optimizer' +import type { Report } from '@asyncapi/optimizer' -const yaml =` -asyncapi: 2.0.0 +const yaml = ` +asyncapi: 3.0.0 info: - title: Streetlights API - version: '1.0.0' - + title: Example Service + version: 1.0.0 + description: Example Service. +servers: + production: + host: 'test.mosquitto.org:{port}' + protocol: mqtt + description: Test broker + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' +operations: + user/deleteAccount.subscribe: + action: send + channel: + $ref: '#/channels/commentLikedChannel' channels: - - smartylighting/event/{streetlightId}/lighting/measured: - parameters: - #this parameter is duplicated. it can be moved to components and ref-ed from here. - streetlightId: - schema: - type: string - subscribe: - operationId: receiveLightMeasurement - traits: - - bindings: - kafka: - clientId: my-app-id - message: - name: lightMeasured - title: Light measured - contentType: application/json - traits: - - headers: - type: object - properties: - my-app-header: - type: integer - minimum: 0 - maximum: 100 + commentLikedChannel: + address: comment/liked + messages: + commentLikedMessage: + description: Message that is being sent when a comment has been liked by someone. payload: type: object + title: commentLikedPayload properties: - lumens: - type: integer - minimum: 0 - #full form is used, we can ref it to: #/components/schemas/sentAt - sentAt: + commentId: type: string - format: date-time - - smartylighting/action/{streetlightId}/turn/on: - parameters: - streetlightId: - schema: - type: string - publish: - operationId: turnOn - traits: - - bindings: - kafka: - clientId: my-app-id - message: - name: turnOnOff - title: Turn on/off - traits: - - headers: - type: object - properties: - my-app-header: - type: integer - minimum: 0 - maximum: 100 - payload: - type: object - properties: - sentAt: - $ref: "#/components/schemas/sentAt" + description: an id object + x-origin: ./schemas.yaml#/schemas/idSchema + x-origin: ./schemas.yaml#/schemas/commentLikedSchema + x-origin: ./messages.yaml#/messages/commentLikedMessage + x-origin: ./channels.yaml#/channels/commentLikedChannel` -components: - messages: - #libarary should be able to find and delete this message, because it is not used anywhere. - unusedMessage: - name: unusedMessage - title: This message is not used in any channel. - - schemas: - #this schema is ref-ed in one channel and used full form in another. library should be able to identify and ref the second channel as well. - sentAt: - type: string - format: date-time`; - -const optimizer = new Optimizer(yaml); +const optimizer = new Optimizer(yaml) ``` + ### Generating report + ```typescript -const report: Report = await optimizer.getReport(); +const report: Report = await optimizer.getReport() /* the report value will be: { - reuseComponents: [ + removeComponents: [], + reuseComponents: [], + moveAllToComponents: [ { - path: 'channels.smartylighting/event/{streetlightId}/lighting/measured.message.payload.properties.sentAt', - action: 'reuse', - target: 'components.schemas.sentAt' - } - ], - removeComponents: [ + path: 'channels.commentLikedChannel.messages.commentLikedMessage.payload.properties.commentId', + action: 'move', + target: 'components.schemas.idSchema' + }, { - path: 'components.messages.unusedMessage', - action: 'remove', - } - ], - moveDuplicatesToComponents: [ + path: 'channels.commentLikedChannel.messages.commentLikedMessage.payload', + action: 'move', + target: 'components.schemas.commentLikedSchema' + }, + { + path: 'channels.commentLikedChannel.messages.commentLikedMessage', + action: 'move', + target: 'components.messages.commentLikedMessage' + }, { - //move will ref the current path to the moved component as well. - path: 'channels.smartylighting/event/{streetlightId}/lighting/measured.parameters.streetlightId', + path: 'operations.user/deleteAccount.subscribe', action: 'move', - target: 'components.parameters.streetlightId' + target: 'components.operations.subscribe' }, { - path: 'channels.smartylighting/action/{streetlightId}/turn/on.parameters.streetlightId', - action: 'reuse', - target: 'components.parameters.streetlightId' + path: 'channels.commentLikedChannel', + action: 'move', + target: 'components.channels.commentLikedChannel' + }, + { + path: 'servers.production', + action: 'move', + target: 'components.servers.production' } - ] + ], + moveDuplicatesToComponents: [] } */ ``` + ### Applying the suggested changes + ```typescript const optimizedDocument = optimizer.getOptimizedDocument({ + output: 'YAML', rules: { reuseComponents: true, removeComponents: true, - moveDuplicatesToComponents: true - } -}); + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: false, + }, +}) /* the optimizedDocument value will be: -asyncapi: 2.0.0 +asyncapi: 3.0.0 info: - title: Streetlights API + title: Example Service version: 1.0.0 -channels: - "smartylighting/event/{streetlightId}/lighting/measured": - parameters: - streetlightId: - $ref: "#/components/parameters/parameter-1" + description: Example Service. +servers: + production: + $ref: '#/components/servers/production' +operations: + user/deleteAccount.subscribe: + action: send + channel: + $ref: '#/channels/commentLikedChannel' + user/deleteAccount: subscribe: - operationId: receiveLightMeasurement - traits: - - bindings: - kafka: - clientId: my-app-id - message: - name: lightMeasured - title: Light measured - contentType: application/json - traits: - - headers: - $ref: "#/components/schemas/schema-1" - payload: - type: object - properties: - lumens: - type: integer - minimum: 0 - sentAt: - $ref: "#/components/schemas/sentAt" - "smartylighting/action/{streetlightId}/turn/on": - parameters: - streetlightId: - $ref: "#/components/parameters/parameter-1" - publish: - operationId: turnOn - traits: - - bindings: - kafka: - clientId: my-app-id - message: - name: turnOnOff - title: Turn on/off - traits: - - headers: - $ref: "#/components/schemas/schema-1" - payload: - type: object - properties: - sentAt: - $ref: "#/components/schemas/sentAt" + $ref: '#/components/operations/subscribe' +channels: + commentLikedChannel: + $ref: '#/components/channels/commentLikedChannel' components: schemas: - sentAt: + idSchema: type: string - format: date-time - schema-1: + description: an id object + x-origin: ./schemas.yaml#/schemas/idSchema + commentLikedSchema: type: object + title: commentLikedPayload properties: - my-app-header: - type: integer - minimum: 0 - maximum: 100 - parameters: - parameter-1: - schema: - type: string` + commentId: + $ref: '#/components/schemas/idSchema' + x-origin: ./schemas.yaml#/schemas/commentLikedSchema + messages: + commentLikedMessage: + description: Message that is being sent when a comment has been liked by someone. + payload: + $ref: '#/components/schemas/commentLikedSchema' + x-origin: ./messages.yaml#/messages/commentLikedMessage + operations: {} + channels: + commentLikedChannel: + address: comment/liked + messages: + commentLikedMessage: + $ref: '#/components/messages/commentLikedMessage' + x-origin: ./channels.yaml#/channels/commentLikedChannel + servers: + production: + host: test.mosquitto.org:{port} + protocol: mqtt + description: Test broker + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' */ ``` diff --git a/examples/index.js b/examples/index.js index 0a2197d2..507639db 100644 --- a/examples/index.js +++ b/examples/index.js @@ -11,7 +11,11 @@ optimizer.getReport().then((report) => { rules: { reuseComponents: true, removeComponents: true, - moveDuplicatesToComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: false, }, }) //store optimizedDocument as to output.yaml diff --git a/src/ComponentProvider.ts b/src/ComponentProvider.ts index 96aa33d7..7131d45c 100644 --- a/src/ComponentProvider.ts +++ b/src/ComponentProvider.ts @@ -53,16 +53,15 @@ export const parseComponentsFromPath = ( } export const getOptimizableComponents = ( - asyncAPIDocument: AsyncAPIDocumentInterface + asyncAPIDocument: AsyncAPIDocumentInterface, ): OptimizableComponentGroup[] => { const optimizeableComponents: OptimizableComponentGroup[] = [] - const getAllComponents = (type: string) => { // @ts-ignore if (typeof asyncAPIDocument[type] !== 'function') return [] // @ts-ignore - return asyncAPIDocument[type]().all().concat(asyncAPIDocument.components()[type]().all()); - }; + return asyncAPIDocument[type]().all().concat(asyncAPIDocument.components()[type]().all()) + } const optimizableComponents = { servers: getAllComponents('servers'), messages: getAllComponents('messages'), diff --git a/src/Optimizer.ts b/src/Optimizer.ts index d1f83568..691ddc20 100644 --- a/src/Optimizer.ts +++ b/src/Optimizer.ts @@ -7,7 +7,12 @@ import { Reporter, } from './index.d' import { Parser } from '@asyncapi/parser' -import { removeComponents, reuseComponents, moveDuplicatesToComponents } from './Reporters' +import { + removeComponents, + reuseComponents, + moveAllToComponents, + moveDuplicatesToComponents, +} from './Reporters' import YAML from 'js-yaml' import merge from 'merge-deep' import * as _ from 'lodash' @@ -42,7 +47,12 @@ export class Optimizer { */ constructor(private YAMLorJSON: any) { this.outputObject = toJS(this.YAMLorJSON) - this.reporters = [removeComponents, reuseComponents, moveDuplicatesToComponents] + this.reporters = [ + removeComponents, + reuseComponents, + moveAllToComponents, + moveDuplicatesToComponents, + ] } /** @@ -78,13 +88,18 @@ export class Optimizer { * @typedef {Object} Rules * @property {Boolean=} reuseComponents - whether to reuse components from `components` section or not. Defaults to `true`. * @property {Boolean=} removeComponents - whether to remove un-used components from `components` section or not. Defaults to `true`. - * @property {Boolean=} moveDuplicatesToComponents - whether to move duplicated components to the `components` section or not. Defaults to `true`. + * @property {Boolean=} moveAllToComponents - whether to move all AsyncAPI Specification-valid components to the `components` section or not. Defaults to `true`. + * @property {Boolean=} moveDuplicatesToComponents - whether to move duplicated components to the `components` section or not. Defaults to `false`. + */ + /** + * @typedef {Object} DisableOptimizationFor + * @property {Boolean=} schema - whether object `schema` should be excluded from the process of optimization (`true` instructs **not** to add calculated `schemas` to the optimized AsyncAPI Document.) */ - /** * @typedef {Object} Options * @property {Rules=} rules - the list of rules that specifies which type of optimizations should be applied. * @property {String=} output - specifies which type of output user wants, `'JSON'` or `'YAML'`. Defaults to `'YAML'`; + * @property {DisableOptimizationFor=} disableOptimizationFor - the list of objects that should be excluded from the process of optimization. */ /** * This function is used to get the optimized document after seeing the report. @@ -98,9 +113,13 @@ export class Optimizer { rules: { reuseComponents: true, removeComponents: true, - moveDuplicatesToComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, // there is no need to move duplicates if `moveAllToComponents` is `true` }, output: Output.YAML, + disableOptimizationFor: { + schema: false, + }, } options = merge(defaultOptions, options) if (!this.reports) { @@ -109,6 +128,11 @@ export class Optimizer { ) } for (const report of this.reports) { + if (options.disableOptimizationFor?.schema === true) { + report.elements = report.elements.filter( + (element) => !element.target?.includes('.schemas.') + ) + } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore if (options.rules[report.type] === true) { diff --git a/src/Reporters/index.ts b/src/Reporters/index.ts index 82bcd854..51fe958d 100644 --- a/src/Reporters/index.ts +++ b/src/Reporters/index.ts @@ -1,3 +1,4 @@ +export * from './moveAllToComponents' export * from './moveDuplicatesToComponents' export * from './RemoveComponents' export * from './ReuseComponents' diff --git a/src/Reporters/moveAllToComponents.ts b/src/Reporters/moveAllToComponents.ts new file mode 100644 index 00000000..b225ab52 --- /dev/null +++ b/src/Reporters/moveAllToComponents.ts @@ -0,0 +1,56 @@ +import { Action } from '../Optimizer' +import { createReport, isEqual, isInComponents, getComponentName } from '../Utils' +import { OptimizableComponent, OptimizableComponentGroup, ReportElement, Reporter } from 'index.d' +import Debug from 'debug' +const debug = Debug('reporter:moveAllToComponents') +/** + * + * @param optimizableComponentGroup all AsyncAPI Specification-valid components. + * @returns A list of optimization report elements. + */ +const findAllComponents = ( + optimizableComponentGroup: OptimizableComponentGroup +): ReportElement[] => { + const allComponents = optimizableComponentGroup.components + const insideComponentsSection = allComponents.filter(isInComponents) + const outsideComponentsSection = getOutsideComponents(allComponents, insideComponentsSection) + + const resultElements: ReportElement[] = [] + + for (const component of outsideComponentsSection.values()) { + const existingResult = resultElements.filter( + (reportElement) => component.path === reportElement.path + )[0] + if (!existingResult) { + const componentName = getComponentName(component) + const target = `components.${optimizableComponentGroup.type}.${componentName}` + resultElements.push({ + path: component.path, + action: Action.Move, + target, + }) + } + } + debug( + 'all %s: %O', + optimizableComponentGroup.type, + resultElements.map((element) => element.path) + ) + return resultElements +} + +export const moveAllToComponents: Reporter = (optimizableComponentsGroup) => { + return createReport(findAllComponents, optimizableComponentsGroup, 'moveAllToComponents') +} + +function getOutsideComponents( + allComponents: OptimizableComponent[], + insideComponentsSection: OptimizableComponent[] +) { + return allComponents.filter( + (component) => + !isInComponents(component) && + insideComponentsSection.filter((inCSC) => isEqual(component.component, inCSC.component, true)) + .length === 0 + ) +} diff --git a/src/Reporters/moveDuplicatesToComponents.ts b/src/Reporters/moveDuplicatesToComponents.ts index 0ebfaf1f..e2d2f1b0 100644 --- a/src/Reporters/moveDuplicatesToComponents.ts +++ b/src/Reporters/moveDuplicatesToComponents.ts @@ -1,11 +1,11 @@ import { Action } from '../Optimizer' -import { createReport, isEqual, isInComponents } from '../Utils' +import { createReport, isEqual, isInComponents, getComponentName } from '../Utils' import { OptimizableComponent, OptimizableComponentGroup, ReportElement, Reporter } from 'index.d' import Debug from 'debug' const debug = Debug('reporter:moveDuplicatesToComponents') /** * - * @param optimizableComponentGroup components that you want to analyze for duplicates. + * @param optimizableComponentGroup all AsyncAPI Specification-valid components that you want to analyze for duplicates. * @returns A list of optimization report elements. */ const findDuplicateComponents = ( @@ -17,8 +17,6 @@ const findDuplicateComponents = ( const resultElements: ReportElement[] = [] - let counter = 1 - for (const [index, component] of outsideComponentsSection.entries()) { for (const compareComponent of outsideComponentsSection.slice(index + 1)) { if (isEqual(component.component, compareComponent.component, false)) { @@ -26,9 +24,7 @@ const findDuplicateComponents = ( (reportElement) => component.path === reportElement.path )[0] if (!existingResult) { - const componentName = - component.component.name || - `${optimizableComponentGroup.type.slice(0, -1)}-${counter++}` + const componentName = getComponentName(component) const target = `components.${optimizableComponentGroup.type}.${componentName}` resultElements.push({ path: component.path, @@ -59,7 +55,11 @@ const findDuplicateComponents = ( } export const moveDuplicatesToComponents: Reporter = (optimizableComponentsGroup) => { - return createReport(findDuplicateComponents, optimizableComponentsGroup, 'moveDuplicatesToComponents') + return createReport( + findDuplicateComponents, + optimizableComponentsGroup, + 'moveDuplicatesToComponents' + ) } function getOutsideComponents( diff --git a/src/Utils/Helpers.ts b/src/Utils/Helpers.ts index 2bed0314..b17eeb8a 100644 --- a/src/Utils/Helpers.ts +++ b/src/Utils/Helpers.ts @@ -158,4 +158,15 @@ const toJS = (asyncapiYAMLorJSON: any): any => { 'Unknown input: Please make sure that your input is an Object/String of a valid AsyncAPI specification document.' ) } -export { compareComponents, isEqual, isInComponents, isInChannels, toJS } + +const getComponentName = (component: OptimizableComponent): string => { + let componentName + if (component.component['x-origin']) { + componentName = String(component.component['x-origin']).split('/').reverse()[0] + } else { + componentName = String(component.path).split('.').reverse()[0] + } + return componentName +} + +export { compareComponents, isEqual, isInComponents, isInChannels, toJS, getComponentName } diff --git a/src/index.d.ts b/src/index.d.ts index eb340d87..28ddcaff 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -18,6 +18,7 @@ export type OptimizableComponentGroup = { export interface Report { reuseComponents?: ReportElement[] removeComponents?: ReportElement[] + moveAllToComponents?: ReportElement[] moveDuplicatesToComponents?: ReportElement[] } @@ -32,11 +33,17 @@ export type Reporter = (optimizeableComponents: OptimizableComponentGroup[]) => interface Rules { reuseComponents?: boolean removeComponents?: boolean + moveAllToComponents?: boolean moveDuplicatesToComponents?: boolean } + +export interface DisableOptimizationFor { + schema?: boolean +} export interface Options { rules?: Rules output?: Output + disableOptimizationFor?: DisableOptimizationFor // non-approved type } export interface IOptimizer { diff --git a/test/Optimizer.spec.ts b/test/Optimizer.spec.ts index b5b9c867..f9b54bbf 100644 --- a/test/Optimizer.spec.ts +++ b/test/Optimizer.spec.ts @@ -1,25 +1,268 @@ -import { inputJSON, inputYAML, outputJSON, outputYAML } from './fixtures' +import { + inputJSON, + inputYAML, + outputJSON_mATCFalse_mDTCTrue_schemaFalse, + outputYAML_mATCFalse_mDTCTrue_schemaFalse, + outputYAML_mATCTrue_mDTCFalse_schemaFalse, + outputJSON_mATCTrue_mDTCFalse_schemaFalse, + outputYAML_mATCFalse_mDTCTrue_schemaTrue, + outputJSON_mATCFalse_mDTCTrue_schemaTrue, + outputYAML_mATCTrue_mDTCFalse_schemaTrue, + outputJSON_mATCTrue_mDTCFalse_schemaTrue, +} from './fixtures' import { Optimizer } from '../src' import { Output } from '../src/Optimizer' describe('Optimizer', () => { - it('should produce the correct optimized file with YAML input.', async () => { + it('should produce the correct optimized file with YAML input and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: false } }`.', async () => { const optimizer = new Optimizer(inputYAML) await optimizer.getReport() - expect(optimizer.getOptimizedDocument().trim()).toEqual(outputYAML.trim()) + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaFalse.trim()) }) - it('should produce the correct optimized file with JSON input.', async () => { + it('should produce the correct optimized file with JSON input and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: false } }`.', async () => { const optimizer = new Optimizer(inputJSON) await optimizer.getReport() - expect(optimizer.getOptimizedDocument().trim()).toEqual(outputYAML.trim()) + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaFalse.trim()) }) - it('should produce the correct JSON output.', async () => { + it('should produce the correct JSON output and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: false } }`.', async () => { const optimizer = new Optimizer(inputYAML) await optimizer.getReport() - expect(optimizer.getOptimizedDocument({ output: Output.JSON }).trim()).toEqual( - outputJSON.trim() - ) + expect( + optimizer + .getOptimizedDocument({ + output: Output.JSON, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputJSON_mATCFalse_mDTCTrue_schemaFalse.trim()) + }) + + it('should produce the correct optimized file with YAML input and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: false } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaFalse.trim()) + }) + + it('should produce the correct optimized file with JSON input and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: false } }`.', async () => { + const optimizer = new Optimizer(inputJSON) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaFalse.trim()) + }) + + it('should produce the correct JSON output and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: false } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.JSON, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: false, + }, + }) + .trim() + ).toEqual(outputJSON_mATCTrue_mDTCFalse_schemaFalse.trim()) + }) + + it('should produce the correct optimized file with YAML input and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaTrue.trim()) + }) + + it('should produce the correct optimized file with JSON input and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputJSON) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaTrue.trim()) + }) + + it('should produce the correct JSON output and `{ moveAllToComponents: false, moveDuplicatesToComponents: true }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.JSON, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: false, + moveDuplicatesToComponents: true, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputJSON_mATCFalse_mDTCTrue_schemaTrue.trim()) + }) + + it('should produce the correct optimized file with YAML input and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaTrue.trim()) + }) + + it('should produce the correct optimized file with JSON input and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputJSON) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.YAML, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaTrue.trim()) + }) + + it('should produce the correct JSON output and `{ moveAllToComponents: true, moveDuplicatesToComponents: false }, disableOptimizationFor: { schema: true } }`.', async () => { + const optimizer = new Optimizer(inputYAML) + await optimizer.getReport() + expect( + optimizer + .getOptimizedDocument({ + output: Output.JSON, + rules: { + reuseComponents: true, + removeComponents: true, + moveAllToComponents: true, + moveDuplicatesToComponents: false, + }, + disableOptimizationFor: { + schema: true, + }, + }) + .trim() + ).toEqual(outputJSON_mATCTrue_mDTCFalse_schemaTrue.trim()) }) }) diff --git a/test/Reporters/Reporters.spec.ts b/test/Reporters/Reporters.spec.ts index 899c6409..f66eeecb 100644 --- a/test/Reporters/Reporters.spec.ts +++ b/test/Reporters/Reporters.spec.ts @@ -1,39 +1,126 @@ -import { moveDuplicatesToComponents, reuseComponents, removeComponents } from '../../src/Reporters' +import { + moveAllToComponents, + moveDuplicatesToComponents, + reuseComponents, + removeComponents, +} from '../../src/Reporters' import { inputYAML } from '../fixtures' import { Parser } from '@asyncapi/parser' import { getOptimizableComponents } from '../../src/ComponentProvider' import { OptimizableComponentGroup } from '../../src/index.d' +const moveAllToComponentsExpectedResult: any[] = [ + { + path: 'channels.withDuplicatedMessage1.messages.duped1', + action: 'move', + target: 'components.messages.duped1', + }, + { + path: 'channels.withDuplicatedMessage2.messages.duped2', + action: 'move', + target: 'components.messages.duped2', + }, + { + path: 'channels.withFullFormMessage.messages.canBeReused', + action: 'move', + target: 'components.messages.canBeReused', + }, + { + path: 'channels.withDuplicatedMessage1', + action: 'move', + target: 'components.channels.withDuplicatedMessage1FromXOrigin', + }, + { + path: 'channels.withDuplicatedMessage2', + action: 'move', + target: 'components.channels.withDuplicatedMessage2', + }, + { + path: 'channels.withFullFormMessage', + action: 'move', + target: 'components.channels.withFullFormMessage', + }, + { + path: 'channels.UserSignedUp1', + action: 'move', + target: 'components.channels.UserSignedUp1', + }, + { + path: 'channels.UserSignedUp2', + action: 'move', + target: 'components.channels.UserSignedUp2', + }, + { + path: 'channels.deleteAccount', + action: 'move', + target: 'components.channels.deleteAccount', + }, + { + path: 'channels.withDuplicatedMessage1.messages.duped1.payload', + action: 'move', + target: 'components.schemas.payload', + }, + { + path: 'channels.withDuplicatedMessage2.messages.duped2.payload', + action: 'move', + target: 'components.schemas.payload', + }, + { + path: 'channels.UserSignedUp1.messages.myMessage.payload', + action: 'move', + target: 'components.schemas.payload', + }, + { + path: 'channels.UserSignedUp1.messages.myMessage.payload.properties.displayName', + action: 'move', + target: 'components.schemas.displayName', + }, + { + path: 'channels.UserSignedUp1.messages.myMessage.payload.properties.email', + action: 'move', + target: 'components.schemas.email', + }, + { + path: 'channels.deleteAccount.messages.deleteUser.payload', + action: 'move', + target: 'components.schemas.payload', + }, + { + path: 'operations.user/deleteAccount.subscribe', + action: 'move', + target: 'components.operations.subscribe', + }, +] const moveDuplicatesToComponentsExpectedResult: any[] = [ { path: 'channels.withDuplicatedMessage1.messages.duped1', action: 'move', - target: 'components.messages.message-1', + target: 'components.messages.duped1', }, { path: 'channels.withDuplicatedMessage2.messages.duped2', action: 'reuse', - target: 'components.messages.message-1', + target: 'components.messages.duped1', }, { path: 'channels.UserSignedUp1', action: 'move', - target: 'components.channels.channel-1', + target: 'components.channels.UserSignedUp1', }, { path: 'channels.UserSignedUp2', action: 'reuse', - target: 'components.channels.channel-1', + target: 'components.channels.UserSignedUp1', }, { path: 'channels.withDuplicatedMessage1.messages.duped1.payload', action: 'move', - target: 'components.schemas.schema-1', + target: 'components.schemas.payload', }, { path: 'channels.withDuplicatedMessage2.messages.duped2.payload', action: 'reuse', - target: 'components.schemas.schema-1', + target: 'components.schemas.payload', }, ] const RemoveComponentsExpectedResult = [ @@ -55,6 +142,14 @@ describe('Optimizers', () => { const asyncapiDocument = await new Parser().parse(inputYAML, { applyTraits: false }) optimizableComponents = getOptimizableComponents(asyncapiDocument.document!) }) + describe('moveAllToComponents', () => { + test('should contain the correct optimizations.', () => { + const report = moveAllToComponents(optimizableComponents) + expect(report.elements).toEqual(moveAllToComponentsExpectedResult) + expect(report.type).toEqual('moveAllToComponents') + }) + }) + describe('moveDuplicatesToComponents', () => { test('should contain the correct optimizations.', () => { const report = moveDuplicatesToComponents(optimizableComponents) diff --git a/test/fixtures.ts b/test/fixtures.ts index 1a112d4c..71387d6c 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -90,6 +90,7 @@ info: This file contains duplicate and unused messages across the file and is used to test the optimizer. channels: withDuplicatedMessage1: + x-origin: ./messages.yaml#/withDuplicatedMessage1FromXOrigin address: user/signedup messages: duped1: @@ -161,9 +162,9 @@ components: email: type: string format: email - description: Email of the user -` -export const outputYAML = `asyncapi: 3.0.0 + description: Email of the user` + +export const outputYAML_mATCFalse_mDTCTrue_schemaFalse = `asyncapi: 3.0.0 info: title: Untidy AsyncAPI file version: 1.0.0 @@ -172,15 +173,16 @@ info: to test the optimizer. channels: withDuplicatedMessage1: + x-origin: ./messages.yaml#/withDuplicatedMessage1FromXOrigin address: user/signedup messages: duped1: - $ref: '#/components/messages/message-1' + $ref: '#/components/messages/duped1' withDuplicatedMessage2: address: user/signedup messages: duped2: - $ref: '#/components/messages/message-1' + $ref: '#/components/messages/duped1' withFullFormMessage: address: user/signedup messages: @@ -188,9 +190,9 @@ channels: payload: $ref: '#/components/schemas/canBeReused' UserSignedUp1: - $ref: '#/components/channels/channel-1' + $ref: '#/components/channels/UserSignedUp1' UserSignedUp2: - $ref: '#/components/channels/channel-1' + $ref: '#/components/channels/UserSignedUp1' deleteAccount: address: user/deleteAccount messages: @@ -208,7 +210,7 @@ components: canBeReused: type: object description: I can be reused. - schema-1: + payload: type: object description: I am duplicated messages: @@ -227,111 +229,427 @@ components: type: string format: email description: Email of the user - message-1: + duped1: payload: - $ref: '#/components/schemas/schema-1' + $ref: '#/components/schemas/payload' channels: - channel-1: + UserSignedUp1: address: user/signedup messages: myMessage: - $ref: '#/components/messages/UserSignedUp' -` + $ref: '#/components/messages/UserSignedUp'` export const inputJSON = `{ - 'asyncapi': '3.0.0', - 'info': - { - 'title': 'Untidy AsyncAPI file', - 'version': '1.0.0', - 'description': 'This file contains duplicate and unused messages across the file and is used to test the optimizer.', + "asyncapi": "3.0.0", + "info": { + "title": "Untidy AsyncAPI file", + "version": "1.0.0", + "description": "This file contains duplicate and unused messages across the file and is used to test the optimizer." + }, + "channels": { + "withDuplicatedMessage1": { + "x-origin": "./messages.yaml#/withDuplicatedMessage1FromXOrigin", + "address": "user/signedup", + "messages": { + "duped1": { + "payload": { + "type": "object", + "description": "I am duplicated" + } + } + } }, - 'channels': - { - 'withDuplicatedMessage1': - { - 'address': 'user/signedup', - 'messages': - { 'duped1': { 'payload': { 'type': 'object', 'description': 'I am duplicated' } } }, - }, - 'withDuplicatedMessage2': - { - 'address': 'user/signedup', - 'messages': - { 'duped2': { 'payload': { 'type': 'object', 'description': 'I am duplicated' } } }, - }, - 'withFullFormMessage': - { - 'address': 'user/signedup', - 'messages': - { - 'canBeReused': { 'payload': { 'type': 'object', 'description': 'I can be reused.' } }, - }, - }, - 'UserSignedUp1': - { - 'address': 'user/signedup', - 'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } }, - }, - 'UserSignedUp2': - { - 'address': 'user/signedup', - 'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } }, - }, - 'deleteAccount': - { - 'address': 'user/deleteAccount', - 'messages': { 'deleteUser': { '$ref': '#/components/messages/DeleteUser' } }, - }, + "withDuplicatedMessage2": { + "address": "user/signedup", + "messages": { + "duped2": { + "payload": { + "type": "object", + "description": "I am duplicated" + } + } + } }, - 'operations': - { - 'user/deleteAccount.subscribe': - { - 'action': 'send', - 'channel': { '$ref': '#/channels/deleteAccount' }, - 'messages': [{ '$ref': '#/channels/deleteAccount/messages/deleteUser' }], - }, + "withFullFormMessage": { + "address": "user/signedup", + "messages": { + "canBeReused": { + "payload": { + "type": "object", + "description": "I can be reused." + } + } + } }, - 'components': - { - 'channels': - { - 'unUsedChannel': - { - 'address': 'user/unused', - 'messages': { 'myMessage': { '$ref': '#/components/messages/UserSignedUp' } }, - }, - }, - 'schemas': { 'canBeReused': { 'type': 'object', 'description': 'I can be reused.' } }, - 'messages': + "UserSignedUp1": { + "address": "user/signedup", + "messages": { + "myMessage": { + "$ref": "#/components/messages/UserSignedUp" + } + } + }, + "UserSignedUp2": { + "address": "user/signedup", + "messages": { + "myMessage": { + "$ref": "#/components/messages/UserSignedUp" + } + } + }, + "deleteAccount": { + "address": "user/deleteAccount", + "messages": { + "deleteUser": { + "$ref": "#/components/messages/DeleteUser" + } + } + } + }, + "operations": { + "user/deleteAccount.subscribe": { + "action": "send", + "channel": { + "$ref": "#/channels/deleteAccount" + }, + "messages": [ { - 'unUsedMessage': { 'payload': { 'type': 'boolean' } }, - 'DeleteUser': - { - 'payload': - { - 'type': 'string', - 'description': 'userId of the user that is going to be deleted', - }, - }, - 'UserSignedUp': - { - 'payload': - { - 'type': 'object', - 'properties': - { - 'displayName': { 'type': 'string', 'description': 'Name of the user' }, - 'email': - { 'type': 'string', 'format': 'email', 'description': 'Email of the user' }, - }, - }, - }, - }, + "$ref": "#/channels/deleteAccount/messages/deleteUser" + } + ] + } + }, + "components": { + "channels": { + "unUsedChannel": { + "address": "user/unused", + "messages": { + "myMessage": { + "$ref": "#/components/messages/UserSignedUp" + } + } + } }, -} -` + "schemas": { + "canBeReused": { + "type": "object", + "description": "I can be reused." + } + }, + "messages": { + "unUsedMessage": { + "payload": { + "type": "boolean" + } + }, + "DeleteUser": { + "payload": { + "type": "string", + "description": "userId of the user that is going to be deleted" + } + }, + "UserSignedUp": { + "payload": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Name of the user" + }, + "email": { + "type": "string", + "format": "email", + "description": "Email of the user" + } + } + } + } + } + } +}` + +// eslint-disable-next-line quotes +export const outputJSON_mATCFalse_mDTCTrue_schemaFalse = `{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"x-origin":"./messages.yaml#/withDuplicatedMessage1FromXOrigin","address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/duped1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/duped1"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"payload":{"$ref":"#/components/schemas/canBeReused"}}}},"UserSignedUp1":{"$ref":"#/components/channels/UserSignedUp1"},"UserSignedUp2":{"$ref":"#/components/channels/UserSignedUp1"},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/channels/deleteAccount/messages/deleteUser"}]}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."},"payload":{"type":"object","description":"I am duplicated"}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"duped1":{"payload":{"$ref":"#/components/schemas/payload"}}},"channels":{"UserSignedUp1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}}}}}` + +export const outputYAML_mATCTrue_mDTCFalse_schemaFalse = `asyncapi: 3.0.0 +info: + title: Untidy AsyncAPI file + version: 1.0.0 + description: >- + This file contains duplicate and unused messages across the file and is used + to test the optimizer. +channels: + withDuplicatedMessage1: + $ref: '#/components/channels/withDuplicatedMessage1FromXOrigin' + withDuplicatedMessage2: + $ref: '#/components/channels/withDuplicatedMessage2' + withFullFormMessage: + $ref: '#/components/channels/withFullFormMessage' + UserSignedUp1: + $ref: '#/components/channels/UserSignedUp1' + UserSignedUp2: + $ref: '#/components/channels/UserSignedUp2' + deleteAccount: + $ref: '#/components/channels/deleteAccount' +operations: + user/deleteAccount.subscribe: + action: send + channel: + $ref: '#/channels/deleteAccount' + messages: + - $ref: '#/channels/deleteAccount/messages/deleteUser' + user/deleteAccount: + subscribe: + $ref: '#/components/operations/subscribe' +components: + schemas: + canBeReused: + type: object + description: I can be reused. + payload: + type: object + description: I am duplicated + messages: + DeleteUser: + payload: + type: string + description: userId of the user that is going to be deleted + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user + canBeReused: + payload: + $ref: '#/components/schemas/canBeReused' + duped1: + payload: + $ref: '#/components/schemas/payload' + duped2: + payload: + $ref: '#/components/schemas/payload' + operations: {} + channels: + withDuplicatedMessage1FromXOrigin: + x-origin: ./messages.yaml#/withDuplicatedMessage1FromXOrigin + address: user/signedup + messages: + duped1: + $ref: '#/components/messages/duped1' + withDuplicatedMessage2: + address: user/signedup + messages: + duped2: + $ref: '#/components/messages/duped2' + withFullFormMessage: + address: user/signedup + messages: + canBeReused: + $ref: '#/components/messages/canBeReused' + UserSignedUp1: + address: user/signedup + messages: + myMessage: + $ref: '#/components/messages/UserSignedUp' + payload: + properties: + displayName: + $ref: '#/components/schemas/displayName' + email: + $ref: '#/components/schemas/email' + UserSignedUp2: + address: user/signedup + messages: + myMessage: + $ref: '#/components/messages/UserSignedUp' + deleteAccount: + address: user/deleteAccount + messages: + deleteUser: + $ref: '#/components/messages/DeleteUser'` + +// eslint-disable-next-line quotes +export const outputJSON_mATCTrue_mDTCFalse_schemaFalse = `{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"$ref":"#/components/channels/withDuplicatedMessage1FromXOrigin"},"withDuplicatedMessage2":{"$ref":"#/components/channels/withDuplicatedMessage2"},"withFullFormMessage":{"$ref":"#/components/channels/withFullFormMessage"},"UserSignedUp1":{"$ref":"#/components/channels/UserSignedUp1"},"UserSignedUp2":{"$ref":"#/components/channels/UserSignedUp2"},"deleteAccount":{"$ref":"#/components/channels/deleteAccount"}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/channels/deleteAccount/messages/deleteUser"}]},"user/deleteAccount":{"subscribe":{"$ref":"#/components/operations/subscribe"}}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."},"payload":{"type":"object","description":"I am duplicated"}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"canBeReused":{"payload":{"$ref":"#/components/schemas/canBeReused"}},"duped1":{"payload":{"$ref":"#/components/schemas/payload"}},"duped2":{"payload":{"$ref":"#/components/schemas/payload"}}},"operations":{},"channels":{"withDuplicatedMessage1FromXOrigin":{"x-origin":"./messages.yaml#/withDuplicatedMessage1FromXOrigin","address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/duped1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/duped2"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"$ref":"#/components/messages/canBeReused"}}},"UserSignedUp1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp","payload":{"properties":{"displayName":{"$ref":"#/components/schemas/displayName"},"email":{"$ref":"#/components/schemas/email"}}}}}},"UserSignedUp2":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}}}}` + +export const outputYAML_mATCFalse_mDTCTrue_schemaTrue = `asyncapi: 3.0.0 +info: + title: Untidy AsyncAPI file + version: 1.0.0 + description: >- + This file contains duplicate and unused messages across the file and is used + to test the optimizer. +channels: + withDuplicatedMessage1: + x-origin: ./messages.yaml#/withDuplicatedMessage1FromXOrigin + address: user/signedup + messages: + duped1: + $ref: '#/components/messages/duped1' + withDuplicatedMessage2: + address: user/signedup + messages: + duped2: + $ref: '#/components/messages/duped1' + withFullFormMessage: + address: user/signedup + messages: + canBeReused: + payload: + type: object + description: I can be reused. + UserSignedUp1: + $ref: '#/components/channels/UserSignedUp1' + UserSignedUp2: + $ref: '#/components/channels/UserSignedUp1' + deleteAccount: + address: user/deleteAccount + messages: + deleteUser: + $ref: '#/components/messages/DeleteUser' +operations: + user/deleteAccount.subscribe: + action: send + channel: + $ref: '#/channels/deleteAccount' + messages: + - $ref: '#/channels/deleteAccount/messages/deleteUser' +components: + schemas: + canBeReused: + type: object + description: I can be reused. + messages: + DeleteUser: + payload: + type: string + description: userId of the user that is going to be deleted + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user + duped1: + payload: + type: object + description: I am duplicated + channels: + UserSignedUp1: + address: user/signedup + messages: + myMessage: + $ref: '#/components/messages/UserSignedUp'` + +// eslint-disable-next-line quotes +export const outputJSON_mATCFalse_mDTCTrue_schemaTrue = `{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"x-origin":"./messages.yaml#/withDuplicatedMessage1FromXOrigin","address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/duped1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/duped1"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"payload":{"type":"object","description":"I can be reused."}}}},"UserSignedUp1":{"$ref":"#/components/channels/UserSignedUp1"},"UserSignedUp2":{"$ref":"#/components/channels/UserSignedUp1"},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/channels/deleteAccount/messages/deleteUser"}]}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"duped1":{"payload":{"type":"object","description":"I am duplicated"}}},"channels":{"UserSignedUp1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}}}}}` +export const outputYAML_mATCTrue_mDTCFalse_schemaTrue = `asyncapi: 3.0.0 +info: + title: Untidy AsyncAPI file + version: 1.0.0 + description: >- + This file contains duplicate and unused messages across the file and is used + to test the optimizer. +channels: + withDuplicatedMessage1: + $ref: '#/components/channels/withDuplicatedMessage1FromXOrigin' + withDuplicatedMessage2: + $ref: '#/components/channels/withDuplicatedMessage2' + withFullFormMessage: + $ref: '#/components/channels/withFullFormMessage' + UserSignedUp1: + $ref: '#/components/channels/UserSignedUp1' + UserSignedUp2: + $ref: '#/components/channels/UserSignedUp2' + deleteAccount: + $ref: '#/components/channels/deleteAccount' +operations: + user/deleteAccount.subscribe: + action: send + channel: + $ref: '#/channels/deleteAccount' + messages: + - $ref: '#/channels/deleteAccount/messages/deleteUser' + user/deleteAccount: + subscribe: + $ref: '#/components/operations/subscribe' +components: + schemas: + canBeReused: + type: object + description: I can be reused. + messages: + DeleteUser: + payload: + type: string + description: userId of the user that is going to be deleted + UserSignedUp: + payload: + type: object + properties: + displayName: + type: string + description: Name of the user + email: + type: string + format: email + description: Email of the user + canBeReused: + payload: + type: object + description: I can be reused. + duped1: + payload: + type: object + description: I am duplicated + duped2: + payload: + type: object + description: I am duplicated + operations: {} + channels: + withDuplicatedMessage1FromXOrigin: + x-origin: ./messages.yaml#/withDuplicatedMessage1FromXOrigin + address: user/signedup + messages: + duped1: + $ref: '#/components/messages/duped1' + withDuplicatedMessage2: + address: user/signedup + messages: + duped2: + $ref: '#/components/messages/duped2' + withFullFormMessage: + address: user/signedup + messages: + canBeReused: + $ref: '#/components/messages/canBeReused' + UserSignedUp1: + address: user/signedup + messages: + myMessage: + $ref: '#/components/messages/UserSignedUp' + UserSignedUp2: + address: user/signedup + messages: + myMessage: + $ref: '#/components/messages/UserSignedUp' + deleteAccount: + address: user/deleteAccount + messages: + deleteUser: + $ref: '#/components/messages/DeleteUser'` + // eslint-disable-next-line quotes -export const outputJSON = `{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/message-1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/message-1"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"payload":{"$ref":"#/components/schemas/canBeReused"}}}},"UserSignedUp1":{"$ref":"#/components/channels/channel-1"},"UserSignedUp2":{"$ref":"#/components/channels/channel-1"},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/channels/deleteAccount/messages/deleteUser"}]}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."},"schema-1":{"type":"object","description":"I am duplicated"}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"message-1":{"payload":{"$ref":"#/components/schemas/schema-1"}}},"channels":{"channel-1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}}}}}` +export const outputJSON_mATCTrue_mDTCFalse_schemaTrue = `{"asyncapi":"3.0.0","info":{"title":"Untidy AsyncAPI file","version":"1.0.0","description":"This file contains duplicate and unused messages across the file and is used to test the optimizer."},"channels":{"withDuplicatedMessage1":{"$ref":"#/components/channels/withDuplicatedMessage1FromXOrigin"},"withDuplicatedMessage2":{"$ref":"#/components/channels/withDuplicatedMessage2"},"withFullFormMessage":{"$ref":"#/components/channels/withFullFormMessage"},"UserSignedUp1":{"$ref":"#/components/channels/UserSignedUp1"},"UserSignedUp2":{"$ref":"#/components/channels/UserSignedUp2"},"deleteAccount":{"$ref":"#/components/channels/deleteAccount"}},"operations":{"user/deleteAccount.subscribe":{"action":"send","channel":{"$ref":"#/channels/deleteAccount"},"messages":[{"$ref":"#/channels/deleteAccount/messages/deleteUser"}]},"user/deleteAccount":{"subscribe":{"$ref":"#/components/operations/subscribe"}}},"components":{"schemas":{"canBeReused":{"type":"object","description":"I can be reused."}},"messages":{"DeleteUser":{"payload":{"type":"string","description":"userId of the user that is going to be deleted"}},"UserSignedUp":{"payload":{"type":"object","properties":{"displayName":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}}}},"canBeReused":{"payload":{"type":"object","description":"I can be reused."}},"duped1":{"payload":{"type":"object","description":"I am duplicated"}},"duped2":{"payload":{"type":"object","description":"I am duplicated"}}},"operations":{},"channels":{"withDuplicatedMessage1FromXOrigin":{"x-origin":"./messages.yaml#/withDuplicatedMessage1FromXOrigin","address":"user/signedup","messages":{"duped1":{"$ref":"#/components/messages/duped1"}}},"withDuplicatedMessage2":{"address":"user/signedup","messages":{"duped2":{"$ref":"#/components/messages/duped2"}}},"withFullFormMessage":{"address":"user/signedup","messages":{"canBeReused":{"$ref":"#/components/messages/canBeReused"}}},"UserSignedUp1":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}},"UserSignedUp2":{"address":"user/signedup","messages":{"myMessage":{"$ref":"#/components/messages/UserSignedUp"}}},"deleteAccount":{"address":"user/deleteAccount","messages":{"deleteUser":{"$ref":"#/components/messages/DeleteUser"}}}}}}`