Skip to content

Commit 63a41d4

Browse files
authored
feat(reference): apply dereferencing architecture 2.0 to OpenAPI 2.0 (#3931)
Refs #3924
1 parent bbb9a25 commit 63a41d4

File tree

8 files changed

+523
-269
lines changed

8 files changed

+523
-269
lines changed

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import stampit from 'stampit';
2-
import { propEq } from 'ramda';
32
import { Element, isElement, cloneDeep, visit } from '@swagger-api/apidom-core';
43

54
import DereferenceStrategy from '../DereferenceStrategy';
@@ -38,7 +37,7 @@ const ApiDOMDereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit(
3837
refSet.add(reference);
3938
} else {
4039
// pre-computed refSet was provided as configuration option
41-
reference = refSet.find(propEq(file.uri, 'uri'));
40+
reference = refSet.find((ref) => ref.uri === file.uri);
4241
}
4342

4443
/**

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

+46-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 openApi2Namespace, {
54
getNodeType,
65
isSwaggerElement,
@@ -40,15 +39,39 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
4039

4140
async dereference(file: IFile, options: IReferenceOptions): Promise<Element> {
4241
const namespace = createNamespace(openApi2Namespace);
43-
const refSet = defaultTo(ReferenceSet(), options.dereference.refSet);
42+
const refSet = options.dereference.refSet ?? ReferenceSet();
4443
let reference;
4544

4645
if (!refSet.has(file.uri)) {
4746
reference = Reference({ uri: file.uri, value: file.parseResult });
4847
refSet.add(reference);
4948
} else {
5049
// pre-computed refSet was provided as configuration option
51-
reference = refSet.find(propEq(file.uri, 'uri'));
50+
reference = refSet.find((ref) => ref.uri === file.uri);
51+
}
52+
53+
/**
54+
* Clone refSet due the dereferencing process being mutable.
55+
* We don't want to mutate the original refSet and the references.
56+
*/
57+
if (options.dereference.immutable) {
58+
const immutableRefs = refSet.refs.map((ref) =>
59+
Reference({
60+
...ref,
61+
uri: `immutable://${ref.uri}`,
62+
}),
63+
);
64+
const mutableRefs = refSet.refs.map((ref) =>
65+
Reference({
66+
...ref,
67+
value: cloneDeep(ref.value),
68+
}),
69+
);
70+
71+
refSet.clean();
72+
mutableRefs.forEach((ref) => refSet.add(ref));
73+
immutableRefs.forEach((ref) => refSet.add(ref));
74+
reference = refSet.find((ref) => ref.uri === file.uri);
5275
}
5376

5477
const visitor = OpenApi2DereferenceVisitor({ reference, namespace, options });
@@ -57,12 +80,27 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
5780
nodeTypeGetter: getNodeType,
5881
});
5982

60-
/**
61-
* Release all memory if this refSet was not provided as an configuration option.
62-
* If provided as configuration option, then provider is responsible for cleanup.
63-
*/
6483
if (options.dereference.refSet === null) {
84+
/**
85+
* Release all memory if this refSet was not provided as a configuration option.
86+
* If provided as configuration option, then provider is responsible for cleanup.
87+
*/
88+
refSet.clean();
89+
} else if (options.dereference.immutable) {
90+
/**
91+
* If immutable option is set, then we need to remove mutable refs from the refSet.
92+
*/
93+
const immutableRefs = refSet.refs
94+
.filter((ref) => ref.uri.startsWith('immutable://'))
95+
.map((ref) =>
96+
Reference({
97+
...ref,
98+
uri: ref.uri.replace(/^immutable:\/\//, ''),
99+
}),
100+
);
101+
65102
refSet.clean();
103+
immutableRefs.forEach((ref) => refSet.add(ref));
66104
}
67105

68106
return dereferencedElement;

0 commit comments

Comments
 (0)