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

fix: update $refs after moving components to components #263

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const outputFilePath = path.join(__dirname, 'output.yaml')
const input = fs.readFileSync(inputFilePath, 'utf8')
const optimizer = new Optimizer(input)

optimizer.getReport().then((report) => {
optimizer.getReport().then(async (report) => {
console.log(report)
const optimizedDocument = optimizer.getOptimizedDocument({
const optimizedDocument = await optimizer.getOptimizedDocument({
output: 'YAML',
rules: {
reuseComponents: true,
Expand Down
35 changes: 32 additions & 3 deletions src/Optimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import YAML from 'js-yaml'
import merge from 'merge-deep'
import * as _ from 'lodash'
import { getOptimizableComponents } from './ComponentProvider'
import { filterReportElements, hasParent, sortReportElements, toJS } from './Utils'
import { filterReportElements, hasParent, sortReportElements, toJS, updateExistingRefs } from './Utils'
import Debug from 'debug'

export enum Action {
Expand All @@ -30,6 +30,11 @@ export enum Output {
JSON = 'JSON',
YAML = 'YAML',
}

const parser = new Parser()

let validationResult: any[] = [];

/**
* this class is the starting point of the library.
* user will only interact with this class. here we generate different kind of reports using optimizers, apply changes and return the results to the user.
Expand Down Expand Up @@ -60,7 +65,6 @@ export class Optimizer {
*
*/
async getReport(): Promise<Report> {
const parser = new Parser()
const parsedDocument = await parser.parse(this.YAMLorJSON, { applyTraits: false })
if (!parsedDocument.document) {
// eslint-disable-next-line no-undef, no-console
Expand Down Expand Up @@ -108,7 +112,7 @@ export class Optimizer {
* @returns {string } returns an stringified version of the YAML output.
*
*/
getOptimizedDocument(options?: Options): string {
async getOptimizedDocument(options?: Options): Promise<string> {
const defaultOptions = {
rules: {
reuseComponents: true,
Expand Down Expand Up @@ -140,6 +144,30 @@ export class Optimizer {
}
}

// 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(this.outputObject)))
}

// 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 exits without doing anything further.
if (
validationResult.length !== 0 &&
validationResult.map((element: any) => element.severity).includes(0)
) {
// eslint-disable-next-line no-undef, no-console
console.log(
'Validation of the optimized AsyncAPI Document failed.\nList of remarks:\n',
validationResult.filter((element: any) => element.severity === 0)
)
throw new Error('Validation of the optimized AsyncAPI Document failed.')
}

if (options.output === Output.JSON) {
return JSON.stringify(this.outputObject)
}
Expand All @@ -163,6 +191,7 @@ export class Optimizer {
_.set(this.outputObject, change.path, {
$ref: `#/${change.target?.replace(/\./g, '/')}`,
})
// updateExistingRefs(this.outputObject, change.path, change.target as string)
debug('moved %s to %s', change.path, change.target)
break

Expand Down
40 changes: 39 additions & 1 deletion src/Utils/Helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,42 @@ const getComponentName = (component: OptimizableComponent): string => {
return componentName
}

export { compareComponents, isEqual, isInComponents, isInChannels, toJS, getComponentName }
function updateExistingRefs(asyncapiComponent: any, changePath: string, changeTarget: string): any {
const changePathArray = changePath.split('.')
changePathArray.unshift('#')
changePath = changePathArray.join('/')

const changeTargetArray = changeTarget.split('.')
changeTargetArray.unshift('#')
changeTarget = changeTargetArray.join('/')

function iterateComponent(asyncapiComponent: any) {
// eslint-disable-next-line github/array-foreach
Object.values(asyncapiComponent).forEach((key: any) => {
if (key && typeof key === 'object' && key !== '$ref') {
if (Object.keys(key).indexOf('$ref') !== -1) {
const keyValue = key['$ref']
if (keyValue.startsWith(`${changePath}/`)) {
key['$ref'] = keyValue.replace(changePath, changeTarget)
}
} else {
iterateComponent(key)
}
}
})
}

iterateComponent(asyncapiComponent)

return asyncapiComponent
}

export {
compareComponents,
isEqual,
isInComponents,
isInChannels,
toJS,
getComponentName,
updateExistingRefs,
}
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface Options {
rules?: Rules
output?: Output
disableOptimizationFor?: DisableOptimizationFor // non-approved type
noValidation?: boolean
}

export interface IOptimizer {
Expand Down
14 changes: 1 addition & 13 deletions test/Optimizer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('Optimizer', () => {
const optimizer = new Optimizer(inputYAML)
await optimizer.getReport()
expect(
optimizer
await optimizer
.getOptimizedDocument({
output: Output.YAML,
rules: {
Expand All @@ -31,7 +31,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaFalse.trim())
})

Expand All @@ -52,7 +51,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaFalse.trim())
})

Expand All @@ -73,7 +71,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputJSON_mATCFalse_mDTCTrue_schemaFalse.trim())
})

Expand All @@ -94,7 +91,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaFalse.trim())
})

Expand All @@ -115,7 +111,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaFalse.trim())
})

Expand All @@ -136,7 +131,6 @@ describe('Optimizer', () => {
schema: false,
},
})
.trim()
).toEqual(outputJSON_mATCTrue_mDTCFalse_schemaFalse.trim())
})

Expand All @@ -157,7 +151,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaTrue.trim())
})

Expand All @@ -178,7 +171,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputYAML_mATCFalse_mDTCTrue_schemaTrue.trim())
})

Expand All @@ -199,7 +191,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputJSON_mATCFalse_mDTCTrue_schemaTrue.trim())
})

Expand All @@ -220,7 +211,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaTrue.trim())
})

Expand All @@ -241,7 +231,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputYAML_mATCTrue_mDTCFalse_schemaTrue.trim())
})

Expand All @@ -262,7 +251,6 @@ describe('Optimizer', () => {
schema: true,
},
})
.trim()
).toEqual(outputJSON_mATCTrue_mDTCFalse_schemaTrue.trim())
})
})
2 changes: 1 addition & 1 deletion test/Reporters/Reporters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { inputYAML } from '../fixtures'
import { Parser } from '@asyncapi/parser'
import { getOptimizableComponents } from '../../src/ComponentProvider'
import { OptimizableComponentGroup } from '../../src/index.d'
import { OptimizableComponentGroup } from '../../src/types'

const moveAllToComponentsExpectedResult: any[] = [
{
Expand Down
Loading