diff --git a/packages/client/src/runtime/RequestHandler.ts b/packages/client/src/runtime/RequestHandler.ts index 7d641b6741de..d305e63b4c17 100644 --- a/packages/client/src/runtime/RequestHandler.ts +++ b/packages/client/src/runtime/RequestHandler.ts @@ -278,7 +278,7 @@ export class RequestHandler { } const operation = Object.keys(data)[0] const response = Object.values(data)[0] - const pathForGet = dataPath.filter((key) => key !== 'select' && key !== 'include') + const pathForGet = dataPathToGetPath(dataPath) const extractedResponse = deepGet(response, pathForGet) const deserializedResponse = operation === 'queryRaw' @@ -367,3 +367,19 @@ function convertValidationError(error: EngineValidationError): EngineValidationE return error } + +/** + * Converts a fluent-API dataPath into the path used to read the result out of + * the response. dataPath is a sequence of [selector, relationField] pairs where + * the selector is always 'select' or 'include'. The relation field names (the + * odd positions) form the path. Filtering by the literal values 'select' or + * 'include' would also drop a relation field that happens to be named that way, + * so the path is derived positionally instead. + */ +export function dataPathToGetPath(dataPath: string[]): string[] { + const getPath: string[] = [] + for (let index = 1; index < dataPath.length; index += 2) { + getPath.push(dataPath[index]) + } + return getPath +} diff --git a/packages/client/src/runtime/dataPathToGetPath.test.ts b/packages/client/src/runtime/dataPathToGetPath.test.ts new file mode 100644 index 000000000000..c21e3128b96b --- /dev/null +++ b/packages/client/src/runtime/dataPathToGetPath.test.ts @@ -0,0 +1,18 @@ +import { dataPathToGetPath } from './RequestHandler' + +describe('dataPathToGetPath', () => { + test('returns the relation field names from a fluent dataPath', () => { + expect(dataPathToGetPath(['select', 'posts'])).toEqual(['posts']) + expect(dataPathToGetPath(['select', 'posts', 'include', 'comments'])).toEqual(['posts', 'comments']) + }) + + test('keeps a relation field named "select" or "include"', () => { + expect(dataPathToGetPath(['select', 'select'])).toEqual(['select']) + expect(dataPathToGetPath(['select', 'include'])).toEqual(['include']) + expect(dataPathToGetPath(['select', 'posts', 'select', 'select'])).toEqual(['posts', 'select']) + }) + + test('returns an empty path for the root result', () => { + expect(dataPathToGetPath([])).toEqual([]) + }) +})