@@ -34,6 +34,64 @@ function isValid (isArray, type, payload, method) {
3434 }
3535}
3636
37+ /**
38+ * Serialises a relational data object to JSON:API format
39+ *
40+ * @param {Object } node Existing relation object
41+ * @param {Object } relations Relation object being built
42+ * @param {string } key Name of the relationship
43+ * @returns {Object } Serialised relationship
44+ * @private
45+ */
46+ function serialiseRelationOne ( node , relations , key ) {
47+ relations [ key ] = { data : { } }
48+ for ( const prop of Object . keys ( node [ key ] . data ) ) {
49+ const propNode = node [ key ] . data [ prop ]
50+ let propRelations = relations [ key ] . data
51+ // Pull everything but id and type into data.attributes
52+ if ( prop && ! [ 'id' , 'type' ] . includes ( prop ) ) {
53+ propRelations = serialiseAttr ( propNode , prop , propRelations )
54+ } else propRelations [ prop ] = propNode
55+ }
56+ return relations
57+ }
58+
59+ /**
60+ * Serialises a relational data array to JSON:API format
61+ *
62+ * @param {Object } node Existing relation object
63+ * @param {Object } relations Relation object being built
64+ * @param {string } key Name of the relationship
65+ * @returns {Object } Serialised relationship
66+ * @private
67+ */
68+ function serialiseRelationMany ( node , relations , key ) {
69+ relations [ key ] = { data : [ ] }
70+ for ( const prop of node [ key ] . data ) {
71+ relations [ key ] . data . push ( prop )
72+ }
73+ return relations
74+ }
75+
76+ /**
77+ * Serialises a relational object to JSON:API format
78+ *
79+ * @param {Object } node Relation object
80+ * @returns {Object } Serialised relationship
81+ * @private
82+ */
83+ function serialiseRelation ( node ) {
84+ // Create a new object to handle collisions with attributes.attributes
85+ let relations = { }
86+ for ( const key in node ) {
87+ const isToMany = Array . isArray ( node [ key ] . data )
88+ relations = isToMany
89+ ? serialiseRelationMany ( node , relations , key )
90+ : serialiseRelationOne ( node , relations , key )
91+ }
92+ return relations
93+ }
94+
3795/**
3896 * Serialises an object to JSON:API format
3997 *
@@ -50,6 +108,7 @@ function serialiseObject (node, nodeType, key, data) {
50108 data . relationships [ key ] = {
51109 data : Object . assign ( node )
52110 }
111+ data . relationships = serialiseRelation ( data . relationships )
53112 return data
54113}
55114
@@ -65,13 +124,15 @@ function serialiseObject (node, nodeType, key, data) {
65124function serialiseArray ( node , nodeType , key , data ) {
66125 if ( ! data . relationships ) data . relationships = { }
67126 data . relationships [ key ] = {
68- data : node . map ( ( { id, type } ) => {
127+ data : node . map ( ( { id, type, ... attributes } ) => {
69128 return {
70129 id,
71- type : type || nodeType
130+ type : type || nodeType ,
131+ attributes : Object . keys ( attributes ) . length ? attributes : undefined
72132 }
73133 } )
74134 }
135+ data . relationships = serialiseRelation ( data . relationships )
75136 return data
76137}
77138
@@ -137,24 +198,21 @@ function serialiseRootObject (type, payload, method, options) {
137198 isValid ( false , type , payload , method )
138199 type = options . pluralTypes ( options . camelCaseTypes ( type ) )
139200 let data = { type }
140-
141201 if ( payload ?. id ) data . id = String ( payload . id )
142-
143202 for ( const key in payload ) {
144203 const node = payload [ key ]
145204 const nodeType = options . pluralTypes ( options . camelCaseTypes ( key ) )
146205 // 1. Skip null nodes, 2. Only grab objects, 3. Filter to only serialise relationable objects
147206 if ( node !== null && node ?. constructor === Object && hasID ( node ) ) {
148- data = serialiseObject ( node , nodeType , key , data , method )
207+ data = serialiseObject ( node , nodeType , key , data )
149208 // 1. Skip null nodes, 2. Only grab arrays, 3. Filter to only serialise relationable arrays
150209 } else if ( node !== null && Array . isArray ( node ) && ( node . length > 0 && hasID ( node [ 0 ] ) ) ) {
151- data = serialiseArray ( node , nodeType , key , data , method )
210+ data = serialiseArray ( node , nodeType , key , data )
152211 // 1. Don't place id/key inside attributes object
153212 } else if ( key !== 'id' && key !== 'type' ) {
154213 data = serialiseAttr ( node , key , data )
155214 }
156215 }
157-
158216 return { data }
159217}
160218
0 commit comments