@@ -4,6 +4,8 @@ const fs = require('fs');
4
4
const jsonPatch = require ( 'rfc6902' ) ;
5
5
const refParser = require ( './patched-json-schema-ref-parser' ) ;
6
6
const jps = require ( './json-pointer-selectors' ) ;
7
+ const jsonPtr = require ( 'json-ptr' ) ;
8
+ const clone = require ( './clone' ) ;
7
9
8
10
/**
9
11
@param {object } doc
@@ -13,37 +15,70 @@ const jps = require('./json-pointer-selectors');
13
15
14
16
@return {object } doc - modified source
15
17
*/
16
- const inherit = function ( doc , options ) {
18
+ const applyInherit = function ( doc , options , rootDoc , inWith ) {
17
19
if ( typeof doc != 'object' || doc == null ) return doc ;
18
-
20
+
21
+ rootDoc = rootDoc || doc ;
19
22
options = options || { } ;
20
23
if ( options . inherit == null ) {
21
24
return doc ;
22
25
}
23
26
if ( options . inherit === true ) {
24
27
options . inherit = '$inherit' ;
25
28
}
29
+
30
+ const $inherit = options . inherit ;
31
+ const _inherit = encodeURIComponent ( $inherit ) ;
32
+ const re_inherit = new RegExp ( `\/${ _inherit } \/source` , 'g' ) ;
33
+ const _source = `${ _inherit } \/source` ;
34
+ const re_source = new RegExp ( `^(.*\/)${ _source } \/?(.*)` ) ;
35
+ const _with = `${ _inherit } \/with` ;
36
+ const re_with = new RegExp ( `^(.*\/)${ _with } \/?(.*)` ) ;
37
+
26
38
if ( Array . isArray ( doc ) ) {
27
39
for ( let i = 0 ; i < doc . length ; i ++ ) {
28
- doc [ i ] = inherit ( doc [ i ] , options ) ;
40
+ doc [ i ] = applyInherit ( doc [ i ] , options , rootDoc , inWith ) ;
29
41
}
30
42
} else {
31
43
for ( const key in doc ) {
32
44
if ( key == '$ref' ) {
33
45
if ( ! doc . $ref . match ( / ^ # / ) ) {
34
46
throw new Error ( 'inherit: all outer references \'$ref\' must be resolved!' ) ;
35
47
} else {
36
- // fix internal references, if they have '/$inherit/source', it is correct for bundling
37
- // but we are going to move object 2 levels up, so it won't be correct
38
- doc . $ref = doc . $ref . replace ( new RegExp ( `\/${ encodeURIComponent ( options . inherit ) } \/source` , 'g' ) , '' ) ;
48
+ // if internal references are like '/$inherit/source*' we just bring the document
49
+ // because after applying json-patch these references will be invalid
50
+ const re = doc . $ref . match ( re_source ) ;
51
+ if ( re ) {
52
+ //console.error('found source ref', doc)
53
+ // pointer to whole document under key 'source'
54
+ if ( inWith || ! re [ 2 ] ) {
55
+ //console.error('cloning document', doc.$ref, re, re_source)
56
+ return clone ( jsonPtr . get ( rootDoc , doc . $ref ) ) ;
57
+ } else {
58
+ //console.error('replacing $ref', doc.$ref, re, re_source)
59
+ doc . $ref = doc . $ref . replace ( re_inherit , '' ) ;
60
+ }
61
+ } else {
62
+ // if internal references are like '/$inherit/with*' we just bring the document
63
+ // because after applying json-patch these references will be invalid
64
+ const re = doc . $ref . match ( re_with ) ;
65
+ if ( re ) {
66
+ //console.error('found with ref', doc)
67
+ // pointer to whole document under key 'source'
68
+ //console.error('cloning document', doc.$ref, re, re_with)
69
+ return clone ( jsonPtr . get ( rootDoc , doc . $ref ) ) ;
70
+ }
71
+ }
39
72
}
40
73
}
41
- doc [ key ] = inherit ( doc [ key ] , options ) ;
74
+ if ( key in doc ) {
75
+ doc [ key ] = applyInherit ( doc [ key ] , options , rootDoc , key == 'with' || inWith ) ;
76
+ }
42
77
}
43
- if ( options . inherit && doc [ options . inherit ] ) {
44
- const inh = doc [ options . inherit ] ;
78
+ if ( doc [ $ inherit] ) {
79
+ const inh = doc [ $ inherit] ;
45
80
if ( inh . source == null ) {
46
- throw new Error ( `inherit: ${ options . inherit } .source is null!` ) ;
81
+ throw new Error ( `inherit: ${ $ inherit} .source is null!` ) ;
47
82
}
48
83
if ( ! ( inh . with == null || Array . isArray ( inh . with ) && inh . with . length == 0 ) ) {
49
84
const patch = ( options . compileJsonPatch || jps . compileJsonPatch ) ( inh . source , inh . with )
@@ -67,6 +102,7 @@ const inherit = function (doc, options) {
67
102
@return {Promise.<object> }
68
103
*/
69
104
const bundle = function ( filepath , options ) {
105
+ //console.error('Bundle()')
70
106
if ( ! fs . existsSync ( filepath ) ) {
71
107
return new Promise ( ( res , rej ) => rej ( new Error ( `invalid argument: file "${ filepath } " not exists` ) ) ) ;
72
108
}
@@ -78,9 +114,9 @@ const bundle = function (filepath, options) {
78
114
return parser . bundle ( filepath )
79
115
. then ( ( doc ) => {
80
116
try {
81
- doc = inherit ( doc , options ) ;
117
+ doc = applyInherit ( doc , options ) ;
82
118
} catch ( e ) {
83
- console . error ( 'inherit' , 'doc:' , doc , 'error:' , e ) ;
119
+ console . error ( 'inherit' , 'doc:' , JSON . stringify ( doc , null , ' ' ) , 'error:' , e ) ;
84
120
throw e ;
85
121
}
86
122
return doc ;
@@ -100,14 +136,15 @@ const bundle = function (filepath, options) {
100
136
@return {Promise.<object> }
101
137
*/
102
138
const dereference = function ( doc , options ) {
139
+ //console.error('Dereference()')
103
140
if ( typeof doc == 'string' ) {
104
141
return bundle ( doc , options )
105
142
. then ( ( doc ) => {
106
143
return dereference ( doc ) ;
107
144
} ) ;
108
145
}
109
146
try {
110
- doc = inherit ( doc , options ) ;
147
+ doc = applyInherit ( doc , options ) ;
111
148
} catch ( e ) {
112
149
console . error ( 'inherit' , 'doc:' , doc , 'error:' , e ) ;
113
150
return new Promise ( function ( resolve , reject ) {
0 commit comments