@@ -43,17 +43,21 @@ function isValid (isArray, type, payload, method) {
4343 * @returns {Object } Serialised relationship
4444 * @private
4545 */
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
46+ function serialiseRelationOne ( node , nodeType ) {
47+ let relation = { }
48+ for ( const prop of Object . keys ( node ) ) {
49+ if ( prop &&
50+ // Properties not being put in data.attributes
51+ ! [ 'id' , 'type' ] . includes ( prop ) &&
52+ // Exclude a valid JSON:API links object being put in data.attributes
53+ ! ( prop === 'links' && ( node [ prop ] . self || node [ prop ] . related ) )
54+ ) {
55+ relation = serialiseAttr ( node [ prop ] , prop , relation )
56+ } else relation [ prop ] = node [ prop ]
5557 }
56- return relations
58+ // Guess relationship type if not provided
59+ if ( ! relation . type ) relation . type = nodeType
60+ return relation
5761}
5862
5963/**
@@ -65,50 +69,35 @@ function serialiseRelationOne (node, relations, key) {
6569 * @returns {Object } Serialised relationship
6670 * @private
6771 */
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+ function serialiseRelationMany ( node , nodeType ) {
73+ const relation = [ ]
74+ for ( const prop of node ) {
75+ const serialised = serialiseRelationOne ( prop )
76+ // Guess relationship type if not provided
77+ if ( ! serialised . type ) serialised . type = nodeType
78+ relation . push ( serialised )
7279 }
73- return relations
80+ return relation
7481}
7582
7683/**
7784 * Serialises a relational object to JSON:API format
7885 *
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-
95- /**
96- * Serialises an object to JSON:API format
97- *
9886 * @param {Object } node Resource object
9987 * @param {string } nodeType Resource type of the object
10088 * @param {string } key The resource object's key value
10189 * @param {Object } data Root JSON:API data object
10290 * @private
10391 */
104- function serialiseObject ( node , nodeType , key , data ) {
92+ function serialiseRelation ( node , nodeType , key , data ) {
10593 if ( ! data . relationships ) data . relationships = { }
106- // Guess type if not provided
107- if ( ! node . type ) node . type = nodeType
10894 data . relationships [ key ] = {
109- data : Object . assign ( node )
95+ data : Array . isArray ( node . data )
96+ ? serialiseRelationMany ( node . data , nodeType )
97+ : serialiseRelationOne ( node . data , nodeType )
11098 }
111- data . relationships = serialiseRelation ( data . relationships )
99+ if ( node ?. links ?. self || node ?. links ?. related ) data . relationships [ key ] . links = node . links
100+ if ( node ?. meta ) data . relationships [ key ] . meta = node . meta
112101 return data
113102}
114103
@@ -123,8 +112,9 @@ function serialiseObject (node, nodeType, key, data) {
123112 */
124113function serialiseArray ( node , nodeType , key , data ) {
125114 if ( ! data . relationships ) data . relationships = { }
115+
126116 data . relationships [ key ] = {
127- data : node . map ( ( { id, type, ...attributes } ) => {
117+ data : node . data . map ( ( { id, type, ...attributes } ) => {
128118 return {
129119 id,
130120 type : type || nodeType ,
@@ -146,7 +136,8 @@ function serialiseArray (node, nodeType, key, data) {
146136 */
147137function serialiseAttr ( node , key , data ) {
148138 if ( ! data . attributes ) data . attributes = { }
149- data . attributes [ key ] = node
139+ if ( key === 'links' && ( node . self || node . related ) ) data . links = node
140+ else data . attributes [ key ] = node
150141 return data
151142}
152143
@@ -158,7 +149,10 @@ function serialiseAttr (node, key, data) {
158149 * @private
159150 */
160151function hasID ( node ) {
161- return Object . prototype . hasOwnProperty . call ( node , 'id' )
152+ if ( ! node . data ) return false
153+ // Check if relationship is to-many
154+ const nodeData = Array . isArray ( node . data ) ? node . data [ 0 ] : node . data
155+ return Object . prototype . hasOwnProperty . call ( nodeData , 'id' )
162156}
163157
164158/**
@@ -198,16 +192,17 @@ function serialiseRootObject (type, payload, method, options) {
198192 isValid ( false , type , payload , method )
199193 type = options . pluralTypes ( options . camelCaseTypes ( type ) )
200194 let data = { type }
195+ // ID not required for POST requests
201196 if ( payload ?. id ) data . id = String ( payload . id )
202197 for ( const key in payload ) {
203198 const node = payload [ key ]
204199 const nodeType = options . pluralTypes ( options . camelCaseTypes ( key ) )
205200 // 1. Skip null nodes, 2. Only grab objects, 3. Filter to only serialise relationable objects
206201 if ( node !== null && node ?. constructor === Object && hasID ( node ) ) {
207- data = serialiseObject ( node , nodeType , key , data )
202+ data = serialiseRelation ( node , nodeType , key , data )
208203 // 1. Skip null nodes, 2. Only grab arrays, 3. Filter to only serialise relationable arrays
209- } else if ( node !== null && Array . isArray ( node ) && ( node . length > 0 && hasID ( node [ 0 ] ) ) ) {
210- data = serialiseArray ( node , nodeType , key , data )
204+ // } else if (node !== null && node?.constructor === Object && hasID(node)) {
205+ // data = serialiseArray(node, nodeType, key, data)
211206 // 1. Don't place id/key inside attributes object
212207 } else if ( key !== 'id' && key !== 'type' ) {
213208 data = serialiseAttr ( node , key , data )
0 commit comments