2
2
3
3
Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
4
4
5
+ const $registeredModels = [ ] ;
6
+ const $registeredAttributes = [ ] ;
7
+ const $registeredRelationships = [ ] ;
8
+
5
9
class Model {
6
- toJSON ( ) {
7
- return { ...this
10
+ toDTO ( ) {
11
+ const response = {
12
+ ...this
13
+ } ;
14
+ delete response . _type ;
15
+ const rels = $registeredRelationships . find ( e => e . klass === this . constructor ) ?? {
16
+ attributes : { }
8
17
} ;
18
+ for ( const key in response ) {
19
+ if ( rels . attributes [ key ] || response [ key ] instanceof Model ) {
20
+ response [ `${ key } Id` ] = response [ key ] ?. id ?? null ;
21
+ delete response [ key ] ;
22
+ }
23
+ }
24
+ return response ;
25
+ }
26
+ toJSON ( maxDepth = 100 ) {
27
+ const response = {
28
+ ...this
29
+ } ;
30
+ delete response . _type ;
31
+ for ( const key in response ) {
32
+ if ( response [ key ] instanceof Model ) {
33
+ if ( maxDepth <= 0 ) {
34
+ delete response [ key ] ;
35
+ } else {
36
+ response [ key ] = response [ key ] . toJSON ( maxDepth - 1 ) ;
37
+ }
38
+ }
39
+ }
40
+ return response ;
9
41
}
10
-
11
42
toFormData ( ) {
12
43
const data = this . toJSON ( ) ;
13
44
const formData = new FormData ( ) ;
14
-
15
45
for ( const key in data ) {
16
46
if ( data [ key ] === null || data [ key ] === undefined ) {
17
47
continue ;
18
48
}
19
-
20
49
if ( Array . isArray ( data [ key ] ) ) {
21
50
for ( const value of data [ key ] ) {
22
51
formData . append ( key + "[]" , value ) ;
@@ -27,47 +56,49 @@ class Model {
27
56
formData . append ( key , data [ key ] ) ;
28
57
}
29
58
}
30
-
31
59
return formData ;
32
60
}
33
-
34
61
}
35
62
36
- function debug ( ...args ) {
37
- debug . adapter ( ...args ) ;
63
+ function debug ( level , ...args ) {
64
+ debug . adapter ( level , ...args ) ;
38
65
}
39
-
40
- debug . adapter = ( ...args ) => console . warn ( ...args ) ;
66
+ debug . adapter = ( level , ...args ) => {
67
+ switch ( level ) {
68
+ case 'warn' :
69
+ console . warn ( ...args ) ;
70
+ break ;
71
+ case 'error' :
72
+ console . error ( ...args ) ;
73
+ break ;
74
+ case 'info' :
75
+ default :
76
+ console . log ( ...args ) ;
77
+ break ;
78
+ }
79
+ } ;
41
80
42
81
class Parser {
43
- static $registeredModels = [ ] ;
44
- static $registeredAttributes = [ ] ;
45
- static $registeredRelationships = [ ] ;
46
82
resolved = { } ;
47
-
48
83
constructor ( data , included = [ ] ) {
49
84
this . data = data ;
50
85
this . included = included ;
51
86
}
52
-
53
87
run ( ) {
54
88
if ( ! this . data ) {
55
89
return null ;
56
90
}
57
-
58
91
const {
59
92
data,
60
93
included
61
94
} = this ;
62
95
const fullIncluded = Array . isArray ( data ) ? [ ...data , ...included ] : [ data , ...included ] ;
63
96
return this . parse ( data , fullIncluded ) ;
64
97
}
65
-
66
98
parse ( data , included = [ ] ) {
67
99
if ( ! data ) {
68
100
return null ;
69
101
}
70
-
71
102
if ( Array . isArray ( data ) ) {
72
103
return this . parseList ( data , included ) ;
73
104
} else if ( "data" in data && ! ( "id" in data ) ) {
@@ -76,119 +107,126 @@ class Parser {
76
107
return this . parseElement ( data , included ) ;
77
108
}
78
109
}
79
-
80
110
parseList ( list , included ) {
81
111
return list . map ( e => {
82
112
return this . parseElement ( e , included ) ;
83
113
} ) ;
84
114
}
85
-
86
115
parseElement ( element , included ) {
87
116
const uniqueKey = `${ element . id } $${ element . type } ` ;
88
-
89
117
if ( this . resolved [ uniqueKey ] ) {
90
118
return this . resolved [ uniqueKey ] ;
91
119
}
92
-
93
120
const loadedElement = Parser . load ( element , included ) ;
94
- const model = Parser . $registeredModels . find ( e => e . type === loadedElement . type ) ;
95
- const attrData = Parser . $registeredAttributes . find ( e => e . klass === model ?. klass ) ;
96
- const relsData = Parser . $registeredRelationships . find ( e => e . klass === model ?. klass ) ;
97
- const instance = new ( model ?. klass || Model ) ( ) ;
121
+ const model = $registeredModels . find ( e => e . type === loadedElement . type ) ;
122
+ const instance = this . wrapWhenPartial ( new ( model ?. klass || Model ) ( ) , loadedElement ) ;
98
123
this . resolved [ uniqueKey ] = instance ;
124
+ if ( model && model . createFn ) {
125
+ return model . createFn ( instance , loadedElement , relation => this . parse ( relation , included ) ) ;
126
+ }
127
+ const attrData = $registeredAttributes . find ( e => e . klass === model ?. klass ) ;
128
+ const relsData = $registeredRelationships . find ( e => e . klass === model ?. klass ) ;
99
129
instance . id = loadedElement . id ;
100
-
101
- for ( const key in loadedElement . attributes ) {
102
- const parser = attrData ?. attributes ?. [ key ] ;
103
-
130
+ instance . _type = loadedElement . type ;
131
+ this . parseAttributes ( instance , loadedElement , attrData ) ;
132
+ this . parseRelationships ( instance , loadedElement , relsData , included ) ;
133
+ return instance ;
134
+ }
135
+ wrapWhenPartial ( instance , loadedElement ) {
136
+ if ( loadedElement . $_partial ) {
137
+ return new Proxy ( instance , {
138
+ get : function ( target , prop ) {
139
+ if ( prop in target ) {
140
+ return target [ prop ] ;
141
+ }
142
+ if ( prop === "$_partial" ) {
143
+ return true ;
144
+ }
145
+ debug ( 'error' , `Trying to call property "${ prop . toString ( ) } " to a model that is not included. Add "${ loadedElement . type } " to included models.` ) ;
146
+ return undefined ;
147
+ }
148
+ } ) ;
149
+ }
150
+ return instance ;
151
+ }
152
+ parseRelationships ( instance , loadedElement , relsData , included ) {
153
+ for ( const key in loadedElement . relationships ) {
154
+ const relation = loadedElement . relationships [ key ] ;
155
+ const parser = relsData ?. attributes ?. [ key ] ;
104
156
if ( parser ) {
105
- instance [ parser . key ] = parser . parser ( loadedElement . attributes [ key ] ) ;
157
+ instance [ parser . key ] = parser . parser ( this . parse ( relation , included ) ) ;
106
158
} else {
107
- instance [ key ] = loadedElement . attributes [ key ] ;
108
- debug ( `Undeclared key "${ key } " in "${ loadedElement . type } "` ) ;
159
+ instance [ key ] = this . parse ( relation , included ) ;
160
+ debug ( 'warn' , `Undeclared relationship "${ key } " in "${ loadedElement . type } "` ) ;
109
161
}
110
162
}
111
-
112
- if ( attrData ) {
113
- for ( const key in attrData . attributes ) {
114
- const parser = attrData . attributes [ key ] ;
115
-
163
+ if ( relsData ) {
164
+ for ( const key in relsData . attributes ) {
165
+ const parser = relsData . attributes [ key ] ;
116
166
if ( ! ( parser . key in instance ) ) {
117
167
if ( "default" in parser ) {
118
168
instance [ parser . key ] = parser . default ;
119
169
} else {
120
- debug ( `Missing attribute "${ key } " in "${ loadedElement . type } "` ) ;
170
+ debug ( 'warn' , `Missing relationships "${ key } " in "${ loadedElement . type } "` ) ;
121
171
}
122
172
}
123
173
}
124
174
}
125
-
126
- for ( const key in loadedElement . relationships ) {
127
- const relation = loadedElement . relationships [ key ] ;
128
- const parser = relsData ?. attributes ?. [ key ] ;
129
-
175
+ }
176
+ parseAttributes ( instance , loadedElement , attrData ) {
177
+ for ( const key in loadedElement . attributes ) {
178
+ const parser = attrData ?. attributes ?. [ key ] ;
130
179
if ( parser ) {
131
- instance [ parser . key ] = parser . parser ( this . parse ( relation , included ) ) ;
180
+ instance [ parser . key ] = parser . parser ( loadedElement . attributes [ key ] ) ;
132
181
} else {
133
- instance [ key ] = this . parse ( relation , included ) ;
134
- debug ( `Undeclared relationship "${ key } " in "${ loadedElement . type } "` ) ;
182
+ instance [ key ] = loadedElement . attributes [ key ] ;
183
+ debug ( 'warn' , `Undeclared key "${ key } " in "${ loadedElement . type } "` ) ;
135
184
}
136
185
}
137
-
138
- if ( relsData ) {
139
- for ( const key in relsData . attributes ) {
140
- const parser = relsData . attributes [ key ] ;
141
-
186
+ if ( attrData ) {
187
+ for ( const key in attrData . attributes ) {
188
+ const parser = attrData . attributes [ key ] ;
142
189
if ( ! ( parser . key in instance ) ) {
143
190
if ( "default" in parser ) {
144
191
instance [ parser . key ] = parser . default ;
145
192
} else {
146
- debug ( `Missing relationships "${ key } " in "${ loadedElement . type } "` ) ;
193
+ debug ( 'warn' , `Missing attribute "${ key } " in "${ loadedElement . type } "` ) ;
147
194
}
148
195
}
149
196
}
150
197
}
151
-
152
- return instance ;
153
198
}
154
-
155
199
static load ( element , included ) {
156
200
const found = included . find ( e => e . id == element . id && e . type === element . type ) ;
157
-
158
201
if ( ! found ) {
159
- debug ( `Relationship with type ${ element . type } with id ${ element . id } not present in included` ) ;
202
+ debug ( 'info' , `Relationship with type ${ element . type } with id ${ element . id } not present in included` ) ;
160
203
}
161
-
162
- return found || { ...element ,
204
+ return found || {
205
+ ...element ,
163
206
$_partial : true
164
207
} ;
165
208
}
166
-
167
209
}
168
210
169
211
function Attr ( sourceKey , options = {
170
212
parser : v => v
171
213
} ) {
172
214
return function _Attr ( klass , key ) {
173
- let model = Parser . $registeredAttributes . find ( e => e . klass === klass . constructor ) ;
174
-
215
+ let model = $registeredAttributes . find ( e => e . klass === klass . constructor ) ;
175
216
if ( ! model ) {
176
217
model = {
177
218
attributes : { } ,
178
219
klass : klass . constructor
179
220
} ;
180
- Parser . $registeredAttributes . push ( model ) ;
221
+ $registeredAttributes . push ( model ) ;
181
222
}
182
-
183
223
const data = {
184
224
parser : options . parser ?? ( v => v ) ,
185
225
key
186
226
} ;
187
-
188
227
if ( "default" in options ) {
189
228
data . default = options . default ;
190
229
}
191
-
192
230
model . attributes [ sourceKey ?? key ] = data ;
193
231
} ;
194
232
}
@@ -197,16 +235,14 @@ function Rel(sourceKey, options = {
197
235
parser : v => v
198
236
} ) {
199
237
return function _Rel ( klass , key ) {
200
- let model = Parser . $registeredRelationships . find ( e => e . klass === klass . constructor ) ;
201
-
238
+ let model = $registeredRelationships . find ( e => e . klass === klass . constructor ) ;
202
239
if ( ! model ) {
203
240
model = {
204
241
attributes : { } ,
205
242
klass : klass . constructor
206
243
} ;
207
- Parser . $registeredRelationships . push ( model ) ;
244
+ $registeredRelationships . push ( model ) ;
208
245
}
209
-
210
246
model . attributes [ sourceKey ?? key ] = {
211
247
parser : options . parser ?? ( v => v ) ,
212
248
key,
@@ -217,7 +253,7 @@ function Rel(sourceKey, options = {
217
253
218
254
function JSONAPI ( type ) {
219
255
return function _JSONAPI ( constructor ) {
220
- Parser . $registeredModels . push ( {
256
+ $registeredModels . push ( {
221
257
klass : constructor ,
222
258
type
223
259
} ) ;
0 commit comments