Skip to content

Commit 856dc5c

Browse files
authored
feat(reference): apply dereferencing architecture 2.0 to AsyncAPI 2.x (#3933)
Refs #3932
1 parent 63a41d4 commit 856dc5c

File tree

9 files changed

+489
-292
lines changed

9 files changed

+489
-292
lines changed

packages/apidom-reference/src/dereference/strategies/apidom/index.ts

+32-35
Original file line numberDiff line numberDiff line change
@@ -28,66 +28,63 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
2828
},
2929

3030
async dereference(file: IFile, options: IReferenceOptions): Promise<Element> {
31-
const refSet = options.dereference.refSet ?? ReferenceSet();
31+
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
32+
const mutableRefsSet = ReferenceSet();
33+
let refSet = immutableRefSet;
3234
let reference;
3335

3436
// determine the initial reference
35-
if (!refSet.has(file.uri)) {
37+
if (!immutableRefSet.has(file.uri)) {
3638
reference = Reference({ uri: file.uri, value: file.parseResult });
37-
refSet.add(reference);
39+
immutableRefSet.add(reference);
3840
} else {
3941
// pre-computed refSet was provided as configuration option
40-
reference = refSet.find((ref) => ref.uri === file.uri);
42+
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
4143
}
4244

4345
/**
4446
* Clone refSet due the dereferencing process being mutable.
4547
* We don't want to mutate the original refSet and the references.
4648
*/
4749
if (options.dereference.immutable) {
48-
const immutableRefs = refSet.refs.map((ref) =>
49-
Reference({
50-
...ref,
51-
uri: `immutable://${ref.uri}`,
52-
}),
53-
);
54-
const mutableRefs = refSet.refs.map((ref) =>
55-
Reference({
56-
...ref,
57-
value: cloneDeep(ref.value),
58-
}),
59-
);
60-
61-
refSet.clean();
62-
mutableRefs.forEach((ref) => refSet.add(ref));
63-
immutableRefs.forEach((ref) => refSet.add(ref));
64-
reference = refSet.find((ref) => ref.uri === file.uri);
50+
immutableRefSet.refs
51+
.map((ref) =>
52+
Reference({
53+
...ref,
54+
value: cloneDeep(ref.value),
55+
}),
56+
)
57+
.forEach((ref) => mutableRefsSet.add(ref));
58+
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
59+
refSet = mutableRefsSet;
6560
}
6661

6762
const visitor = ApiDOMDereferenceVisitor({ reference, options });
6863
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor);
6964

70-
if (options.dereference.refSet === null) {
71-
/**
72-
* Release all memory if this refSet was not provided as a configuration option.
73-
* If provided as configuration option, then provider is responsible for cleanup.
74-
*/
75-
refSet.clean();
76-
} else if (options.dereference.immutable) {
77-
/**
78-
* If immutable option is set, then we need to remove mutable refs from the refSet.
79-
*/
80-
const immutableRefs = refSet.refs
65+
/**
66+
* If immutable option is set, replay refs from the refSet.
67+
*/
68+
if (options.dereference.immutable) {
69+
mutableRefsSet.refs
8170
.filter((ref) => ref.uri.startsWith('immutable://'))
8271
.map((ref) =>
8372
Reference({
8473
...ref,
8574
uri: ref.uri.replace(/^immutable:\/\//, ''),
8675
}),
87-
);
76+
)
77+
.forEach((ref) => immutableRefSet.add(ref));
78+
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
79+
refSet = immutableRefSet;
80+
}
8881

89-
refSet.clean();
90-
immutableRefs.forEach((ref) => refSet.add(ref));
82+
/**
83+
* Release all memory if this refSet was not provided as a configuration option.
84+
* If provided as configuration option, then provider is responsible for cleanup.
85+
*/
86+
if (options.dereference.refSet === null) {
87+
immutableRefSet.clean();
9188
}
9289

9390
return dereferencedElement;

packages/apidom-reference/src/dereference/strategies/asyncapi-2/index.ts

+43-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import stampit from 'stampit';
2-
import { defaultTo, propEq } from 'ramda';
3-
import { createNamespace, visit, Element } from '@swagger-api/apidom-core';
2+
import { createNamespace, visit, Element, cloneDeep } from '@swagger-api/apidom-core';
43
import asyncApi2Namespace, {
54
getNodeType,
65
isAsyncApi2Element,
@@ -40,15 +39,34 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
4039

4140
async dereference(file: IFile, options: IReferenceOptions): Promise<Element> {
4241
const namespace = createNamespace(asyncApi2Namespace);
43-
const refSet = defaultTo(ReferenceSet(), options.dereference.refSet);
42+
const immutableRefSet = options.dereference.refSet ?? ReferenceSet();
43+
const mutableRefsSet = ReferenceSet();
44+
let refSet = immutableRefSet;
4445
let reference;
4546

46-
if (!refSet.has(file.uri)) {
47+
if (!immutableRefSet.has(file.uri)) {
4748
reference = Reference({ uri: file.uri, value: file.parseResult });
48-
refSet.add(reference);
49+
immutableRefSet.add(reference);
4950
} else {
5051
// pre-computed refSet was provided as configuration option
51-
reference = refSet.find(propEq(file.uri, 'uri'));
52+
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
53+
}
54+
55+
/**
56+
* Clone refSet due the dereferencing process being mutable.
57+
* We don't want to mutate the original refSet and the references.
58+
*/
59+
if (options.dereference.immutable) {
60+
immutableRefSet.refs
61+
.map((ref) =>
62+
Reference({
63+
...ref,
64+
value: cloneDeep(ref.value),
65+
}),
66+
)
67+
.forEach((ref) => mutableRefsSet.add(ref));
68+
reference = mutableRefsSet.find((ref) => ref.uri === file.uri);
69+
refSet = mutableRefsSet;
5270
}
5371

5472
const visitor = AsyncApi2DereferenceVisitor({ reference, namespace, options });
@@ -58,11 +76,28 @@ const AsyncApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampi
5876
});
5977

6078
/**
61-
* Release all memory if this refSet was not provided as an configuration option.
79+
* If immutable option is set, replay refs from the refSet.
80+
*/
81+
if (options.dereference.immutable) {
82+
mutableRefsSet.refs
83+
.filter((ref) => ref.uri.startsWith('immutable://'))
84+
.map((ref) =>
85+
Reference({
86+
...ref,
87+
uri: ref.uri.replace(/^immutable:\/\//, ''),
88+
}),
89+
)
90+
.forEach((ref) => immutableRefSet.add(ref));
91+
reference = immutableRefSet.find((ref) => ref.uri === file.uri);
92+
refSet = immutableRefSet;
93+
}
94+
95+
/**
96+
* Release all memory if this refSet was not provided as a configuration option.
6297
* If provided as configuration option, then provider is responsible for cleanup.
6398
*/
6499
if (options.dereference.refSet === null) {
65-
refSet.clean();
100+
immutableRefSet.clean();
66101
}
67102

68103
return dereferencedElement;

0 commit comments

Comments
 (0)