(data: any, fields: FieldDef[])
| 56 | } |
| 57 | |
| 58 | private processRow(data: any, fields: FieldDef[]) { |
| 59 | if (!data || typeof data !== 'object') { |
| 60 | return data; |
| 61 | } |
| 62 | |
| 63 | // handle special keys |
| 64 | for (const key of Object.keys(data)) { |
| 65 | const value = data[key]; |
| 66 | if (value === undefined) { |
| 67 | continue; |
| 68 | } |
| 69 | |
| 70 | if (key === '_count') { |
| 71 | // underlying database provider may return string for count |
| 72 | data[key] = typeof value === 'string' ? JSON.parse(value) : value; |
| 73 | } else if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) { |
| 74 | // merge delegate descendant fields |
| 75 | if (value) { |
| 76 | // descendant fields are packed as JSON |
| 77 | const subRow = this.dialect.transformOutput(value, 'Json', false); |
| 78 | |
| 79 | // process the sub-row |
| 80 | const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length) as GetModels<Schema>; |
| 81 | const idValues = getIdValues(this.schema, subModel, subRow); |
| 82 | if (Object.values(idValues).some((v) => v === null || v === undefined)) { |
| 83 | // if the row doesn't have a valid id, the joined row doesn't exist |
| 84 | delete data[key]; |
| 85 | continue; |
| 86 | } |
| 87 | const subFields = this.resolveFields(subRow, subModel); |
| 88 | const processedSubRow = this.processRow(subRow, subFields); |
| 89 | |
| 90 | // merge the sub-row into the main row |
| 91 | Object.assign(data, processedSubRow); |
| 92 | } |
| 93 | delete data[key]; |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | // process regular fields using pre-resolved field definitions |
| 98 | for (const fieldDef of fields) { |
| 99 | const value = data[fieldDef.name]; |
| 100 | if (value === undefined) { |
| 101 | continue; |
| 102 | } |
| 103 | |
| 104 | if (value === null) { |
| 105 | // scalar list defaults to empty array |
| 106 | if (fieldDef.array && !fieldDef.relation) { |
| 107 | data[fieldDef.name] = []; |
| 108 | } |
| 109 | continue; |
| 110 | } |
| 111 | |
| 112 | if (fieldDef.relation) { |
| 113 | data[fieldDef.name] = this.processRelation(value, fieldDef); |
| 114 | } else { |
| 115 | data[fieldDef.name] = this.processFieldValue(value, fieldDef); |
no test coverage detected