@raphiniert/ra-data-postgrest 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +236 -224
- package/README.md +247 -232
- package/esm/index.d.ts +2 -1
- package/esm/index.js +16 -5
- package/esm/urlBuilder.d.ts +7 -1
- package/esm/urlBuilder.js +12 -3
- package/lib/index.d.ts +2 -1
- package/lib/index.js +16 -5
- package/lib/urlBuilder.d.ts +7 -1
- package/lib/urlBuilder.js +13 -4
- package/package.json +51 -50
- package/src/index.ts +422 -408
- package/src/urlBuilder.ts +320 -311
package/src/index.ts
CHANGED
|
@@ -1,408 +1,422 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DataProvider,
|
|
3
|
-
GetListParams,
|
|
4
|
-
GetOneParams,
|
|
5
|
-
GetManyParams,
|
|
6
|
-
GetManyReferenceParams,
|
|
7
|
-
UpdateParams,
|
|
8
|
-
UpdateManyParams,
|
|
9
|
-
CreateParams,
|
|
10
|
-
DeleteParams,
|
|
11
|
-
DeleteManyParams,
|
|
12
|
-
} from 'ra-core';
|
|
13
|
-
import {
|
|
14
|
-
PrimaryKey,
|
|
15
|
-
PostgRestOperator,
|
|
16
|
-
getPrimaryKey,
|
|
17
|
-
parseFilters,
|
|
18
|
-
getOrderBy,
|
|
19
|
-
dataWithVirtualId,
|
|
20
|
-
dataWithoutVirtualId,
|
|
21
|
-
removePrimaryKey,
|
|
22
|
-
getQuery,
|
|
23
|
-
encodeId,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* @
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* import
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
export const
|
|
79
|
-
|
|
80
|
-
export
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
) =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const {
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
})
|
|
1
|
+
import {
|
|
2
|
+
DataProvider,
|
|
3
|
+
GetListParams,
|
|
4
|
+
GetOneParams,
|
|
5
|
+
GetManyParams,
|
|
6
|
+
GetManyReferenceParams,
|
|
7
|
+
UpdateParams,
|
|
8
|
+
UpdateManyParams,
|
|
9
|
+
CreateParams,
|
|
10
|
+
DeleteParams,
|
|
11
|
+
DeleteManyParams,
|
|
12
|
+
} from 'ra-core';
|
|
13
|
+
import {
|
|
14
|
+
PrimaryKey,
|
|
15
|
+
PostgRestOperator,
|
|
16
|
+
getPrimaryKey,
|
|
17
|
+
parseFilters,
|
|
18
|
+
getOrderBy,
|
|
19
|
+
dataWithVirtualId,
|
|
20
|
+
dataWithoutVirtualId,
|
|
21
|
+
removePrimaryKey,
|
|
22
|
+
getQuery,
|
|
23
|
+
encodeId,
|
|
24
|
+
PostgRestSortOrder,
|
|
25
|
+
} from './urlBuilder';
|
|
26
|
+
import qs from 'qs';
|
|
27
|
+
import isEqual from 'lodash/isEqual';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Maps react-admin queries to a postgrest REST API
|
|
31
|
+
*
|
|
32
|
+
* This REST dialect uses postgrest syntax
|
|
33
|
+
*
|
|
34
|
+
* @see https://postgrest.org/en/stable/api.html#embedded-filters
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
*
|
|
38
|
+
* getList => GET http://my.api.url/posts?order=title.asc&offset=0&limit=24&filterField=eq.value
|
|
39
|
+
* getOne => GET http://my.api.url/posts?id=eq.123
|
|
40
|
+
* getMany => GET http://my.api.url/posts?id=in.(123,456,789)
|
|
41
|
+
* getManyReference => GET http://my.api.url/posts?author_id=eq.345
|
|
42
|
+
* create => POST http://my.api.url/posts
|
|
43
|
+
* update => PATCH http://my.api.url/posts?id=eq.123
|
|
44
|
+
* updateMany => PATCH http://my.api.url/posts?id=in.(123,456,789)
|
|
45
|
+
* delete => DELETE http://my.api.url/posts?id=eq.123
|
|
46
|
+
* deleteMany => DELETE http://my.api.url/posts?id=in.(123,456,789)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
*
|
|
50
|
+
* import * as React from 'react';
|
|
51
|
+
* import { Admin, Resource, fetchUtils } from 'react-admin';
|
|
52
|
+
* import postgrestRestProvider,
|
|
53
|
+
* { IDataProviderConfig,
|
|
54
|
+
* defaultPrimaryKeys,
|
|
55
|
+
* defaultSchema } from '@raphiniert/ra-data-postgrest';
|
|
56
|
+
*
|
|
57
|
+
* import { PostList } from './posts';
|
|
58
|
+
*
|
|
59
|
+
* const config: IDataProviderConfig = {
|
|
60
|
+
* apiUrl: 'http://path.to.my.api/',
|
|
61
|
+
* httpClient: fetchUtils.fetchJson,
|
|
62
|
+
* defaultListOp: 'eq',
|
|
63
|
+
* primaryKeys: defaultPrimaryKeys,
|
|
64
|
+
* schema: defaultSchema
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* const App = () => (
|
|
68
|
+
* <Admin dataProvider={postgrestRestProvider(config)}>
|
|
69
|
+
* <Resource name="posts" list={PostList} />
|
|
70
|
+
* </Admin>
|
|
71
|
+
* );
|
|
72
|
+
*
|
|
73
|
+
* export default App;
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
export type MetaOption = string | undefined;
|
|
77
|
+
|
|
78
|
+
export const defaultPrimaryKeys = new Map<string, PrimaryKey>();
|
|
79
|
+
|
|
80
|
+
export const defaultSchema = () => '';
|
|
81
|
+
|
|
82
|
+
export interface IDataProviderConfig {
|
|
83
|
+
apiUrl: string;
|
|
84
|
+
httpClient: (string, Options) => Promise<any>;
|
|
85
|
+
defaultListOp: PostgRestOperator;
|
|
86
|
+
sortOrder?: PostgRestSortOrder;
|
|
87
|
+
primaryKeys: Map<string, PrimaryKey>;
|
|
88
|
+
schema: () => string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const useCustomSchema = (
|
|
92
|
+
schema: () => string,
|
|
93
|
+
metaSchema: MetaOption,
|
|
94
|
+
method: string
|
|
95
|
+
) => {
|
|
96
|
+
let funcHeaderSchema = schema;
|
|
97
|
+
if (metaSchema !== undefined) {
|
|
98
|
+
funcHeaderSchema = () => metaSchema;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (funcHeaderSchema().length > 0) {
|
|
102
|
+
let schemaHeader = '';
|
|
103
|
+
if (['GET', 'HEAD'].includes(method)) {
|
|
104
|
+
schemaHeader = 'Accept-Profile';
|
|
105
|
+
} else if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(method)) {
|
|
106
|
+
schemaHeader = 'Content-Profile';
|
|
107
|
+
} else return {};
|
|
108
|
+
|
|
109
|
+
return { [schemaHeader]: funcHeaderSchema() };
|
|
110
|
+
} else return {};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default (config: IDataProviderConfig): DataProvider => ({
|
|
114
|
+
getList: (resource, params: Partial<GetListParams> = {}) => {
|
|
115
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
116
|
+
|
|
117
|
+
const { page, perPage } = params.pagination;
|
|
118
|
+
const { field, order } = params.sort || {};
|
|
119
|
+
const { filter, select } = parseFilters(params, config.defaultListOp);
|
|
120
|
+
const metaSchema = params.meta?.schema;
|
|
121
|
+
|
|
122
|
+
let query = {
|
|
123
|
+
offset: String((page - 1) * perPage),
|
|
124
|
+
limit: String(perPage),
|
|
125
|
+
// append filters
|
|
126
|
+
...filter,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
if (field) {
|
|
130
|
+
query.order = getOrderBy(field, order, primaryKey);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (select) {
|
|
134
|
+
query.select = select;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// add header that Content-Range is in returned header
|
|
138
|
+
const options = {
|
|
139
|
+
headers: new Headers({
|
|
140
|
+
Accept: 'application/json',
|
|
141
|
+
Prefer: 'count=exact',
|
|
142
|
+
...(params.meta?.headers || {}),
|
|
143
|
+
...useCustomSchema(config.schema, metaSchema, 'GET'),
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
148
|
+
|
|
149
|
+
return config.httpClient(url, options).then(({ headers, json }) => {
|
|
150
|
+
if (!headers.has('content-range')) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`The Content-Range header is missing in the HTTP Response. The postgREST data provider expects
|
|
153
|
+
responses for lists of resources to contain this header with the total number of results to build
|
|
154
|
+
the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
data: json.map(obj => dataWithVirtualId(obj, primaryKey)),
|
|
159
|
+
total: parseInt(
|
|
160
|
+
headers.get('content-range').split('/').pop(),
|
|
161
|
+
10
|
|
162
|
+
),
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
getOne: (resource, params: Partial<GetOneParams> = {}) => {
|
|
168
|
+
const { id, meta } = params;
|
|
169
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
170
|
+
|
|
171
|
+
const query = getQuery(primaryKey, id, resource, meta);
|
|
172
|
+
|
|
173
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
174
|
+
const metaSchema = params.meta?.schema;
|
|
175
|
+
|
|
176
|
+
return config
|
|
177
|
+
.httpClient(url, {
|
|
178
|
+
headers: new Headers({
|
|
179
|
+
accept: 'application/vnd.pgrst.object+json',
|
|
180
|
+
...(params.meta?.headers || {}),
|
|
181
|
+
...useCustomSchema(config.schema, metaSchema, 'GET'),
|
|
182
|
+
}),
|
|
183
|
+
})
|
|
184
|
+
.then(({ json }) => ({
|
|
185
|
+
data: dataWithVirtualId(json, primaryKey),
|
|
186
|
+
}));
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
getMany: (resource, params: Partial<GetManyParams> = {}) => {
|
|
190
|
+
const ids = params.ids;
|
|
191
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
192
|
+
|
|
193
|
+
const query = getQuery(primaryKey, ids, resource, params.meta);
|
|
194
|
+
|
|
195
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
196
|
+
const metaSchema = params.meta?.schema;
|
|
197
|
+
|
|
198
|
+
return config
|
|
199
|
+
.httpClient(url, {
|
|
200
|
+
headers: new Headers({
|
|
201
|
+
...useCustomSchema(config.schema, metaSchema, 'GET'),
|
|
202
|
+
}),
|
|
203
|
+
})
|
|
204
|
+
.then(({ json }) => ({
|
|
205
|
+
data: json.map(data => dataWithVirtualId(data, primaryKey)),
|
|
206
|
+
}));
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
getManyReference: (
|
|
210
|
+
resource,
|
|
211
|
+
params: Partial<GetManyReferenceParams> = {}
|
|
212
|
+
) => {
|
|
213
|
+
const { page, perPage } = params.pagination;
|
|
214
|
+
const { field, order } = params.sort;
|
|
215
|
+
|
|
216
|
+
const { filter, select } = parseFilters(params, config.defaultListOp);
|
|
217
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
218
|
+
|
|
219
|
+
const metaSchema = params.meta?.schema;
|
|
220
|
+
|
|
221
|
+
let query = params.target
|
|
222
|
+
? {
|
|
223
|
+
[params.target]: `eq.${params.id}`,
|
|
224
|
+
order: getOrderBy(field, order, primaryKey, config.sortOrder),
|
|
225
|
+
offset: String((page - 1) * perPage),
|
|
226
|
+
limit: String(perPage),
|
|
227
|
+
...filter,
|
|
228
|
+
}
|
|
229
|
+
: {
|
|
230
|
+
order: getOrderBy(field, order, primaryKey),
|
|
231
|
+
offset: String((page - 1) * perPage),
|
|
232
|
+
limit: String(perPage),
|
|
233
|
+
...filter,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
if (select) {
|
|
237
|
+
query.select = select;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// add header that Content-Range is in returned header
|
|
241
|
+
const options = {
|
|
242
|
+
headers: new Headers({
|
|
243
|
+
Accept: 'application/json',
|
|
244
|
+
Prefer: 'count=exact',
|
|
245
|
+
...(params.meta?.headers || {}),
|
|
246
|
+
...useCustomSchema(config.schema, metaSchema, 'GET'),
|
|
247
|
+
}),
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
251
|
+
|
|
252
|
+
return config.httpClient(url, options).then(({ headers, json }) => {
|
|
253
|
+
if (!headers.has('content-range')) {
|
|
254
|
+
throw new Error(
|
|
255
|
+
`The Content-Range header is missing in the HTTP Response. The postgREST data provider expects
|
|
256
|
+
responses for lists of resources to contain this header with the total number of results to build
|
|
257
|
+
the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?`
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
data: json.map(data => dataWithVirtualId(data, primaryKey)),
|
|
262
|
+
total: parseInt(
|
|
263
|
+
headers.get('content-range').split('/').pop(),
|
|
264
|
+
10
|
|
265
|
+
),
|
|
266
|
+
};
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
update: (resource, params: Partial<UpdateParams> = {}) => {
|
|
271
|
+
const { id, data, meta, previousData } = params;
|
|
272
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
273
|
+
const query = getQuery(primaryKey, id, resource, meta);
|
|
274
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
275
|
+
const changedData = getChanges(data, previousData);
|
|
276
|
+
const metaSchema = params.meta?.schema;
|
|
277
|
+
|
|
278
|
+
const body = JSON.stringify({
|
|
279
|
+
...dataWithoutVirtualId(
|
|
280
|
+
removePrimaryKey(changedData, primaryKey),
|
|
281
|
+
primaryKey
|
|
282
|
+
),
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
return config
|
|
286
|
+
.httpClient(url, {
|
|
287
|
+
method: 'PATCH',
|
|
288
|
+
headers: new Headers({
|
|
289
|
+
Accept: 'application/vnd.pgrst.object+json',
|
|
290
|
+
Prefer: 'return=representation',
|
|
291
|
+
'Content-Type': 'application/json',
|
|
292
|
+
...(params.meta?.headers || {}),
|
|
293
|
+
...useCustomSchema(config.schema, metaSchema, 'PATCH'),
|
|
294
|
+
}),
|
|
295
|
+
body,
|
|
296
|
+
})
|
|
297
|
+
.then(({ json }) => ({
|
|
298
|
+
data: dataWithVirtualId(json, primaryKey),
|
|
299
|
+
}));
|
|
300
|
+
},
|
|
301
|
+
|
|
302
|
+
updateMany: (resource, params: Partial<UpdateManyParams> = {}) => {
|
|
303
|
+
const { ids, meta, data } = params;
|
|
304
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
305
|
+
const query = getQuery(primaryKey, ids, resource, meta);
|
|
306
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
307
|
+
const body = JSON.stringify({
|
|
308
|
+
...dataWithoutVirtualId(
|
|
309
|
+
removePrimaryKey(data, primaryKey),
|
|
310
|
+
primaryKey
|
|
311
|
+
),
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const metaSchema = params.meta?.schema;
|
|
315
|
+
|
|
316
|
+
return config
|
|
317
|
+
.httpClient(url, {
|
|
318
|
+
method: 'PATCH',
|
|
319
|
+
headers: new Headers({
|
|
320
|
+
Prefer: 'return=representation',
|
|
321
|
+
'Content-Type': 'application/json',
|
|
322
|
+
...(params.meta?.headers || {}),
|
|
323
|
+
...useCustomSchema(config.schema, metaSchema, 'PATCH'),
|
|
324
|
+
}),
|
|
325
|
+
body,
|
|
326
|
+
})
|
|
327
|
+
.then(({ json }) => ({
|
|
328
|
+
data: json.map(data => encodeId(data, primaryKey)),
|
|
329
|
+
}));
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
create: (resource, params: Partial<CreateParams> = {}) => {
|
|
333
|
+
const { meta } = params;
|
|
334
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
335
|
+
const query = getQuery(primaryKey, undefined, resource, meta);
|
|
336
|
+
const queryStr = qs.stringify(query);
|
|
337
|
+
const url = `${config.apiUrl}/${resource}${
|
|
338
|
+
queryStr.length > 0 ? '?' : ''
|
|
339
|
+
}${queryStr}`;
|
|
340
|
+
const metaSchema = params.meta?.schema;
|
|
341
|
+
|
|
342
|
+
return config
|
|
343
|
+
.httpClient(url, {
|
|
344
|
+
method: 'POST',
|
|
345
|
+
headers: new Headers({
|
|
346
|
+
Accept: 'application/vnd.pgrst.object+json',
|
|
347
|
+
Prefer: 'return=representation',
|
|
348
|
+
'Content-Type': 'application/json',
|
|
349
|
+
...(params.meta?.headers || {}),
|
|
350
|
+
...useCustomSchema(config.schema, metaSchema, 'POST'),
|
|
351
|
+
}),
|
|
352
|
+
body: JSON.stringify(
|
|
353
|
+
dataWithoutVirtualId(params.data, primaryKey)
|
|
354
|
+
),
|
|
355
|
+
})
|
|
356
|
+
.then(({ json }) => ({
|
|
357
|
+
data: {
|
|
358
|
+
...json,
|
|
359
|
+
id: encodeId(json, primaryKey),
|
|
360
|
+
},
|
|
361
|
+
}));
|
|
362
|
+
},
|
|
363
|
+
|
|
364
|
+
delete: (resource, params: Partial<DeleteParams> = {}) => {
|
|
365
|
+
const { id, meta } = params;
|
|
366
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
367
|
+
|
|
368
|
+
const query = getQuery(primaryKey, id, resource, meta);
|
|
369
|
+
|
|
370
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
371
|
+
const metaSchema = params.meta?.schema;
|
|
372
|
+
|
|
373
|
+
return config
|
|
374
|
+
.httpClient(url, {
|
|
375
|
+
method: 'DELETE',
|
|
376
|
+
headers: new Headers({
|
|
377
|
+
Accept: 'application/vnd.pgrst.object+json',
|
|
378
|
+
Prefer: 'return=representation',
|
|
379
|
+
'Content-Type': 'application/json',
|
|
380
|
+
...(params.meta?.headers || {}),
|
|
381
|
+
...useCustomSchema(config.schema, metaSchema, 'DELETE'),
|
|
382
|
+
}),
|
|
383
|
+
})
|
|
384
|
+
.then(({ json }) => ({
|
|
385
|
+
data: dataWithVirtualId(json, primaryKey),
|
|
386
|
+
}));
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
deleteMany: (resource, params: Partial<DeleteManyParams> = {}) => {
|
|
390
|
+
const { ids, meta } = params;
|
|
391
|
+
const primaryKey = getPrimaryKey(resource, config.primaryKeys);
|
|
392
|
+
|
|
393
|
+
const query = getQuery(primaryKey, ids, resource, meta);
|
|
394
|
+
|
|
395
|
+
const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
|
|
396
|
+
const metaSchema = params.meta?.schema;
|
|
397
|
+
|
|
398
|
+
return config
|
|
399
|
+
.httpClient(url, {
|
|
400
|
+
method: 'DELETE',
|
|
401
|
+
headers: new Headers({
|
|
402
|
+
Prefer: 'return=representation',
|
|
403
|
+
'Content-Type': 'application/json',
|
|
404
|
+
...(params.meta?.headers || {}),
|
|
405
|
+
...useCustomSchema(config.schema, metaSchema, 'DELETE'),
|
|
406
|
+
}),
|
|
407
|
+
})
|
|
408
|
+
.then(({ json }) => ({
|
|
409
|
+
data: json.map(data => encodeId(data, primaryKey)),
|
|
410
|
+
}));
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const getChanges = (data: any, previousData: any) => {
|
|
415
|
+
const changes = Object.keys(data).reduce((changes, key) => {
|
|
416
|
+
if (!isEqual(data[key], previousData[key])) {
|
|
417
|
+
changes[key] = data[key];
|
|
418
|
+
}
|
|
419
|
+
return changes;
|
|
420
|
+
}, {});
|
|
421
|
+
return changes;
|
|
422
|
+
};
|