-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
parser.ts
105 lines (94 loc) · 3 KB
/
parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import $RefParser, {$Refs} from '@apidevtools/json-schema-ref-parser';
import { JSONPath } from 'jsonpath-plus';
import { merge } from 'lodash';
import { AsyncAPIObject } from 'spec-types';
class ExternalComponents {
ref;
resolvedJSON;
constructor(ref: string, resolvedJSON: string) {
this.ref = ref;
this.resolvedJSON = resolvedJSON;
}
getKey() {
const keys = this.ref.split('/');
return keys[keys.length - 1];
}
getValue() {
return this.resolvedJSON;
}
}
function crawlChannelPropertiesForRefs(JSONSchema: any) {
return JSONPath({
json: JSONSchema,
path: '$.channels.*.messages.*.[\'$ref\']',
});
}
export function isExternalReference(ref: string): boolean {
return typeof ref === 'string' && !ref.startsWith('#');
}
async function resolveExternalRefs(parsedJSON: any, $refs: $Refs) {
const componentObj: any = { messages: {} };
JSONPath({
json: parsedJSON,
resultType: 'all',
path: '$.channels.*.messages.*',
}).forEach(
({ parent, parentProperty }: { parent: any; parentProperty: string }) => {
const ref = parent[String(parentProperty)]['$ref'];
if (isExternalReference(ref)) {
const value: any = $refs.get(ref);
const component = new ExternalComponents(ref, value);
if (componentObj.messages) {
componentObj.messages[String(component.getKey())] =
component.getValue() as unknown;
}
parent[String(parentProperty)][
'$ref'
] = `#/components/messages/${component.getKey()}`;
}
}
);
return componentObj;
}
async function resolveExternalRefsForOperation(parsedJSON: any, $refs: $Refs) {
JSONPath({
json: parsedJSON,
resultType: 'all',
path: '$.operations.*.messages.*'
}).forEach(
({parent, parentProperty}: {parent: any, parentProperty: string}) => {
parent.forEach((reference: any) => {
const ref = reference['$ref'];
if (isExternalReference(ref)) {
const value: any = $refs.get(ref);
const component = new ExternalComponents(ref, value);
parent[String(parentProperty)]['$ref'] = `#/components/messages/${component.getKey()}`;
}
});
}
);
}
export async function parse(JSONSchema: any) {
const $ref: any = await $RefParser.resolve(JSONSchema);
const refs = crawlChannelPropertiesForRefs(JSONSchema);
for (const ref of refs) {
if (isExternalReference(ref)) {
const componentObj = await resolveExternalRefs(JSONSchema, $ref);
await resolveExternalRefsForOperation(JSONSchema, $ref);
if (JSONSchema.components) {
merge(JSONSchema.components, componentObj);
} else {
JSONSchema.components = componentObj;
}
}
}
}
export async function resolveV3Document(asyncapiDocuments: AsyncAPIObject[]) {
const docs = [];
for (const asyncapiDocument of asyncapiDocuments) {
await parse(asyncapiDocument);
//const bundledAsyncAPIDocument = await $RefParser.bundle(asyncapiDocument)
docs.push(asyncapiDocument);
}
return docs;
}