1
1
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' ;
4
3
import openApi2Namespace , {
5
4
getNodeType ,
6
5
isSwaggerElement ,
@@ -40,15 +39,39 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
40
39
41
40
async dereference ( file : IFile , options : IReferenceOptions ) : Promise < Element > {
42
41
const namespace = createNamespace ( openApi2Namespace ) ;
43
- const refSet = defaultTo ( ReferenceSet ( ) , options . dereference . refSet ) ;
42
+ const refSet = options . dereference . refSet ?? ReferenceSet ( ) ;
44
43
let reference ;
45
44
46
45
if ( ! refSet . has ( file . uri ) ) {
47
46
reference = Reference ( { uri : file . uri , value : file . parseResult } ) ;
48
47
refSet . add ( reference ) ;
49
48
} else {
50
49
// 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 ) ;
52
75
}
53
76
54
77
const visitor = OpenApi2DereferenceVisitor ( { reference, namespace, options } ) ;
@@ -57,12 +80,27 @@ const OpenApi2DereferenceStrategy: stampit.Stamp<IDereferenceStrategy> = stampit
57
80
nodeTypeGetter : getNodeType ,
58
81
} ) ;
59
82
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
- */
64
83
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 ( / ^ i m m u t a b l e : \/ \/ / , '' ) ,
99
+ } ) ,
100
+ ) ;
101
+
65
102
refSet . clean ( ) ;
103
+ immutableRefs . forEach ( ( ref ) => refSet . add ( ref ) ) ;
66
104
}
67
105
68
106
return dereferencedElement ;
0 commit comments