@@ -6,18 +6,20 @@ if (!Object.values) {
6
6
values . shim ( ) ;
7
7
}
8
8
9
+ class ReferenceError extends Error { }
10
+
9
11
// Test whether a key is a special Swagger extension.
10
12
const isExtension = ( value , key ) => _ . startsWith ( key , 'x-' ) ;
11
13
12
14
const parseReference = ( reference ) => {
13
15
const parts = reference . split ( '/' ) ;
14
16
15
17
if ( parts [ 0 ] !== '#' ) {
16
- throw new Error ( 'Schema reference must start with document root (#)' ) ;
18
+ throw new ReferenceError ( 'Schema reference must start with document root (#)' ) ;
17
19
}
18
20
19
21
if ( parts [ 1 ] !== 'definitions' || parts . length !== 3 ) {
20
- throw new Error ( 'Schema reference must be reference to #/definitions' ) ;
22
+ throw new ReferenceError ( 'Schema reference must be reference to #/definitions' ) ;
21
23
}
22
24
23
25
const id = parts [ 2 ] ;
@@ -43,11 +45,11 @@ const lookupReference = (reference, root, depth) => {
43
45
const parts = reference . split ( '/' ) . reverse ( ) ;
44
46
45
47
if ( parts . pop ( ) !== '#' ) {
46
- throw new Error ( 'Schema reference must start with document root (#)' ) ;
48
+ throw new ReferenceError ( 'Schema reference must start with document root (#)' ) ;
47
49
}
48
50
49
51
if ( parts . pop ( ) !== 'definitions' ) {
50
- throw new Error ( 'Schema reference must be reference to #/definitions' ) ;
52
+ throw new ReferenceError ( 'Schema reference must be reference to #/definitions' ) ;
51
53
}
52
54
53
55
const id = parts [ parts . length - 1 ] ;
@@ -67,7 +69,7 @@ const lookupReference = (reference, root, depth) => {
67
69
}
68
70
69
71
if ( value === undefined ) {
70
- throw new Error ( `Reference to ${ reference } does not exist` ) ;
72
+ throw new ReferenceError ( `Reference to ${ reference } does not exist` ) ;
71
73
}
72
74
73
75
return {
@@ -93,6 +95,20 @@ const pathHasCircularReference = (paths, path, reference) => {
93
95
} ;
94
96
95
97
const dereference = ( example , root , paths , path ) => {
98
+ // We shouldn't even be dereferencing examples, but given how swagger-parser
99
+ // works it had been doing this from the start (which was caught later).
100
+ //
101
+ // See https://github.com/apiaryio/api-elements.js/issues/220
102
+ //
103
+ // At thsi point, changing that behaviour would be a significant breaking
104
+ // change and it will affect some of our larger users. Not to mention that
105
+ // swagger-parser will still dereference the examples in cases where our code
106
+ // path doesn't, it won't be easy to solve.
107
+ //
108
+ // The below code attemps to dereference an example, but if we can't we
109
+ // will just return the example (possibly a "reference object") to be
110
+ // the example value.
111
+
96
112
if ( example === null || example === undefined ) {
97
113
return example ;
98
114
}
@@ -105,7 +121,18 @@ const dereference = (example, root, paths, path) => {
105
121
return null ;
106
122
}
107
123
108
- const ref = lookupReference ( example . $ref , root ) ;
124
+ let ref ;
125
+
126
+ try {
127
+ ref = lookupReference ( example . $ref , root ) ;
128
+ } catch ( error ) {
129
+ if ( error instanceof ReferenceError ) {
130
+ // Cannot find the reference, use example
131
+ return example ;
132
+ }
133
+
134
+ throw error ;
135
+ }
109
136
110
137
const newPaths = ( paths || [ ] ) . concat ( [ currentPath ] ) ;
111
138
return dereference ( ref . referenced , root , newPaths , refPath ) ;
0 commit comments