@raphiniert/ra-data-postgrest 2.0.0-alpha.0 → 2.0.0-alpha.3
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 +137 -41
- package/IDEAS.md +46 -0
- package/README.md +120 -55
- package/esm/index.d.ts +58 -7
- package/esm/index.js +229 -221
- package/esm/urlBuilder.d.ts +7 -3
- package/esm/urlBuilder.js +87 -38
- package/lib/index.d.ts +58 -7
- package/lib/index.js +234 -221
- package/lib/urlBuilder.d.ts +7 -3
- package/lib/urlBuilder.js +87 -38
- package/package.json +11 -6
- package/src/index.ts +237 -125
- package/src/urlBuilder.ts +100 -43
package/src/urlBuilder.ts
CHANGED
|
@@ -44,13 +44,21 @@ const postgrestOperators = [
|
|
|
44
44
|
'and',
|
|
45
45
|
] as const;
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
type ParsedFiltersResult = {
|
|
48
|
+
filter: any;
|
|
49
|
+
select: any;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type PostgRestOperator = (typeof postgrestOperators)[number];
|
|
48
53
|
|
|
49
54
|
export const parseFilters = (
|
|
50
|
-
|
|
55
|
+
params: any,
|
|
51
56
|
defaultListOp: PostgRestOperator
|
|
52
|
-
) => {
|
|
53
|
-
|
|
57
|
+
): Partial<ParsedFiltersResult> => {
|
|
58
|
+
const { filter, meta = {} } = params;
|
|
59
|
+
|
|
60
|
+
let result: Partial<ParsedFiltersResult> = {};
|
|
61
|
+
result.filter = {};
|
|
54
62
|
Object.keys(filter).forEach(function (key) {
|
|
55
63
|
// key: the name of the object key
|
|
56
64
|
|
|
@@ -64,33 +72,72 @@ export const parseFilters = (
|
|
|
64
72
|
if (['like', 'ilike'].includes(operation)) {
|
|
65
73
|
// we split the search term in words
|
|
66
74
|
values = filter[key].trim().split(/\s+/);
|
|
75
|
+
}
|
|
76
|
+
// CASE: Logical operator
|
|
77
|
+
else if (['or', 'and'].includes(operation)) {
|
|
78
|
+
// we extract each value entries and make it dot separated string.
|
|
79
|
+
const { filter: subFilter } = parseFilters(
|
|
80
|
+
{ filter: filter[key] },
|
|
81
|
+
defaultListOp
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// something like { "age@lt": 18 } and { "age@gt": 21 }
|
|
85
|
+
const filterExpressions: string[] = [];
|
|
86
|
+
Object.entries(subFilter).forEach(([op, val]) => {
|
|
87
|
+
if (Array.isArray(val))
|
|
88
|
+
filterExpressions.push(...val.map(v => [op, v].join('.')));
|
|
89
|
+
else filterExpressions.push([op, val].join('.'));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// finally we flatten all as single string and enclose with bracket.
|
|
93
|
+
values = [`(${filterExpressions.join(',')})`];
|
|
67
94
|
} else {
|
|
68
95
|
values = [filter[key]];
|
|
69
96
|
}
|
|
70
97
|
|
|
71
98
|
values.forEach(value => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
99
|
+
let op: string = (() => {
|
|
100
|
+
// if operator is intentionally blank, rpc syntax
|
|
101
|
+
if (operation.length === 0) return `${value}`;
|
|
102
|
+
|
|
103
|
+
if (operation.includes('like'))
|
|
104
|
+
return `${operation}.*${value}*`;
|
|
105
|
+
if (['and', 'or'].includes(operation)) return `${value}`;
|
|
106
|
+
if (['cs', 'cd'].includes(operation))
|
|
107
|
+
return `${operation}.{${value}}`;
|
|
108
|
+
return `${operation}.${value}`;
|
|
109
|
+
})();
|
|
110
|
+
|
|
111
|
+
// If resulting filter haven't contains the fieldname, then add it.
|
|
112
|
+
if (result.filter[splitKey[0]] === undefined) {
|
|
113
|
+
// first operator for the key,
|
|
114
|
+
if (['and', 'or'].includes(operation)) {
|
|
115
|
+
result.filter[operation] = op;
|
|
116
|
+
} else {
|
|
117
|
+
// we add it to the dict
|
|
118
|
+
result.filter[splitKey[0]] = op;
|
|
119
|
+
}
|
|
82
120
|
} else {
|
|
83
121
|
if (!Array.isArray(result[splitKey[0]])) {
|
|
84
122
|
// second operator, we transform to an array
|
|
85
|
-
result[splitKey[0]] = [
|
|
123
|
+
result.filter[splitKey[0]] = [
|
|
124
|
+
result.filter[splitKey[0]],
|
|
125
|
+
op,
|
|
126
|
+
];
|
|
86
127
|
} else {
|
|
87
128
|
// third and subsequent, we add to array
|
|
88
|
-
result[splitKey[0]].push(op);
|
|
129
|
+
result.filter[splitKey[0]].push(op);
|
|
89
130
|
}
|
|
90
131
|
}
|
|
91
132
|
});
|
|
92
133
|
});
|
|
93
134
|
|
|
135
|
+
if (meta?.columns) {
|
|
136
|
+
result.select = Array.isArray(meta.columns)
|
|
137
|
+
? meta.columns.join(',')
|
|
138
|
+
: meta.columns;
|
|
139
|
+
}
|
|
140
|
+
|
|
94
141
|
return result;
|
|
95
142
|
};
|
|
96
143
|
|
|
@@ -140,8 +187,10 @@ export const isCompoundKey = (primaryKey: PrimaryKey): Boolean => {
|
|
|
140
187
|
export const getQuery = (
|
|
141
188
|
primaryKey: PrimaryKey,
|
|
142
189
|
ids: Identifier | Array<Identifier>,
|
|
143
|
-
resource: string
|
|
144
|
-
|
|
190
|
+
resource: string,
|
|
191
|
+
meta: any = null
|
|
192
|
+
): any => {
|
|
193
|
+
let result: any = {};
|
|
145
194
|
if (Array.isArray(ids) && ids.length > 1) {
|
|
146
195
|
// no standardized query with multiple ids possible for rpc endpoints which are api-exposed database functions
|
|
147
196
|
if (resource.startsWith('rpc/')) {
|
|
@@ -153,17 +202,18 @@ export const getQuery = (
|
|
|
153
202
|
}
|
|
154
203
|
|
|
155
204
|
if (isCompoundKey(primaryKey)) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
205
|
+
result = {
|
|
206
|
+
or: `(${ids.map(id => {
|
|
207
|
+
const primaryKeyParams = decodeId(id, primaryKey);
|
|
208
|
+
return `and(${primaryKey
|
|
209
|
+
.map((key, i) => `${key}.eq.${primaryKeyParams[i]}`)
|
|
210
|
+
.join(',')})`;
|
|
211
|
+
})})`,
|
|
212
|
+
};
|
|
163
213
|
} else {
|
|
164
|
-
|
|
214
|
+
result = {
|
|
165
215
|
[primaryKey[0]]: `in.(${ids.join(',')})`,
|
|
166
|
-
}
|
|
216
|
+
};
|
|
167
217
|
}
|
|
168
218
|
} else {
|
|
169
219
|
// if ids is one Identifier
|
|
@@ -171,27 +221,34 @@ export const getQuery = (
|
|
|
171
221
|
const primaryKeyParams = decodeId(id, primaryKey);
|
|
172
222
|
|
|
173
223
|
if (isCompoundKey(primaryKey)) {
|
|
174
|
-
if (resource.startsWith('rpc/'))
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
(key
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return `and=(${primaryKey
|
|
184
|
-
.map(
|
|
224
|
+
if (resource.startsWith('rpc/')) {
|
|
225
|
+
result = {};
|
|
226
|
+
primaryKey.map(
|
|
227
|
+
(key: string, i: any) =>
|
|
228
|
+
(result[key] = `${primaryKeyParams[i]}`)
|
|
229
|
+
);
|
|
230
|
+
} else {
|
|
231
|
+
result = {
|
|
232
|
+
and: `(${primaryKey.map(
|
|
185
233
|
(key: string, i: any) =>
|
|
186
234
|
`${key}.eq.${primaryKeyParams[i]}`
|
|
187
|
-
)
|
|
188
|
-
|
|
235
|
+
)})`,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
189
238
|
} else {
|
|
190
|
-
|
|
191
|
-
[primaryKey[0]
|
|
192
|
-
|
|
239
|
+
result = {
|
|
240
|
+
[primaryKey[0]]: `eq.${id}`,
|
|
241
|
+
};
|
|
193
242
|
}
|
|
194
243
|
}
|
|
244
|
+
|
|
245
|
+
if (meta && meta.columns) {
|
|
246
|
+
result.select = Array.isArray(meta.columns)
|
|
247
|
+
? meta.columns.join(',')
|
|
248
|
+
: meta.columns;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return result;
|
|
195
252
|
};
|
|
196
253
|
|
|
197
254
|
export const getKeyData = (primaryKey: PrimaryKey, data: object): object => {
|