diff --git a/packages/ra-data-simple-rest/src/index.spec.ts b/packages/ra-data-simple-rest/src/index.spec.ts index f60eaddc710..0b145d79987 100644 --- a/packages/ra-data-simple-rest/src/index.spec.ts +++ b/packages/ra-data-simple-rest/src/index.spec.ts @@ -67,6 +67,28 @@ describe('Data Simple REST Client', () => { expect(result.total).toEqual(42); }); + it('should support embeds via meta', async () => { + const httpClient = jest.fn(() => + Promise.resolve({ + headers: new Headers({ + 'content-range': '0/4-8', + }), + }) + ); + const client = simpleClient('http://localhost:3000', httpClient); + + await client.getList('posts', { + filter: {}, + pagination: { page: 1, perPage: 10 }, + sort: { field: 'title', order: 'DESC' }, + meta: { embed: ['author'] }, + }); + + expect(httpClient).toHaveBeenCalledWith( + 'http://localhost:3000/posts?embed=%5B%22author%22%5D&filter=%7B%7D&range=%5B0%2C9%5D&sort=%5B%22title%22%2C%22DESC%22%5D', + { headers: { map: { range: 'posts=0-9' } } } + ); + }); }); describe('getOne', () => { it('should allow numeric id in path', async () => { @@ -91,6 +113,20 @@ describe('Data Simple REST Client', () => { expect.any(Object) ); }); + it('should support embeds via meta', async () => { + const httpClient = jest.fn().mockResolvedValue({ id: 'Post#123' }); + const client = simpleClient('http://localhost:3000', httpClient); + + await client.getOne('posts', { + id: 'Post#123', + meta: { embed: ['author'] }, + }); + + expect(httpClient).toHaveBeenCalledWith( + 'http://localhost:3000/posts/Post%23123?embed=%5B%22author%22%5D', + expect.any(Object) + ); + }); }); describe('update', () => { it('should escape id in path', async () => { diff --git a/packages/ra-data-simple-rest/src/index.ts b/packages/ra-data-simple-rest/src/index.ts index 92fd0548789..35a2289c32d 100644 --- a/packages/ra-data-simple-rest/src/index.ts +++ b/packages/ra-data-simple-rest/src/index.ts @@ -45,11 +45,19 @@ export default ( const rangeStart = (page - 1) * perPage; const rangeEnd = page * perPage - 1; - const query = { + const query: { + sort: string; + range: string; + filter: string; + embed?: string; + } = { sort: JSON.stringify([field, order]), range: JSON.stringify([rangeStart, rangeEnd]), filter: JSON.stringify(params.filter), }; + if (params.meta && params.meta.embed) { + query.embed = JSON.stringify(params.meta.embed); + } const url = `${apiUrl}/${resource}?${stringify(query)}`; const options = countHeader === 'Content-Range' @@ -82,17 +90,26 @@ export default ( }); }, - getOne: (resource, params) => - httpClient(`${apiUrl}/${resource}/${encodeURIComponent(params.id)}`, { - signal: params?.signal, - }).then(({ json }) => ({ - data: json, - })), + getOne: async (resource, params) => { + let query: string = ''; + if (params.meta && params.meta.embed) { + query = + '?' + stringify({ embed: JSON.stringify(params.meta.embed) }); + } + const { json } = await httpClient( + `${apiUrl}/${resource}/${encodeURIComponent(params.id)}${query}`, + { signal: params?.signal } + ); + return { data: json }; + }, getMany: (resource, params) => { - const query = { + const query: { filter: string; embed?: string } = { filter: JSON.stringify({ id: params.ids }), }; + if (params.meta && params.meta.embed) { + query.embed = JSON.stringify(params.meta.embed); + } const url = `${apiUrl}/${resource}?${stringify(query)}`; return httpClient(url, { signal: params?.signal }).then(({ json }) => ({ data: json, @@ -106,7 +123,12 @@ export default ( const rangeStart = (page - 1) * perPage; const rangeEnd = page * perPage - 1; - const query = { + const query: { + sort: string; + range: string; + filter: string; + embed?: string; + } = { sort: JSON.stringify([field, order]), range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]), filter: JSON.stringify({ @@ -114,6 +136,9 @@ export default ( [params.target]: params.id, }), }; + if (params.meta && params.meta.embed) { + query.embed = JSON.stringify(params.meta.embed); + } const url = `${apiUrl}/${resource}?${stringify(query)}`; const options = countHeader === 'Content-Range'