import { CustomError } from '../error' export default (req) => { try { const { queryResult, settings } = req const { url, responseType } = settings const entity = req.params.children ?? req.params.entity if (responseType === 'json') return queryResult.primary const { entityDef, body } = req const { primaryKey } = entityDef const result: TResponse = { links: { self: url, first: { url, body: { ...body, pagination: { ...body.pagination, page: 1, }, }, }, last: { url, body: { ...body, pagination: { ...body.pagination, page: queryResult.metadata.pages, }, }, }, }, data: [], metadata: queryResult.metadata, } if (result.metadata.page < result.metadata.pages) { result.links.next = { url, body: { ...body, pagination: { ...body.pagination, page: result.metadata.page + 1, }, }, } } if ( result.metadata.page > 1 && result.metadata.page <= result.metadata.pages ) { result.links.prev = { url, body: { ...body, pagination: { ...body.pagination, page: result.metadata.page - 1, }, }, } } let fields = body.fields && body.fields[entity] ? body.fields[entity] : [] fields = fields.map((field) => field.trim()) for (const record of queryResult.primary) { const element: TDataElement = { type: entity, id: record[primaryKey], links: { self: `${url}/${record[primaryKey]}`, }, attributes: {}, } /** * Attributes handler */ Object.keys(record).forEach((key) => { if (!fields.length || fields.includes(key)) { element.attributes[key] = record[key] } }) /* END Attributes handler */ /** * Relationships handler */ if (entity === req.params.entity && entityDef.relationships) { Object.keys(entityDef.relationships).forEach((relationship) => { if (!element.relationships) { element.relationships = {} } // has-one if (entityDef.relationships[relationship].type === 'has-one') { if (record[entityDef.relationships[relationship].foreignKey]) { element.relationships[relationship] = { type: relationship, id: record[entityDef.relationships[relationship].foreignKey], } } // Handle included relationships if ( queryResult.secondary[relationship] && queryResult.secondary[relationship].length ) { let relatedFields = body.fields && body.fields[relationship] ? body.fields[relationship] : [] relatedFields = relatedFields.map((field) => field.trim()) const relatedRecord = queryResult.secondary[relationship][0] if (relatedFields.length) { Object.keys(relatedRecord).forEach((key) => { if (!relatedFields.includes(key)) { delete relatedRecord[key] } }) } element.relationships[relationship].attributes = relatedRecord } } // has-many if (entityDef.relationships[relationship].type === 'has-many') { let relatedFields = body.fields && body.fields[relationship] ? body.fields[relationship] : [] relatedFields = relatedFields.map((field) => field.trim()) const relatedRecords: Record[] = [] if (queryResult.secondary[relationship]) { for (const relatedRecord of queryResult.secondary[relationship]) { const record: Record = { type: relationship, id: relatedRecord[ entityDef.relationships[relationship].primaryKey ], } if (relatedFields.length) { Object.keys(relatedRecord).forEach((key) => { if (!relatedFields.includes(key)) { delete relatedRecord[key] } }) } record.attributes = relatedRecord relatedRecords.push(record) } } element.relationships[relationship] = { links: { related: `${url}/${record[primaryKey]}/${relationship}`, }, } if (queryResult.secondary[relationship]) { element.relationships[relationship].data = relatedRecords || [] } } }) } /* END Relationships handler */ result.data.push(element) } return result } catch (error: any) { throw new CustomError(`[normalizeDataStoreResults] ${error.message}`, 400) } }