@raphiniert/ra-data-postgrest 2.0.0-alpha.3 → 2.0.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 CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  Find all notable changes of this project in this file.
4
4
 
5
+ ## v2.0.0 - 2023-12-29
6
+ ### Improvements
7
+ - updated dependencies
8
+
9
+ ### Fixes
10
+ - [#113](https://github.com/raphiniert-com/ra-data-postgrest/pull/113) remove {} value wrapping for cs/cd @[ruslantalpa](https://github.com/ruslantalpa)
11
+
12
+ ### Breaking changes
13
+ - the fix in this version might break old versions, as the {} are removed. Thus, one needs to manually add the {} for cs/cd.
14
+
15
+
16
+ ## v2.0.0-alpha.4 - 2023-10-23
17
+ ### Improvements
18
+ - updated dependencies
19
+
20
+ ### New feature
21
+ - [#100](https://github.com/raphiniert-com/ra-data-postgrest/pull/100) support "meta.columns" on all code paths (useful when the user does not have permissions on all the columns in which case doing select=* gives permissions errors) - @[ruslantalpa](https://github.com/ruslantalpa)
22
+
23
+ ### Fixes
24
+ - [#50](https://github.com/raphiniert-com/ra-data-postgrest/issues/50) and [#88](https://github.com/raphiniert-com/ra-data-postgrest/issues/88) solved by [#100](https://github.com/raphiniert-com/ra-data-postgrest/pull/100) including other fixes - @[ruslantalpa](https://github.com/ruslantalpa)
25
+
26
+
5
27
  ## v2.0.0-alpha.3 - 2023-06-16
6
28
  ### Improvements
7
29
  - updated dependencies
package/esm/index.js CHANGED
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { getPrimaryKey, parseFilters, getOrderBy, dataWithId, getQuery, getKeyData, encodeId, decodeId, isCompoundKey, } from './urlBuilder';
12
+ import { getPrimaryKey, parseFilters, getOrderBy, dataWithVirtualId, dataWithoutVirtualId, removePrimaryKey, getQuery, encodeId, } from './urlBuilder';
13
13
  import qs from 'qs';
14
14
  export var defaultPrimaryKeys = new Map();
15
15
  export var defaultSchema = function () { return ''; };
@@ -61,7 +61,7 @@ export default (function (config) { return ({
61
61
  throw new Error("The Content-Range header is missing in the HTTP Response. The postgREST data provider expects \n responses for lists of resources to contain this header with the total number of results to build \n the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?");
62
62
  }
63
63
  return {
64
- data: json.map(function (obj) { return dataWithId(obj, primaryKey); }),
64
+ data: json.map(function (obj) { return dataWithVirtualId(obj, primaryKey); }),
65
65
  total: parseInt(headers.get('content-range').split('/').pop(), 10),
66
66
  };
67
67
  });
@@ -81,7 +81,7 @@ export default (function (config) { return ({
81
81
  .then(function (_a) {
82
82
  var json = _a.json;
83
83
  return ({
84
- data: dataWithId(json, primaryKey),
84
+ data: dataWithVirtualId(json, primaryKey),
85
85
  });
86
86
  });
87
87
  },
@@ -100,7 +100,7 @@ export default (function (config) { return ({
100
100
  .then(function (_a) {
101
101
  var json = _a.json;
102
102
  return ({
103
- data: json.map(function (data) { return dataWithId(data, primaryKey); }),
103
+ data: json.map(function (data) { return dataWithVirtualId(data, primaryKey); }),
104
104
  });
105
105
  });
106
106
  },
@@ -129,7 +129,7 @@ export default (function (config) { return ({
129
129
  throw new Error("The Content-Range header is missing in the HTTP Response. The postgREST data provider expects \n responses for lists of resources to contain this header with the total number of results to build \n the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?");
130
130
  }
131
131
  return {
132
- data: json.map(function (data) { return dataWithId(data, primaryKey); }),
132
+ data: json.map(function (data) { return dataWithVirtualId(data, primaryKey); }),
133
133
  total: parseInt(headers.get('content-range').split('/').pop(), 10),
134
134
  };
135
135
  });
@@ -140,10 +140,9 @@ export default (function (config) { return ({
140
140
  var id = params.id, data = params.data, meta = params.meta;
141
141
  var primaryKey = getPrimaryKey(resource, config.primaryKeys);
142
142
  var query = getQuery(primaryKey, id, resource, meta);
143
- var primaryKeyData = getKeyData(primaryKey, data);
144
143
  var url = "".concat(config.apiUrl, "/").concat(resource, "?").concat(qs.stringify(query));
145
144
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
146
- var body = JSON.stringify(__assign(__assign({}, data), primaryKeyData));
145
+ var body = JSON.stringify(__assign({}, dataWithoutVirtualId(removePrimaryKey(data, primaryKey), primaryKey)));
147
146
  return config
148
147
  .httpClient(url, {
149
148
  method: 'PATCH',
@@ -152,29 +151,19 @@ export default (function (config) { return ({
152
151
  })
153
152
  .then(function (_a) {
154
153
  var json = _a.json;
155
- return ({ data: dataWithId(json, primaryKey) });
154
+ return ({
155
+ data: dataWithVirtualId(json, primaryKey),
156
+ });
156
157
  });
157
158
  },
158
159
  updateMany: function (resource, params) {
159
160
  var _a, _b;
160
161
  if (params === void 0) { params = {}; }
161
- var ids = params.ids;
162
+ var ids = params.ids, meta = params.meta, data = params.data;
162
163
  var primaryKey = getPrimaryKey(resource, config.primaryKeys);
163
- var body = JSON.stringify(params.ids.map(function (id) {
164
- var data = params.data;
165
- var primaryKeyParams = decodeId(id, primaryKey);
166
- var primaryKeyData = {};
167
- if (isCompoundKey(primaryKey)) {
168
- primaryKey.forEach(function (key, index) {
169
- primaryKeyData[key] = primaryKeyParams[index];
170
- });
171
- }
172
- else {
173
- primaryKeyData[primaryKey[0]] = primaryKeyParams[0];
174
- }
175
- return __assign(__assign({}, data), primaryKeyData);
176
- }));
177
- var url = "".concat(config.apiUrl, "/").concat(resource);
164
+ var query = getQuery(primaryKey, ids, resource, meta);
165
+ var url = "".concat(config.apiUrl, "/").concat(resource, "?").concat(qs.stringify(query));
166
+ var body = JSON.stringify(__assign({}, dataWithoutVirtualId(removePrimaryKey(data, primaryKey), primaryKey)));
178
167
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
179
168
  return config
180
169
  .httpClient(url, {
@@ -192,14 +181,17 @@ export default (function (config) { return ({
192
181
  create: function (resource, params) {
193
182
  var _a, _b;
194
183
  if (params === void 0) { params = {}; }
184
+ var meta = params.meta;
195
185
  var primaryKey = getPrimaryKey(resource, config.primaryKeys);
196
- var url = "".concat(config.apiUrl, "/").concat(resource);
186
+ var query = getQuery(primaryKey, undefined, resource, meta);
187
+ var queryStr = qs.stringify(query);
188
+ var url = "".concat(config.apiUrl, "/").concat(resource).concat(queryStr.length > 0 ? '?' : '').concat(queryStr);
197
189
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
198
190
  return config
199
191
  .httpClient(url, {
200
192
  method: 'POST',
201
193
  headers: new Headers(__assign(__assign({ Accept: 'application/vnd.pgrst.object+json', Prefer: 'return=representation', 'Content-Type': 'application/json' }, (((_b = params.meta) === null || _b === void 0 ? void 0 : _b.headers) || {})), useCustomSchema(config.schema, metaSchema, 'POST'))),
202
- body: JSON.stringify(params.data),
194
+ body: JSON.stringify(dataWithoutVirtualId(params.data, primaryKey)),
203
195
  })
204
196
  .then(function (_a) {
205
197
  var json = _a.json;
@@ -223,7 +215,9 @@ export default (function (config) { return ({
223
215
  })
224
216
  .then(function (_a) {
225
217
  var json = _a.json;
226
- return ({ data: dataWithId(json, primaryKey) });
218
+ return ({
219
+ data: dataWithVirtualId(json, primaryKey),
220
+ });
227
221
  });
228
222
  },
229
223
  deleteMany: function (resource, params) {
@@ -14,9 +14,9 @@ export type PrimaryKey = Array<string>;
14
14
  export declare const getPrimaryKey: (resource: string, primaryKeys: Map<string, PrimaryKey>) => PrimaryKey;
15
15
  export declare const decodeId: (id: Identifier, primaryKey: PrimaryKey) => string[] | number[];
16
16
  export declare const encodeId: (data: any, primaryKey: PrimaryKey) => Identifier;
17
- export declare const dataWithId: (data: any, primaryKey: PrimaryKey) => any;
18
- export declare const isCompoundKey: (primaryKey: PrimaryKey) => Boolean;
19
- export declare const getQuery: (primaryKey: PrimaryKey, ids: Identifier | Array<Identifier>, resource: string, meta?: any) => any;
20
- export declare const getKeyData: (primaryKey: PrimaryKey, data: object) => object;
17
+ export declare const removePrimaryKey: (data: any, primaryKey: PrimaryKey) => any;
18
+ export declare const dataWithVirtualId: (data: any, primaryKey: PrimaryKey) => any;
19
+ export declare const dataWithoutVirtualId: (data: any, primaryKey: PrimaryKey) => any;
20
+ export declare const getQuery: (primaryKey: PrimaryKey, ids: Identifier | Array<Identifier> | undefined, resource: string, meta?: any) => any;
21
21
  export declare const getOrderBy: (field: string, order: string, primaryKey: PrimaryKey) => string;
22
22
  export {};
package/esm/urlBuilder.js CHANGED
@@ -9,6 +9,17 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
12
23
  /**
13
24
  * List of all possible operators in PostgRest
14
25
  * (https://postgrest.org/en/stable/api.html#operators)
@@ -42,25 +53,53 @@ var postgrestOperators = [
42
53
  'or',
43
54
  'and',
44
55
  ];
56
+ var isObject = function (obj) {
57
+ return typeof obj === 'object' && !Array.isArray(obj) && obj !== null;
58
+ };
59
+ var resolveKeys = function (filter, keys) {
60
+ var result = filter[keys[0]];
61
+ for (var i = 1; i < keys.length; ++i) {
62
+ result = result[keys[i]];
63
+ }
64
+ return result;
65
+ };
45
66
  export var parseFilters = function (params, defaultListOp) {
46
67
  var filter = params.filter, _a = params.meta, meta = _a === void 0 ? {} : _a;
47
68
  var result = {};
48
69
  result.filter = {};
49
70
  Object.keys(filter).forEach(function (key) {
50
71
  // key: the name of the object key
72
+ var keyArray = [key];
73
+ var values;
74
+ // in case of a nested object selection in a text field
75
+ // RA returns object{ object } structure which is resolved here
76
+ // see issue https://github.com/raphiniert-com/ra-data-postgrest/issues/58
77
+ if (key.split('@')[0] !== '' && isObject(filter[key])) {
78
+ var innerVal = filter[key];
79
+ do {
80
+ var inner = resolveKeys(filter, keyArray);
81
+ var innerKey = Object.keys(inner)[0];
82
+ keyArray.push(innerKey);
83
+ innerVal = inner[innerKey];
84
+ } while (isObject(innerVal));
85
+ key = keyArray.join('.');
86
+ values = [innerVal];
87
+ }
88
+ else {
89
+ values = [filter[key]];
90
+ }
51
91
  var splitKey = key.split('@');
52
92
  var operation = splitKey.length == 2
53
93
  ? splitKey[1]
54
94
  : defaultListOp;
55
- var values;
56
95
  if (['like', 'ilike'].includes(operation)) {
57
96
  // we split the search term in words
58
- values = filter[key].trim().split(/\s+/);
97
+ values = resolveKeys(filter, keyArray).trim().split(/\s+/);
59
98
  }
60
99
  // CASE: Logical operator
61
100
  else if (['or', 'and'].includes(operation)) {
62
101
  // we extract each value entries and make it dot separated string.
63
- var subFilter = parseFilters({ filter: filter[key] }, defaultListOp).filter;
102
+ var subFilter = parseFilters({ filter: resolveKeys(filter, keyArray) }, defaultListOp).filter;
64
103
  // something like { "age@lt": 18 } and { "age@gt": 21 }
65
104
  var filterExpressions_1 = [];
66
105
  Object.entries(subFilter).forEach(function (_a) {
@@ -73,9 +112,6 @@ export var parseFilters = function (params, defaultListOp) {
73
112
  // finally we flatten all as single string and enclose with bracket.
74
113
  values = ["(".concat(filterExpressions_1.join(','), ")")];
75
114
  }
76
- else {
77
- values = [filter[key]];
78
- }
79
115
  values.forEach(function (value) {
80
116
  var op = (function () {
81
117
  // if operator is intentionally blank, rpc syntax
@@ -85,11 +121,9 @@ export var parseFilters = function (params, defaultListOp) {
85
121
  return "".concat(operation, ".*").concat(value, "*");
86
122
  if (['and', 'or'].includes(operation))
87
123
  return "".concat(value);
88
- if (['cs', 'cd'].includes(operation))
89
- return "".concat(operation, ".{").concat(value, "}");
90
124
  return "".concat(operation, ".").concat(value);
91
125
  })();
92
- // If resulting filter haven't contains the fieldname, then add it.
126
+ // If resulting filter doesn't contain the fieldname, then add it.
93
127
  if (result.filter[splitKey[0]] === undefined) {
94
128
  // first operator for the key,
95
129
  if (['and', 'or'].includes(operation)) {
@@ -141,15 +175,29 @@ export var encodeId = function (data, primaryKey) {
141
175
  return data[primaryKey[0]];
142
176
  }
143
177
  };
144
- export var dataWithId = function (data, primaryKey) {
145
- if (JSON.stringify(primaryKey) === JSON.stringify(['id'])) {
178
+ export var removePrimaryKey = function (data, primaryKey) {
179
+ var newData = __assign({}, data);
180
+ primaryKey.forEach(function (key) {
181
+ delete newData[key];
182
+ });
183
+ return newData;
184
+ };
185
+ export var dataWithVirtualId = function (data, primaryKey) {
186
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
146
187
  return data;
147
188
  }
148
189
  return Object.assign(data, {
149
190
  id: encodeId(data, primaryKey),
150
191
  });
151
192
  };
152
- export var isCompoundKey = function (primaryKey) {
193
+ export var dataWithoutVirtualId = function (data, primaryKey) {
194
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
195
+ return data;
196
+ }
197
+ var id = data.id, dataWithoutId = __rest(data, ["id"]);
198
+ return dataWithoutId;
199
+ };
200
+ var isCompoundKey = function (primaryKey) {
153
201
  return primaryKey.length > 1;
154
202
  };
155
203
  export var getQuery = function (primaryKey, ids, resource, meta) {
@@ -178,7 +226,7 @@ export var getQuery = function (primaryKey, ids, resource, meta) {
178
226
  _a);
179
227
  }
180
228
  }
181
- else {
229
+ else if (ids) {
182
230
  // if ids is one Identifier
183
231
  var id = ids.toString();
184
232
  var primaryKeyParams_1 = decodeId(id, primaryKey);
@@ -210,18 +258,6 @@ export var getQuery = function (primaryKey, ids, resource, meta) {
210
258
  }
211
259
  return result;
212
260
  };
213
- export var getKeyData = function (primaryKey, data) {
214
- var _a;
215
- if (isCompoundKey(primaryKey)) {
216
- return primaryKey.reduce(function (keyData, key) {
217
- var _a;
218
- return (__assign(__assign({}, keyData), (_a = {}, _a[key] = data[key], _a)));
219
- }, {});
220
- }
221
- else {
222
- return _a = {}, _a[primaryKey[0]] = data[primaryKey[0]], _a;
223
- }
224
- };
225
261
  export var getOrderBy = function (field, order, primaryKey) {
226
262
  if (field == 'id') {
227
263
  return primaryKey.map(function (key) { return "".concat(key, ".").concat(order.toLowerCase()); }).join(',');
package/lib/index.js CHANGED
@@ -68,7 +68,7 @@ exports.default = (function (config) { return ({
68
68
  throw new Error("The Content-Range header is missing in the HTTP Response. The postgREST data provider expects \n responses for lists of resources to contain this header with the total number of results to build \n the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?");
69
69
  }
70
70
  return {
71
- data: json.map(function (obj) { return (0, urlBuilder_1.dataWithId)(obj, primaryKey); }),
71
+ data: json.map(function (obj) { return (0, urlBuilder_1.dataWithVirtualId)(obj, primaryKey); }),
72
72
  total: parseInt(headers.get('content-range').split('/').pop(), 10),
73
73
  };
74
74
  });
@@ -88,7 +88,7 @@ exports.default = (function (config) { return ({
88
88
  .then(function (_a) {
89
89
  var json = _a.json;
90
90
  return ({
91
- data: (0, urlBuilder_1.dataWithId)(json, primaryKey),
91
+ data: (0, urlBuilder_1.dataWithVirtualId)(json, primaryKey),
92
92
  });
93
93
  });
94
94
  },
@@ -107,7 +107,7 @@ exports.default = (function (config) { return ({
107
107
  .then(function (_a) {
108
108
  var json = _a.json;
109
109
  return ({
110
- data: json.map(function (data) { return (0, urlBuilder_1.dataWithId)(data, primaryKey); }),
110
+ data: json.map(function (data) { return (0, urlBuilder_1.dataWithVirtualId)(data, primaryKey); }),
111
111
  });
112
112
  });
113
113
  },
@@ -136,7 +136,7 @@ exports.default = (function (config) { return ({
136
136
  throw new Error("The Content-Range header is missing in the HTTP Response. The postgREST data provider expects \n responses for lists of resources to contain this header with the total number of results to build \n the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?");
137
137
  }
138
138
  return {
139
- data: json.map(function (data) { return (0, urlBuilder_1.dataWithId)(data, primaryKey); }),
139
+ data: json.map(function (data) { return (0, urlBuilder_1.dataWithVirtualId)(data, primaryKey); }),
140
140
  total: parseInt(headers.get('content-range').split('/').pop(), 10),
141
141
  };
142
142
  });
@@ -147,10 +147,9 @@ exports.default = (function (config) { return ({
147
147
  var id = params.id, data = params.data, meta = params.meta;
148
148
  var primaryKey = (0, urlBuilder_1.getPrimaryKey)(resource, config.primaryKeys);
149
149
  var query = (0, urlBuilder_1.getQuery)(primaryKey, id, resource, meta);
150
- var primaryKeyData = (0, urlBuilder_1.getKeyData)(primaryKey, data);
151
150
  var url = "".concat(config.apiUrl, "/").concat(resource, "?").concat(qs_1.default.stringify(query));
152
151
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
153
- var body = JSON.stringify(__assign(__assign({}, data), primaryKeyData));
152
+ var body = JSON.stringify(__assign({}, (0, urlBuilder_1.dataWithoutVirtualId)((0, urlBuilder_1.removePrimaryKey)(data, primaryKey), primaryKey)));
154
153
  return config
155
154
  .httpClient(url, {
156
155
  method: 'PATCH',
@@ -159,29 +158,19 @@ exports.default = (function (config) { return ({
159
158
  })
160
159
  .then(function (_a) {
161
160
  var json = _a.json;
162
- return ({ data: (0, urlBuilder_1.dataWithId)(json, primaryKey) });
161
+ return ({
162
+ data: (0, urlBuilder_1.dataWithVirtualId)(json, primaryKey),
163
+ });
163
164
  });
164
165
  },
165
166
  updateMany: function (resource, params) {
166
167
  var _a, _b;
167
168
  if (params === void 0) { params = {}; }
168
- var ids = params.ids;
169
+ var ids = params.ids, meta = params.meta, data = params.data;
169
170
  var primaryKey = (0, urlBuilder_1.getPrimaryKey)(resource, config.primaryKeys);
170
- var body = JSON.stringify(params.ids.map(function (id) {
171
- var data = params.data;
172
- var primaryKeyParams = (0, urlBuilder_1.decodeId)(id, primaryKey);
173
- var primaryKeyData = {};
174
- if ((0, urlBuilder_1.isCompoundKey)(primaryKey)) {
175
- primaryKey.forEach(function (key, index) {
176
- primaryKeyData[key] = primaryKeyParams[index];
177
- });
178
- }
179
- else {
180
- primaryKeyData[primaryKey[0]] = primaryKeyParams[0];
181
- }
182
- return __assign(__assign({}, data), primaryKeyData);
183
- }));
184
- var url = "".concat(config.apiUrl, "/").concat(resource);
171
+ var query = (0, urlBuilder_1.getQuery)(primaryKey, ids, resource, meta);
172
+ var url = "".concat(config.apiUrl, "/").concat(resource, "?").concat(qs_1.default.stringify(query));
173
+ var body = JSON.stringify(__assign({}, (0, urlBuilder_1.dataWithoutVirtualId)((0, urlBuilder_1.removePrimaryKey)(data, primaryKey), primaryKey)));
185
174
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
186
175
  return config
187
176
  .httpClient(url, {
@@ -199,14 +188,17 @@ exports.default = (function (config) { return ({
199
188
  create: function (resource, params) {
200
189
  var _a, _b;
201
190
  if (params === void 0) { params = {}; }
191
+ var meta = params.meta;
202
192
  var primaryKey = (0, urlBuilder_1.getPrimaryKey)(resource, config.primaryKeys);
203
- var url = "".concat(config.apiUrl, "/").concat(resource);
193
+ var query = (0, urlBuilder_1.getQuery)(primaryKey, undefined, resource, meta);
194
+ var queryStr = qs_1.default.stringify(query);
195
+ var url = "".concat(config.apiUrl, "/").concat(resource).concat(queryStr.length > 0 ? '?' : '').concat(queryStr);
204
196
  var metaSchema = (_a = params.meta) === null || _a === void 0 ? void 0 : _a.schema;
205
197
  return config
206
198
  .httpClient(url, {
207
199
  method: 'POST',
208
200
  headers: new Headers(__assign(__assign({ Accept: 'application/vnd.pgrst.object+json', Prefer: 'return=representation', 'Content-Type': 'application/json' }, (((_b = params.meta) === null || _b === void 0 ? void 0 : _b.headers) || {})), useCustomSchema(config.schema, metaSchema, 'POST'))),
209
- body: JSON.stringify(params.data),
201
+ body: JSON.stringify((0, urlBuilder_1.dataWithoutVirtualId)(params.data, primaryKey)),
210
202
  })
211
203
  .then(function (_a) {
212
204
  var json = _a.json;
@@ -230,7 +222,9 @@ exports.default = (function (config) { return ({
230
222
  })
231
223
  .then(function (_a) {
232
224
  var json = _a.json;
233
- return ({ data: (0, urlBuilder_1.dataWithId)(json, primaryKey) });
225
+ return ({
226
+ data: (0, urlBuilder_1.dataWithVirtualId)(json, primaryKey),
227
+ });
234
228
  });
235
229
  },
236
230
  deleteMany: function (resource, params) {
@@ -14,9 +14,9 @@ export type PrimaryKey = Array<string>;
14
14
  export declare const getPrimaryKey: (resource: string, primaryKeys: Map<string, PrimaryKey>) => PrimaryKey;
15
15
  export declare const decodeId: (id: Identifier, primaryKey: PrimaryKey) => string[] | number[];
16
16
  export declare const encodeId: (data: any, primaryKey: PrimaryKey) => Identifier;
17
- export declare const dataWithId: (data: any, primaryKey: PrimaryKey) => any;
18
- export declare const isCompoundKey: (primaryKey: PrimaryKey) => Boolean;
19
- export declare const getQuery: (primaryKey: PrimaryKey, ids: Identifier | Array<Identifier>, resource: string, meta?: any) => any;
20
- export declare const getKeyData: (primaryKey: PrimaryKey, data: object) => object;
17
+ export declare const removePrimaryKey: (data: any, primaryKey: PrimaryKey) => any;
18
+ export declare const dataWithVirtualId: (data: any, primaryKey: PrimaryKey) => any;
19
+ export declare const dataWithoutVirtualId: (data: any, primaryKey: PrimaryKey) => any;
20
+ export declare const getQuery: (primaryKey: PrimaryKey, ids: Identifier | Array<Identifier> | undefined, resource: string, meta?: any) => any;
21
21
  export declare const getOrderBy: (field: string, order: string, primaryKey: PrimaryKey) => string;
22
22
  export {};
package/lib/urlBuilder.js CHANGED
@@ -10,8 +10,19 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
+ var __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
13
24
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.getOrderBy = exports.getKeyData = exports.getQuery = exports.isCompoundKey = exports.dataWithId = exports.encodeId = exports.decodeId = exports.getPrimaryKey = exports.parseFilters = void 0;
25
+ exports.getOrderBy = exports.getQuery = exports.dataWithoutVirtualId = exports.dataWithVirtualId = exports.removePrimaryKey = exports.encodeId = exports.decodeId = exports.getPrimaryKey = exports.parseFilters = void 0;
15
26
  /**
16
27
  * List of all possible operators in PostgRest
17
28
  * (https://postgrest.org/en/stable/api.html#operators)
@@ -45,25 +56,53 @@ var postgrestOperators = [
45
56
  'or',
46
57
  'and',
47
58
  ];
59
+ var isObject = function (obj) {
60
+ return typeof obj === 'object' && !Array.isArray(obj) && obj !== null;
61
+ };
62
+ var resolveKeys = function (filter, keys) {
63
+ var result = filter[keys[0]];
64
+ for (var i = 1; i < keys.length; ++i) {
65
+ result = result[keys[i]];
66
+ }
67
+ return result;
68
+ };
48
69
  var parseFilters = function (params, defaultListOp) {
49
70
  var filter = params.filter, _a = params.meta, meta = _a === void 0 ? {} : _a;
50
71
  var result = {};
51
72
  result.filter = {};
52
73
  Object.keys(filter).forEach(function (key) {
53
74
  // key: the name of the object key
75
+ var keyArray = [key];
76
+ var values;
77
+ // in case of a nested object selection in a text field
78
+ // RA returns object{ object } structure which is resolved here
79
+ // see issue https://github.com/raphiniert-com/ra-data-postgrest/issues/58
80
+ if (key.split('@')[0] !== '' && isObject(filter[key])) {
81
+ var innerVal = filter[key];
82
+ do {
83
+ var inner = resolveKeys(filter, keyArray);
84
+ var innerKey = Object.keys(inner)[0];
85
+ keyArray.push(innerKey);
86
+ innerVal = inner[innerKey];
87
+ } while (isObject(innerVal));
88
+ key = keyArray.join('.');
89
+ values = [innerVal];
90
+ }
91
+ else {
92
+ values = [filter[key]];
93
+ }
54
94
  var splitKey = key.split('@');
55
95
  var operation = splitKey.length == 2
56
96
  ? splitKey[1]
57
97
  : defaultListOp;
58
- var values;
59
98
  if (['like', 'ilike'].includes(operation)) {
60
99
  // we split the search term in words
61
- values = filter[key].trim().split(/\s+/);
100
+ values = resolveKeys(filter, keyArray).trim().split(/\s+/);
62
101
  }
63
102
  // CASE: Logical operator
64
103
  else if (['or', 'and'].includes(operation)) {
65
104
  // we extract each value entries and make it dot separated string.
66
- var subFilter = (0, exports.parseFilters)({ filter: filter[key] }, defaultListOp).filter;
105
+ var subFilter = (0, exports.parseFilters)({ filter: resolveKeys(filter, keyArray) }, defaultListOp).filter;
67
106
  // something like { "age@lt": 18 } and { "age@gt": 21 }
68
107
  var filterExpressions_1 = [];
69
108
  Object.entries(subFilter).forEach(function (_a) {
@@ -76,9 +115,6 @@ var parseFilters = function (params, defaultListOp) {
76
115
  // finally we flatten all as single string and enclose with bracket.
77
116
  values = ["(".concat(filterExpressions_1.join(','), ")")];
78
117
  }
79
- else {
80
- values = [filter[key]];
81
- }
82
118
  values.forEach(function (value) {
83
119
  var op = (function () {
84
120
  // if operator is intentionally blank, rpc syntax
@@ -88,11 +124,9 @@ var parseFilters = function (params, defaultListOp) {
88
124
  return "".concat(operation, ".*").concat(value, "*");
89
125
  if (['and', 'or'].includes(operation))
90
126
  return "".concat(value);
91
- if (['cs', 'cd'].includes(operation))
92
- return "".concat(operation, ".{").concat(value, "}");
93
127
  return "".concat(operation, ".").concat(value);
94
128
  })();
95
- // If resulting filter haven't contains the fieldname, then add it.
129
+ // If resulting filter doesn't contain the fieldname, then add it.
96
130
  if (result.filter[splitKey[0]] === undefined) {
97
131
  // first operator for the key,
98
132
  if (['and', 'or'].includes(operation)) {
@@ -131,7 +165,7 @@ var getPrimaryKey = function (resource, primaryKeys) {
131
165
  };
132
166
  exports.getPrimaryKey = getPrimaryKey;
133
167
  var decodeId = function (id, primaryKey) {
134
- if ((0, exports.isCompoundKey)(primaryKey)) {
168
+ if (isCompoundKey(primaryKey)) {
135
169
  return JSON.parse(id.toString());
136
170
  }
137
171
  else {
@@ -140,7 +174,7 @@ var decodeId = function (id, primaryKey) {
140
174
  };
141
175
  exports.decodeId = decodeId;
142
176
  var encodeId = function (data, primaryKey) {
143
- if ((0, exports.isCompoundKey)(primaryKey)) {
177
+ if (isCompoundKey(primaryKey)) {
144
178
  return JSON.stringify(primaryKey.map(function (key) { return data[key]; }));
145
179
  }
146
180
  else {
@@ -148,19 +182,34 @@ var encodeId = function (data, primaryKey) {
148
182
  }
149
183
  };
150
184
  exports.encodeId = encodeId;
151
- var dataWithId = function (data, primaryKey) {
152
- if (JSON.stringify(primaryKey) === JSON.stringify(['id'])) {
185
+ var removePrimaryKey = function (data, primaryKey) {
186
+ var newData = __assign({}, data);
187
+ primaryKey.forEach(function (key) {
188
+ delete newData[key];
189
+ });
190
+ return newData;
191
+ };
192
+ exports.removePrimaryKey = removePrimaryKey;
193
+ var dataWithVirtualId = function (data, primaryKey) {
194
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
153
195
  return data;
154
196
  }
155
197
  return Object.assign(data, {
156
198
  id: (0, exports.encodeId)(data, primaryKey),
157
199
  });
158
200
  };
159
- exports.dataWithId = dataWithId;
201
+ exports.dataWithVirtualId = dataWithVirtualId;
202
+ var dataWithoutVirtualId = function (data, primaryKey) {
203
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
204
+ return data;
205
+ }
206
+ var id = data.id, dataWithoutId = __rest(data, ["id"]);
207
+ return dataWithoutId;
208
+ };
209
+ exports.dataWithoutVirtualId = dataWithoutVirtualId;
160
210
  var isCompoundKey = function (primaryKey) {
161
211
  return primaryKey.length > 1;
162
212
  };
163
- exports.isCompoundKey = isCompoundKey;
164
213
  var getQuery = function (primaryKey, ids, resource, meta) {
165
214
  var _a, _b;
166
215
  if (meta === void 0) { meta = null; }
@@ -171,7 +220,7 @@ var getQuery = function (primaryKey, ids, resource, meta) {
171
220
  console.error("PostgREST's rpc endpoints are not intended to be handled as views. Therefore, no query generation for multiple key values implemented!");
172
221
  return;
173
222
  }
174
- if ((0, exports.isCompoundKey)(primaryKey)) {
223
+ if (isCompoundKey(primaryKey)) {
175
224
  result = {
176
225
  or: "(".concat(ids.map(function (id) {
177
226
  var primaryKeyParams = (0, exports.decodeId)(id, primaryKey);
@@ -187,11 +236,11 @@ var getQuery = function (primaryKey, ids, resource, meta) {
187
236
  _a);
188
237
  }
189
238
  }
190
- else {
239
+ else if (ids) {
191
240
  // if ids is one Identifier
192
241
  var id = ids.toString();
193
242
  var primaryKeyParams_1 = (0, exports.decodeId)(id, primaryKey);
194
- if ((0, exports.isCompoundKey)(primaryKey)) {
243
+ if (isCompoundKey(primaryKey)) {
195
244
  if (resource.startsWith('rpc/')) {
196
245
  result = {};
197
246
  primaryKey.map(function (key, i) {
@@ -220,19 +269,6 @@ var getQuery = function (primaryKey, ids, resource, meta) {
220
269
  return result;
221
270
  };
222
271
  exports.getQuery = getQuery;
223
- var getKeyData = function (primaryKey, data) {
224
- var _a;
225
- if ((0, exports.isCompoundKey)(primaryKey)) {
226
- return primaryKey.reduce(function (keyData, key) {
227
- var _a;
228
- return (__assign(__assign({}, keyData), (_a = {}, _a[key] = data[key], _a)));
229
- }, {});
230
- }
231
- else {
232
- return _a = {}, _a[primaryKey[0]] = data[primaryKey[0]], _a;
233
- }
234
- };
235
- exports.getKeyData = getKeyData;
236
272
  var getOrderBy = function (field, order, primaryKey) {
237
273
  if (field == 'id') {
238
274
  return primaryKey.map(function (key) { return "".concat(key, ".").concat(order.toLowerCase()); }).join(',');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raphiniert/ra-data-postgrest",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0",
4
4
  "description": "postgREST data provider for react-admin",
5
5
  "main": "lib/index.js",
6
6
  "module": "esm/index.js",
@@ -12,7 +12,6 @@
12
12
  "src"
13
13
  ],
14
14
  "authors": [
15
- "François Zaninotto",
16
15
  "Raphael Scheible"
17
16
  ],
18
17
  "repository": "raphiniert-com/ra-data-postgrest",
@@ -30,17 +29,17 @@
30
29
  "prettier": "prettier --config ./.prettierrc.js --write --list-different \"src/**/*.{js,json,ts,tsx,css,md}\""
31
30
  },
32
31
  "devDependencies": {
33
- "@types/jest": "^28.1.4",
34
- "@types/qs": "^6.9.7",
32
+ "@types/jest": "^29.5.11",
33
+ "@types/qs": "^6.9.11",
35
34
  "cross-env": "^7.0.3",
36
- "eslint-config-prettier": "^8.8.0",
37
- "eslint-plugin-prettier": "^4.2.1",
35
+ "eslint-config-prettier": "^9.1.0",
36
+ "eslint-plugin-prettier": "^5.0.1",
38
37
  "install-peers-cli": "^2.2.0",
39
- "jest": "^28.1.2",
40
- "prettier": "~2.8.8",
38
+ "jest": "^29.7.0",
39
+ "prettier": "^3.1.1",
41
40
  "rimraf": "^5.0.0",
42
- "ts-jest": "^28.0.5",
43
- "typescript": "^5.0.4"
41
+ "ts-jest": "^29.1.1",
42
+ "typescript": "^5.3.3"
44
43
  },
45
44
  "peerDependencies": {
46
45
  "ra-core": "^4.1.0"
package/src/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import {
2
- fetchUtils,
3
2
  DataProvider,
4
3
  GetListParams,
5
4
  GetOneParams,
@@ -17,12 +16,11 @@ import {
17
16
  getPrimaryKey,
18
17
  parseFilters,
19
18
  getOrderBy,
20
- dataWithId,
19
+ dataWithVirtualId,
20
+ dataWithoutVirtualId,
21
+ removePrimaryKey,
21
22
  getQuery,
22
- getKeyData,
23
23
  encodeId,
24
- decodeId,
25
- isCompoundKey,
26
24
  } from './urlBuilder';
27
25
  import qs from 'qs';
28
26
 
@@ -154,7 +152,7 @@ export default (config: IDataProviderConfig): DataProvider => ({
154
152
  );
155
153
  }
156
154
  return {
157
- data: json.map(obj => dataWithId(obj, primaryKey)),
155
+ data: json.map(obj => dataWithVirtualId(obj, primaryKey)),
158
156
  total: parseInt(
159
157
  headers.get('content-range').split('/').pop(),
160
158
  10
@@ -181,7 +179,7 @@ export default (config: IDataProviderConfig): DataProvider => ({
181
179
  }),
182
180
  })
183
181
  .then(({ json }) => ({
184
- data: dataWithId(json, primaryKey),
182
+ data: dataWithVirtualId(json, primaryKey),
185
183
  }));
186
184
  },
187
185
 
@@ -201,7 +199,7 @@ export default (config: IDataProviderConfig): DataProvider => ({
201
199
  }),
202
200
  })
203
201
  .then(({ json }) => ({
204
- data: json.map(data => dataWithId(data, primaryKey)),
202
+ data: json.map(data => dataWithVirtualId(data, primaryKey)),
205
203
  }));
206
204
  },
207
205
 
@@ -257,7 +255,7 @@ export default (config: IDataProviderConfig): DataProvider => ({
257
255
  );
258
256
  }
259
257
  return {
260
- data: json.map(data => dataWithId(data, primaryKey)),
258
+ data: json.map(data => dataWithVirtualId(data, primaryKey)),
261
259
  total: parseInt(
262
260
  headers.get('content-range').split('/').pop(),
263
261
  10
@@ -269,17 +267,15 @@ export default (config: IDataProviderConfig): DataProvider => ({
269
267
  update: (resource, params: Partial<UpdateParams> = {}) => {
270
268
  const { id, data, meta } = params;
271
269
  const primaryKey = getPrimaryKey(resource, config.primaryKeys);
272
-
273
270
  const query = getQuery(primaryKey, id, resource, meta);
274
-
275
- const primaryKeyData = getKeyData(primaryKey, data);
276
-
277
271
  const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
278
272
  const metaSchema = params.meta?.schema;
279
273
 
280
274
  const body = JSON.stringify({
281
- ...data,
282
- ...primaryKeyData,
275
+ ...dataWithoutVirtualId(
276
+ removePrimaryKey(data, primaryKey),
277
+ primaryKey
278
+ ),
283
279
  });
284
280
 
285
281
  return config
@@ -294,35 +290,23 @@ export default (config: IDataProviderConfig): DataProvider => ({
294
290
  }),
295
291
  body,
296
292
  })
297
- .then(({ json }) => ({ data: dataWithId(json, primaryKey) }));
293
+ .then(({ json }) => ({
294
+ data: dataWithVirtualId(json, primaryKey),
295
+ }));
298
296
  },
299
297
 
300
298
  updateMany: (resource, params: Partial<UpdateManyParams> = {}) => {
301
- const ids = params.ids;
299
+ const { ids, meta, data } = params;
302
300
  const primaryKey = getPrimaryKey(resource, config.primaryKeys);
301
+ const query = getQuery(primaryKey, ids, resource, meta);
302
+ const url = `${config.apiUrl}/${resource}?${qs.stringify(query)}`;
303
+ const body = JSON.stringify({
304
+ ...dataWithoutVirtualId(
305
+ removePrimaryKey(data, primaryKey),
306
+ primaryKey
307
+ ),
308
+ });
303
309
 
304
- const body = JSON.stringify(
305
- params.ids.map(id => {
306
- const { data } = params;
307
- const primaryKeyParams = decodeId(id, primaryKey);
308
-
309
- const primaryKeyData = {};
310
- if (isCompoundKey(primaryKey)) {
311
- primaryKey.forEach((key, index) => {
312
- primaryKeyData[key] = primaryKeyParams[index];
313
- });
314
- } else {
315
- primaryKeyData[primaryKey[0]] = primaryKeyParams[0];
316
- }
317
-
318
- return {
319
- ...data,
320
- ...primaryKeyData,
321
- };
322
- })
323
- );
324
-
325
- const url = `${config.apiUrl}/${resource}`;
326
310
  const metaSchema = params.meta?.schema;
327
311
 
328
312
  return config
@@ -342,8 +326,13 @@ export default (config: IDataProviderConfig): DataProvider => ({
342
326
  },
343
327
 
344
328
  create: (resource, params: Partial<CreateParams> = {}) => {
329
+ const { meta } = params;
345
330
  const primaryKey = getPrimaryKey(resource, config.primaryKeys);
346
- const url = `${config.apiUrl}/${resource}`;
331
+ const query = getQuery(primaryKey, undefined, resource, meta);
332
+ const queryStr = qs.stringify(query);
333
+ const url = `${config.apiUrl}/${resource}${
334
+ queryStr.length > 0 ? '?' : ''
335
+ }${queryStr}`;
347
336
  const metaSchema = params.meta?.schema;
348
337
 
349
338
  return config
@@ -356,7 +345,9 @@ export default (config: IDataProviderConfig): DataProvider => ({
356
345
  ...(params.meta?.headers || {}),
357
346
  ...useCustomSchema(config.schema, metaSchema, 'POST'),
358
347
  }),
359
- body: JSON.stringify(params.data),
348
+ body: JSON.stringify(
349
+ dataWithoutVirtualId(params.data, primaryKey)
350
+ ),
360
351
  })
361
352
  .then(({ json }) => ({
362
353
  data: {
@@ -386,7 +377,9 @@ export default (config: IDataProviderConfig): DataProvider => ({
386
377
  ...useCustomSchema(config.schema, metaSchema, 'DELETE'),
387
378
  }),
388
379
  })
389
- .then(({ json }) => ({ data: dataWithId(json, primaryKey) }));
380
+ .then(({ json }) => ({
381
+ data: dataWithVirtualId(json, primaryKey),
382
+ }));
390
383
  },
391
384
 
392
385
  deleteMany: (resource, params: Partial<DeleteManyParams> = {}) => {
package/src/urlBuilder.ts CHANGED
@@ -49,6 +49,18 @@ type ParsedFiltersResult = {
49
49
  select: any;
50
50
  };
51
51
 
52
+ const isObject = obj =>
53
+ typeof obj === 'object' && !Array.isArray(obj) && obj !== null;
54
+
55
+ const resolveKeys = (filter: any, keys: Array<any>) => {
56
+ let result = filter[keys[0]];
57
+ for (let i = 1; i < keys.length; ++i) {
58
+ result = result[keys[i]];
59
+ }
60
+
61
+ return result;
62
+ };
63
+
52
64
  export type PostgRestOperator = (typeof postgrestOperators)[number];
53
65
 
54
66
  export const parseFilters = (
@@ -62,22 +74,44 @@ export const parseFilters = (
62
74
  Object.keys(filter).forEach(function (key) {
63
75
  // key: the name of the object key
64
76
 
77
+ let keyArray = [key];
78
+ let values: Array<string>;
79
+
80
+ // in case of a nested object selection in a text field
81
+ // RA returns object{ object } structure which is resolved here
82
+ // see issue https://github.com/raphiniert-com/ra-data-postgrest/issues/58
83
+ if (key.split('@')[0] !== '' && isObject(filter[key])) {
84
+ let innerVal = filter[key];
85
+
86
+ do {
87
+ const inner = resolveKeys(filter, keyArray);
88
+ const [innerKey] = Object.keys(inner);
89
+
90
+ keyArray.push(innerKey);
91
+ innerVal = inner[innerKey];
92
+ } while (isObject(innerVal));
93
+
94
+ key = keyArray.join('.');
95
+ values = [innerVal];
96
+ } else {
97
+ values = [filter[key]];
98
+ }
99
+
65
100
  const splitKey = key.split('@');
66
101
  const operation: PostgRestOperator =
67
102
  splitKey.length == 2
68
103
  ? (splitKey[1] as PostgRestOperator)
69
104
  : defaultListOp;
70
105
 
71
- let values: Array<string>;
72
106
  if (['like', 'ilike'].includes(operation)) {
73
107
  // we split the search term in words
74
- values = filter[key].trim().split(/\s+/);
108
+ values = resolveKeys(filter, keyArray).trim().split(/\s+/);
75
109
  }
76
110
  // CASE: Logical operator
77
111
  else if (['or', 'and'].includes(operation)) {
78
112
  // we extract each value entries and make it dot separated string.
79
113
  const { filter: subFilter } = parseFilters(
80
- { filter: filter[key] },
114
+ { filter: resolveKeys(filter, keyArray) },
81
115
  defaultListOp
82
116
  );
83
117
 
@@ -91,8 +125,6 @@ export const parseFilters = (
91
125
 
92
126
  // finally we flatten all as single string and enclose with bracket.
93
127
  values = [`(${filterExpressions.join(',')})`];
94
- } else {
95
- values = [filter[key]];
96
128
  }
97
129
 
98
130
  values.forEach(value => {
@@ -103,12 +135,10 @@ export const parseFilters = (
103
135
  if (operation.includes('like'))
104
136
  return `${operation}.*${value}*`;
105
137
  if (['and', 'or'].includes(operation)) return `${value}`;
106
- if (['cs', 'cd'].includes(operation))
107
- return `${operation}.{${value}}`;
108
138
  return `${operation}.${value}`;
109
139
  })();
110
140
 
111
- // If resulting filter haven't contains the fieldname, then add it.
141
+ // If resulting filter doesn't contain the fieldname, then add it.
112
142
  if (result.filter[splitKey[0]] === undefined) {
113
143
  // first operator for the key,
114
144
  if (['and', 'or'].includes(operation)) {
@@ -170,8 +200,16 @@ export const encodeId = (data: any, primaryKey: PrimaryKey): Identifier => {
170
200
  }
171
201
  };
172
202
 
173
- export const dataWithId = (data: any, primaryKey: PrimaryKey) => {
174
- if (JSON.stringify(primaryKey) === JSON.stringify(['id'])) {
203
+ export const removePrimaryKey = (data: any, primaryKey: PrimaryKey) => {
204
+ const newData = { ...data };
205
+ primaryKey.forEach(key => {
206
+ delete newData[key];
207
+ });
208
+ return newData;
209
+ };
210
+
211
+ export const dataWithVirtualId = (data: any, primaryKey: PrimaryKey) => {
212
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
175
213
  return data;
176
214
  }
177
215
 
@@ -180,13 +218,22 @@ export const dataWithId = (data: any, primaryKey: PrimaryKey) => {
180
218
  });
181
219
  };
182
220
 
183
- export const isCompoundKey = (primaryKey: PrimaryKey): Boolean => {
221
+ export const dataWithoutVirtualId = (data: any, primaryKey: PrimaryKey) => {
222
+ if (primaryKey.length === 1 && primaryKey[0] === 'id') {
223
+ return data;
224
+ }
225
+
226
+ const { id, ...dataWithoutId } = data;
227
+ return dataWithoutId;
228
+ };
229
+
230
+ const isCompoundKey = (primaryKey: PrimaryKey): Boolean => {
184
231
  return primaryKey.length > 1;
185
232
  };
186
233
 
187
234
  export const getQuery = (
188
235
  primaryKey: PrimaryKey,
189
- ids: Identifier | Array<Identifier>,
236
+ ids: Identifier | Array<Identifier> | undefined,
190
237
  resource: string,
191
238
  meta: any = null
192
239
  ): any => {
@@ -215,7 +262,7 @@ export const getQuery = (
215
262
  [primaryKey[0]]: `in.(${ids.join(',')})`,
216
263
  };
217
264
  }
218
- } else {
265
+ } else if (ids) {
219
266
  // if ids is one Identifier
220
267
  const id: Identifier = ids.toString();
221
268
  const primaryKeyParams = decodeId(id, primaryKey);
@@ -251,20 +298,6 @@ export const getQuery = (
251
298
  return result;
252
299
  };
253
300
 
254
- export const getKeyData = (primaryKey: PrimaryKey, data: object): object => {
255
- if (isCompoundKey(primaryKey)) {
256
- return primaryKey.reduce(
257
- (keyData, key) => ({
258
- ...keyData,
259
- [key]: data[key],
260
- }),
261
- {}
262
- );
263
- } else {
264
- return { [primaryKey[0]]: data[primaryKey[0]] };
265
- }
266
- };
267
-
268
301
  export const getOrderBy = (
269
302
  field: string,
270
303
  order: string,