Skip to content

Commit 6540e3b

Browse files
authored
Merge pull request #10898 from marmelab/simple-rest-embed
Add support for embedded resources in ra-data-simple-rest
2 parents bbc9074 + bcedd93 commit 6540e3b

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

packages/ra-data-simple-rest/src/index.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,28 @@ describe('Data Simple REST Client', () => {
6767

6868
expect(result.total).toEqual(42);
6969
});
70+
it('should support embeds via meta', async () => {
71+
const httpClient = jest.fn(() =>
72+
Promise.resolve({
73+
headers: new Headers({
74+
'content-range': '0/4-8',
75+
}),
76+
})
77+
);
78+
const client = simpleClient('http://localhost:3000', httpClient);
79+
80+
await client.getList('posts', {
81+
filter: {},
82+
pagination: { page: 1, perPage: 10 },
83+
sort: { field: 'title', order: 'DESC' },
84+
meta: { embed: ['author'] },
85+
});
86+
87+
expect(httpClient).toHaveBeenCalledWith(
88+
'http://localhost:3000/posts?embed=%5B%22author%22%5D&filter=%7B%7D&range=%5B0%2C9%5D&sort=%5B%22title%22%2C%22DESC%22%5D',
89+
{ headers: { map: { range: 'posts=0-9' } } }
90+
);
91+
});
7092
});
7193
describe('getOne', () => {
7294
it('should allow numeric id in path', async () => {
@@ -91,6 +113,20 @@ describe('Data Simple REST Client', () => {
91113
expect.any(Object)
92114
);
93115
});
116+
it('should support embeds via meta', async () => {
117+
const httpClient = jest.fn().mockResolvedValue({ id: 'Post#123' });
118+
const client = simpleClient('http://localhost:3000', httpClient);
119+
120+
await client.getOne('posts', {
121+
id: 'Post#123',
122+
meta: { embed: ['author'] },
123+
});
124+
125+
expect(httpClient).toHaveBeenCalledWith(
126+
'http://localhost:3000/posts/Post%23123?embed=%5B%22author%22%5D',
127+
expect.any(Object)
128+
);
129+
});
94130
});
95131
describe('update', () => {
96132
it('should escape id in path', async () => {

packages/ra-data-simple-rest/src/index.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,19 @@ export default (
4545
const rangeStart = (page - 1) * perPage;
4646
const rangeEnd = page * perPage - 1;
4747

48-
const query = {
48+
const query: {
49+
sort: string;
50+
range: string;
51+
filter: string;
52+
embed?: string;
53+
} = {
4954
sort: JSON.stringify([field, order]),
5055
range: JSON.stringify([rangeStart, rangeEnd]),
5156
filter: JSON.stringify(params.filter),
5257
};
58+
if (params.meta && params.meta.embed) {
59+
query.embed = JSON.stringify(params.meta.embed);
60+
}
5361
const url = `${apiUrl}/${resource}?${stringify(query)}`;
5462
const options =
5563
countHeader === 'Content-Range'
@@ -82,17 +90,26 @@ export default (
8290
});
8391
},
8492

85-
getOne: (resource, params) =>
86-
httpClient(`${apiUrl}/${resource}/${encodeURIComponent(params.id)}`, {
87-
signal: params?.signal,
88-
}).then(({ json }) => ({
89-
data: json,
90-
})),
93+
getOne: async (resource, params) => {
94+
let query: string = '';
95+
if (params.meta && params.meta.embed) {
96+
query =
97+
'?' + stringify({ embed: JSON.stringify(params.meta.embed) });
98+
}
99+
const { json } = await httpClient(
100+
`${apiUrl}/${resource}/${encodeURIComponent(params.id)}${query}`,
101+
{ signal: params?.signal }
102+
);
103+
return { data: json };
104+
},
91105

92106
getMany: (resource, params) => {
93-
const query = {
107+
const query: { filter: string; embed?: string } = {
94108
filter: JSON.stringify({ id: params.ids }),
95109
};
110+
if (params.meta && params.meta.embed) {
111+
query.embed = JSON.stringify(params.meta.embed);
112+
}
96113
const url = `${apiUrl}/${resource}?${stringify(query)}`;
97114
return httpClient(url, { signal: params?.signal }).then(({ json }) => ({
98115
data: json,
@@ -106,14 +123,22 @@ export default (
106123
const rangeStart = (page - 1) * perPage;
107124
const rangeEnd = page * perPage - 1;
108125

109-
const query = {
126+
const query: {
127+
sort: string;
128+
range: string;
129+
filter: string;
130+
embed?: string;
131+
} = {
110132
sort: JSON.stringify([field, order]),
111133
range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
112134
filter: JSON.stringify({
113135
...params.filter,
114136
[params.target]: params.id,
115137
}),
116138
};
139+
if (params.meta && params.meta.embed) {
140+
query.embed = JSON.stringify(params.meta.embed);
141+
}
117142
const url = `${apiUrl}/${resource}?${stringify(query)}`;
118143
const options =
119144
countHeader === 'Content-Range'

0 commit comments

Comments
 (0)