@feathersjs/adapter-commons 5.0.0-pre.16 → 5.0.0-pre.19

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/src/service.ts CHANGED
@@ -1,14 +1,7 @@
1
- import { NotImplemented, BadRequest, MethodNotAllowed } from '@feathersjs/errors';
2
- import { ServiceMethods, Params, Id, NullableId, Paginated } from '@feathersjs/feathers';
3
- import { filterQuery } from './filter-query';
4
-
5
- const callMethod = (self: any, name: any, ...args: any[]) => {
6
- if (typeof self[name] !== 'function') {
7
- return Promise.reject(new NotImplemented(`Method ${name} not available`));
8
- }
9
-
10
- return self[name](...args);
11
- };
1
+ import { BadRequest, MethodNotAllowed } from '@feathersjs/errors';
2
+ import { Id, NullableId, Paginated, Query } from '@feathersjs/feathers';
3
+ import { AdapterParams, AdapterServiceOptions, InternalServiceMethods, PaginationOptions } from './declarations';
4
+ import { filterQuery } from './query';
12
5
 
13
6
  const alwaysMulti: { [key: string]: boolean } = {
14
7
  find: true,
@@ -16,72 +9,180 @@ const alwaysMulti: { [key: string]: boolean } = {
16
9
  update: false
17
10
  };
18
11
 
19
- export interface ServiceOptions {
20
- events?: string[];
21
- multi?: boolean|string[];
22
- id?: string;
23
- paginate?: {
24
- default?: number;
25
- max?: number;
12
+ /**
13
+ * An abstract base class that a database adapter can extend from to implement the
14
+ * `__find`, `__get`, `__update`, `__patch` and `__remove` methods.
15
+ */
16
+ export abstract class AdapterBase<
17
+ T = any,
18
+ D = Partial<T>,
19
+ P extends AdapterParams = AdapterParams,
20
+ O extends AdapterServiceOptions = AdapterServiceOptions
21
+ > implements InternalServiceMethods<T, D, P> {
22
+ options: O;
23
+
24
+ constructor (options: O) {
25
+ this.options = {
26
+ id: 'id',
27
+ events: [],
28
+ paginate: false,
29
+ multi: false,
30
+ filters: {},
31
+ operators: [],
32
+ ...options
33
+ };
34
+ }
35
+
36
+ get id () {
37
+ return this.options.id;
38
+ }
39
+
40
+ get events () {
41
+ return this.options.events;
26
42
  }
43
+
27
44
  /**
28
- * @deprecated renamed to `allow`.
45
+ * Check if this adapter allows multiple updates for a method.
46
+ * @param method The method name to check.
47
+ * @param params The service call params.
48
+ * @returns Wether or not multiple updates are allowed.
29
49
  */
30
- whitelist?: string[];
31
- allow?: string[];
32
- filters?: string[];
33
- }
50
+ allowsMulti (method: string, params: P = {} as P) {
51
+ const always = alwaysMulti[method];
34
52
 
35
- export interface AdapterOptions<M = any> extends Pick<ServiceOptions, 'multi'|'allow'|'paginate'> {
36
- Model?: M;
37
- }
53
+ if (typeof always !== 'undefined') {
54
+ return always;
55
+ }
38
56
 
39
- export interface AdapterParams<M = any> extends Params {
40
- adapter?: Partial<AdapterOptions<M>>;
41
- }
57
+ const { multi } = this.getOptions(params);
42
58
 
43
- /**
44
- * Hook-less (internal) service methods. Directly call database adapter service methods
45
- * without running any service-level hooks. This can be useful if you need the raw data
46
- * from the service and don't want to trigger any of its hooks.
47
- *
48
- * Important: These methods are only available internally on the server, not on the client
49
- * side and only for the Feathers database adapters.
50
- *
51
- * These methods do not trigger events.
52
- *
53
- * @see {@link https://docs.feathersjs.com/guides/migrating.html#hook-less-service-methods}
54
- */
55
- export interface InternalServiceMethods<T = any, D = Partial<T>> {
59
+ if (multi === true || multi === false) {
60
+ return multi;
61
+ }
62
+
63
+ return multi.includes(method);
64
+ }
56
65
 
57
66
  /**
58
- * Retrieve all resources from this service, skipping any service-level hooks.
67
+ * Returns the combined options for a service call. Options will be merged
68
+ * with `this.options` and `params.adapter` for dynamic overrides.
69
+ *
70
+ * @param params The parameters for the service method call
71
+ * @returns The actual options for this call
72
+ */
73
+ getOptions (params: P): O {
74
+ const paginate = params.paginate !== undefined ? params.paginate : this.options.paginate;
75
+
76
+ return {
77
+ ...this.options,
78
+ paginate,
79
+ ...params.adapter
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Sanitize the incoming data, e.g. removing invalid keywords etc.
85
+ *
86
+ * @param data The data to sanitize
87
+ * @param _params Service call parameters
88
+ * @returns The sanitized data
89
+ */
90
+ async sanitizeData<X = Partial<D>> (data: X, _params: P) {
91
+ return data;
92
+ }
93
+
94
+ /**
95
+ * Returns a sanitized version of `params.query`, converting filter values
96
+ * (like $limit and $skip) into the expected type. Will throw an error if
97
+ * a `$` prefixed filter or operator value that is not allowed in `filters`
98
+ * or `operators` is encountered.
99
+ *
100
+ * @param params The service call parameter.
101
+ * @returns A new object containing the sanitized query.
102
+ */
103
+ async sanitizeQuery (params: P = {} as P): Promise<Query> {
104
+ const options = this.getOptions(params);
105
+ const { query, filters } = filterQuery(params.query, options)
106
+
107
+ return {
108
+ ...filters,
109
+ ...query
110
+ };
111
+ }
112
+
113
+ abstract $find(_params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>;
114
+ abstract $find(_params?: P & { paginate: false }): Promise<T[]>;
115
+ abstract $find(params?: P): Promise<T[] | Paginated<T>>;
116
+
117
+ /**
118
+ * Retrieve all resources from this service, skipping any service-level hooks but sanitize the query
119
+ * with allowed filters and properties by calling `sanitizeQuery`.
59
120
  *
60
121
  * @param params - Service call parameters {@link Params}
61
122
  * @see {@link HookLessServiceMethods}
62
123
  * @see {@link https://docs.feathersjs.com/api/services.html#find-params|Feathers API Documentation: .find(params)}
63
124
  */
64
- _find (params?: AdapterParams): Promise<T | T[] | Paginated<T>>;
125
+ async _find(_params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>;
126
+ async _find(_params?: P & { paginate: false }): Promise<T[]>;
127
+ async _find(params?: P): Promise<T | T[] | Paginated<T>>;
128
+ async _find (params?: P): Promise<T | T[] | Paginated<T>> {
129
+ const query = await this.sanitizeQuery(params);
130
+
131
+ return this.$find({
132
+ ...params,
133
+ query
134
+ });
135
+ }
136
+
137
+ abstract $get(id: Id, params?: P): Promise<T>;
65
138
 
66
139
  /**
67
- * Retrieve a single resource matching the given ID, skipping any service-level hooks.
140
+ * Retrieve a single resource matching the given ID, skipping any service-level hooks but sanitize the query
141
+ * with allowed filters and properties by calling `sanitizeQuery`.
68
142
  *
69
143
  * @param id - ID of the resource to locate
70
144
  * @param params - Service call parameters {@link Params}
71
145
  * @see {@link HookLessServiceMethods}
72
146
  * @see {@link https://docs.feathersjs.com/api/services.html#get-id-params|Feathers API Documentation: .get(id, params)}
73
147
  */
74
- _get (id: Id, params?: AdapterParams): Promise<T>;
148
+ async _get (id: Id, params?: P): Promise<T> {
149
+ const query = await this.sanitizeQuery(params);
150
+
151
+ return this.$get(id, {
152
+ ...params,
153
+ query
154
+ });
155
+ }
156
+
157
+ abstract $create(data: Partial<D>, params?: P): Promise<T>;
158
+ abstract $create(data: Partial<D>[], params?: P): Promise<T[]>;
159
+ abstract $create(data: Partial<D> | Partial<D>[], params?: P): Promise<T | T[]>;
75
160
 
76
161
  /**
77
- * Create a new resource for this service, skipping any service-level hooks.
162
+ * Create a new resource for this service, skipping any service-level hooks, sanitize the data
163
+ * and check if multiple updates are allowed.
78
164
  *
79
165
  * @param data - Data to insert into this service.
80
166
  * @param params - Service call parameters {@link Params}
81
167
  * @see {@link HookLessServiceMethods}
82
168
  * @see {@link https://docs.feathersjs.com/api/services.html#create-data-params|Feathers API Documentation: .create(data, params)}
83
169
  */
84
- _create (data: D | D[], params?: AdapterParams): Promise<T | T[]>;
170
+ async _create(data: Partial<D>, params?: P): Promise<T>;
171
+ async _create(data: Partial<D>[], params?: P): Promise<T[]>;
172
+ async _create(data: Partial<D> | Partial<D>[], params?: P): Promise<T | T[]>;
173
+ async _create (data: Partial<D> | Partial<D>[], params?: P): Promise<T | T[]> {
174
+ if (Array.isArray(data) && !this.allowsMulti('create', params)) {
175
+ throw new MethodNotAllowed('Can not create multiple entries');
176
+ }
177
+
178
+ const payload = Array.isArray(data)
179
+ ? (await Promise.all(data.map(current => this.sanitizeData(current, params))))
180
+ : (await this.sanitizeData(data, params));
181
+
182
+ return this.$create(payload, params);
183
+ }
184
+
185
+ abstract $update(id: Id, data: D, params?: P): Promise<T>;
85
186
 
86
187
  /**
87
188
  * Replace any resources matching the given ID with the given data, skipping any service-level hooks.
@@ -92,10 +193,29 @@ export interface InternalServiceMethods<T = any, D = Partial<T>> {
92
193
  * @see {@link HookLessServiceMethods}
93
194
  * @see {@link https://docs.feathersjs.com/api/services.html#update-id-data-params|Feathers API Documentation: .update(id, data, params)}
94
195
  */
95
- _update (id: Id, data: D, params?: AdapterParams): Promise<T>;
196
+ async _update (id: Id, data: D, params?: P): Promise<T> {
197
+ if (id === null || Array.isArray(data)) {
198
+ throw new BadRequest(
199
+ 'You can not replace multiple instances. Did you mean \'patch\'?'
200
+ );
201
+ }
202
+
203
+ const payload = await this.sanitizeData(data, params);
204
+ const query = await this.sanitizeQuery(params);
205
+
206
+ return this.$update(id, payload, {
207
+ ...params,
208
+ query
209
+ });
210
+ }
211
+
212
+ abstract $patch(id: null, data: Partial<D>, params?: P): Promise<T[]>;
213
+ abstract $patch(id: Id, data: Partial<D>, params?: P): Promise<T>;
214
+ abstract $patch(id: NullableId, data: Partial<D>, params?: P): Promise<T | T[]>;
96
215
 
97
216
  /**
98
217
  * Merge any resources matching the given ID with the given data, skipping any service-level hooks.
218
+ * Sanitizes the query and data and checks it multiple updates are allowed.
99
219
  *
100
220
  * @param id - ID of the resource to be patched
101
221
  * @param data - Data to merge with the current resource.
@@ -103,132 +223,49 @@ export interface InternalServiceMethods<T = any, D = Partial<T>> {
103
223
  * @see {@link HookLessServiceMethods}
104
224
  * @see {@link https://docs.feathersjs.com/api/services.html#patch-id-data-params|Feathers API Documentation: .patch(id, data, params)}
105
225
  */
106
- _patch (id: NullableId, data: D, params?: AdapterParams): Promise<T | T[]>;
226
+ async _patch(id: null, data: Partial<D>, params?: P): Promise<T[]>;
227
+ async _patch(id: Id, data: Partial<D>, params?: P): Promise<T>;
228
+ async _patch(id: NullableId, data: Partial<D>, params?: P): Promise<T | T[]>;
229
+ async _patch (id: NullableId, data: Partial<D>, params?: P): Promise<T | T[]> {
230
+ if (id === null && !this.allowsMulti('patch', params)) {
231
+ throw new MethodNotAllowed('Can not patch multiple entries');
232
+ }
233
+
234
+ const query = await this.sanitizeQuery(params);
235
+ const payload = await this.sanitizeData(data, params);
236
+
237
+ return this.$patch(id, payload, {
238
+ ...params,
239
+ query
240
+ });
241
+ }
242
+
243
+ abstract $remove(id: null, params?: P): Promise<T[]>;
244
+ abstract $remove(id: Id, params?: P): Promise<T>;
245
+ abstract $remove(id: NullableId, params?: P): Promise<T | T[]>;
107
246
 
108
247
  /**
109
248
  * Remove resources matching the given ID from the this service, skipping any service-level hooks.
249
+ * Sanitized the query and verifies that multiple updates are allowed.
110
250
  *
111
251
  * @param id - ID of the resource to be removed
112
252
  * @param params - Service call parameters {@link Params}
113
253
  * @see {@link HookLessServiceMethods}
114
254
  * @see {@link https://docs.feathersjs.com/api/services.html#remove-id-params|Feathers API Documentation: .remove(id, params)}
115
255
  */
116
- _remove (id: NullableId, params?: AdapterParams): Promise<T | T[]>;
117
- }
118
-
119
- export class AdapterService<
120
- T = any,
121
- D = Partial<T>,
122
- O extends Partial<ServiceOptions> = Partial<ServiceOptions>
123
- > implements ServiceMethods<T|Paginated<T>, D> {
124
- options: ServiceOptions & O;
125
-
126
- constructor (options: O) {
127
- this.options = Object.assign({
128
- id: 'id',
129
- events: [],
130
- paginate: {},
131
- multi: false,
132
- filters: [],
133
- allow: []
134
- }, options);
135
- }
136
-
137
- get id () {
138
- return this.options.id;
139
- }
140
-
141
- get events () {
142
- return this.options.events;
143
- }
144
-
145
- filterQuery (params: AdapterParams = {}, opts: any = {}) {
146
- const paginate = typeof params.paginate !== 'undefined'
147
- ? params.paginate
148
- : this.getOptions(params).paginate;
149
- const { query = {} } = params;
150
- const options = Object.assign({
151
- operators: this.options.whitelist || this.options.allow || [],
152
- filters: this.options.filters,
153
- paginate
154
- }, opts);
155
- const result = filterQuery(query, options);
156
-
157
- return Object.assign(result, { paginate });
158
- }
159
-
160
- allowsMulti (method: string, params: AdapterParams = {}) {
161
- const always = alwaysMulti[method];
162
-
163
- if (typeof always !== 'undefined') {
164
- return always;
165
- }
166
-
167
- const { multi: option } = this.getOptions(params);
168
-
169
- if (option === true || option === false) {
170
- return option;
171
- }
172
-
173
- return option.includes(method);
174
- }
175
-
176
- getOptions (params: AdapterParams): ServiceOptions & { model?: any } {
177
- return {
178
- ...this.options,
179
- ...params.adapter
180
- }
181
- }
182
-
183
- find (params?: AdapterParams): Promise<T[] | Paginated<T>> {
184
- return callMethod(this, '_find', params);
185
- }
186
-
187
- get (id: Id, params?: AdapterParams): Promise<T> {
188
- return callMethod(this, '_get', id, params);
189
- }
190
-
191
- create (data: Partial<T>, params?: AdapterParams): Promise<T>;
192
- create (data: Partial<T>[], params?: AdapterParams): Promise<T[]>;
193
- create (data: Partial<T> | Partial<T>[], params?: AdapterParams): Promise<T | T[]> {
194
- if (Array.isArray(data) && !this.allowsMulti('create', params)) {
195
- return Promise.reject(new MethodNotAllowed('Can not create multiple entries'));
196
- }
197
-
198
- return callMethod(this, '_create', data, params);
199
- }
200
-
201
- update (id: Id, data: D, params?: AdapterParams): Promise<T> {
202
- if (id === null || Array.isArray(data)) {
203
- return Promise.reject(new BadRequest(
204
- 'You can not replace multiple instances. Did you mean \'patch\'?'
205
- ));
206
- }
207
-
208
- return callMethod(this, '_update', id, data, params);
209
- }
210
-
211
- patch (id: Id, data: Partial<T>, params?: AdapterParams): Promise<T>;
212
- patch (id: null, data: Partial<T>, params?: AdapterParams): Promise<T[]>;
213
- patch (id: NullableId, data: Partial<T>, params?: AdapterParams): Promise<T | T[]>;
214
- patch (id: NullableId, data: Partial<T>, params?: AdapterParams): Promise<T | T[]> {
215
- if (id === null && !this.allowsMulti('patch', params)) {
216
- return Promise.reject(new MethodNotAllowed('Can not patch multiple entries'));
217
- }
218
-
219
- return callMethod(this, '_patch', id, data, params);
220
- }
221
-
222
- remove (id: Id, params?: AdapterParams): Promise<T>;
223
- remove (id: null, params?: AdapterParams): Promise<T[]>;
224
- remove (id: NullableId, params?: AdapterParams): Promise<T | T[]>;
225
- remove (id: NullableId, params?: AdapterParams): Promise<T | T[]> {
256
+ async _remove(id: null, params?: P): Promise<T[]>;
257
+ async _remove(id: Id, params?: P): Promise<T>;
258
+ async _remove(id: NullableId, params?: P): Promise<T | T[]>;
259
+ async _remove (id: NullableId, params?: P): Promise<T | T[]> {
226
260
  if (id === null && !this.allowsMulti('remove', params)) {
227
- return Promise.reject(new MethodNotAllowed('Can not remove multiple entries'));
261
+ throw new MethodNotAllowed('Can not remove multiple entries');
228
262
  }
229
263
 
230
- return callMethod(this, '_remove', id, params);
231
- }
264
+ const query = await this.sanitizeQuery(params);
232
265
 
233
- async setup () {}
266
+ return this.$remove(id, {
267
+ ...params,
268
+ query
269
+ });
270
+ }
234
271
  }
@@ -1,10 +0,0 @@
1
- export declare const FILTERS: {
2
- $sort: (value: any) => any;
3
- $limit: (value: any, options: any) => any;
4
- $skip: (value: any) => number;
5
- $select: (value: any) => any;
6
- };
7
- export declare const OPERATORS: string[];
8
- export declare function filterQuery(query: any, options?: any): {
9
- [key: string]: any;
10
- };
@@ -1,96 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.filterQuery = exports.OPERATORS = exports.FILTERS = void 0;
4
- const commons_1 = require("@feathersjs/commons");
5
- const errors_1 = require("@feathersjs/errors");
6
- function parse(number) {
7
- if (typeof number !== 'undefined') {
8
- return Math.abs(parseInt(number, 10));
9
- }
10
- return undefined;
11
- }
12
- // Returns the pagination limit and will take into account the
13
- // default and max pagination settings
14
- function getLimit(limit, paginate) {
15
- if (paginate && (paginate.default || paginate.max)) {
16
- const base = paginate.default || 0;
17
- const lower = typeof limit === 'number' && !isNaN(limit) ? limit : base;
18
- const upper = typeof paginate.max === 'number' ? paginate.max : Number.MAX_VALUE;
19
- return Math.min(lower, upper);
20
- }
21
- return limit;
22
- }
23
- // Makes sure that $sort order is always converted to an actual number
24
- function convertSort(sort) {
25
- if (typeof sort !== 'object' || Array.isArray(sort)) {
26
- return sort;
27
- }
28
- return Object.keys(sort).reduce((result, key) => {
29
- result[key] = typeof sort[key] === 'object'
30
- ? sort[key] : parseInt(sort[key], 10);
31
- return result;
32
- }, {});
33
- }
34
- function cleanQuery(query, operators, filters) {
35
- if (Array.isArray(query)) {
36
- return query.map(value => cleanQuery(value, operators, filters));
37
- }
38
- else if (commons_1._.isObject(query) && query.constructor === {}.constructor) {
39
- const result = {};
40
- commons_1._.each(query, (value, key) => {
41
- if (key[0] === '$') {
42
- if (filters[key] !== undefined) {
43
- return;
44
- }
45
- if (!operators.includes(key)) {
46
- throw new errors_1.BadRequest(`Invalid query parameter ${key}`, query);
47
- }
48
- }
49
- result[key] = cleanQuery(value, operators, filters);
50
- });
51
- Object.getOwnPropertySymbols(query).forEach(symbol => {
52
- // @ts-ignore
53
- result[symbol] = query[symbol];
54
- });
55
- return result;
56
- }
57
- return query;
58
- }
59
- function assignFilters(object, query, filters, options) {
60
- if (Array.isArray(filters)) {
61
- commons_1._.each(filters, (key) => {
62
- if (query[key] !== undefined) {
63
- object[key] = query[key];
64
- }
65
- });
66
- }
67
- else {
68
- commons_1._.each(filters, (converter, key) => {
69
- const converted = converter(query[key], options);
70
- if (converted !== undefined) {
71
- object[key] = converted;
72
- }
73
- });
74
- }
75
- return object;
76
- }
77
- exports.FILTERS = {
78
- $sort: (value) => convertSort(value),
79
- $limit: (value, options) => getLimit(parse(value), options.paginate),
80
- $skip: (value) => parse(value),
81
- $select: (value) => value
82
- };
83
- exports.OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or'];
84
- // Converts Feathers special query parameters and pagination settings
85
- // and returns them separately a `filters` and the rest of the query
86
- // as `query`
87
- function filterQuery(query, options = {}) {
88
- const { filters: additionalFilters = {}, operators: additionalOperators = [] } = options;
89
- const result = {};
90
- result.filters = assignFilters({}, query, exports.FILTERS, options);
91
- result.filters = assignFilters(result.filters, query, additionalFilters, options);
92
- result.query = cleanQuery(query, exports.OPERATORS.concat(additionalOperators), result.filters);
93
- return result;
94
- }
95
- exports.filterQuery = filterQuery;
96
- //# sourceMappingURL=filter-query.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-query.js","sourceRoot":"","sources":["../src/filter-query.ts"],"names":[],"mappings":"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"}
@@ -1,116 +0,0 @@
1
- import { _ } from '@feathersjs/commons';
2
- import { BadRequest } from '@feathersjs/errors';
3
-
4
- function parse (number: any) {
5
- if (typeof number !== 'undefined') {
6
- return Math.abs(parseInt(number, 10));
7
- }
8
-
9
- return undefined;
10
- }
11
-
12
- // Returns the pagination limit and will take into account the
13
- // default and max pagination settings
14
- function getLimit (limit: any, paginate: any) {
15
- if (paginate && (paginate.default || paginate.max)) {
16
- const base = paginate.default || 0;
17
- const lower = typeof limit === 'number' && !isNaN(limit) ? limit : base;
18
- const upper = typeof paginate.max === 'number' ? paginate.max : Number.MAX_VALUE;
19
-
20
- return Math.min(lower, upper);
21
- }
22
-
23
- return limit;
24
- }
25
-
26
- // Makes sure that $sort order is always converted to an actual number
27
- function convertSort (sort: any) {
28
- if (typeof sort !== 'object' || Array.isArray(sort)) {
29
- return sort;
30
- }
31
-
32
- return Object.keys(sort).reduce((result, key) => {
33
- result[key] = typeof sort[key] === 'object'
34
- ? sort[key] : parseInt(sort[key], 10);
35
-
36
- return result;
37
- }, {} as { [key: string]: number });
38
- }
39
-
40
- function cleanQuery (query: any, operators: any, filters: any): any {
41
- if (Array.isArray(query)) {
42
- return query.map(value => cleanQuery(value, operators, filters));
43
- } else if (_.isObject(query) && query.constructor === {}.constructor) {
44
- const result: { [key: string]: any } = {};
45
-
46
- _.each(query, (value, key) => {
47
- if (key[0] === '$') {
48
- if (filters[key] !== undefined) {
49
- return;
50
- }
51
-
52
- if (!operators.includes(key)) {
53
- throw new BadRequest(`Invalid query parameter ${key}`, query);
54
- }
55
- }
56
-
57
- result[key] = cleanQuery(value, operators, filters);
58
- });
59
-
60
- Object.getOwnPropertySymbols(query).forEach(symbol => {
61
- // @ts-ignore
62
- result[symbol] = query[symbol];
63
- });
64
-
65
- return result;
66
- }
67
-
68
- return query;
69
- }
70
-
71
- function assignFilters (object: any, query: any, filters: any, options: any) {
72
- if (Array.isArray(filters)) {
73
- _.each(filters, (key) => {
74
- if (query[key] !== undefined) {
75
- object[key] = query[key];
76
- }
77
- });
78
- } else {
79
- _.each(filters, (converter, key) => {
80
- const converted = converter(query[key], options);
81
-
82
- if (converted !== undefined) {
83
- object[key] = converted;
84
- }
85
- });
86
- }
87
-
88
- return object;
89
- }
90
-
91
- export const FILTERS = {
92
- $sort: (value: any) => convertSort(value),
93
- $limit: (value: any, options: any) => getLimit(parse(value), options.paginate),
94
- $skip: (value: any) => parse(value),
95
- $select: (value: any) => value
96
- };
97
-
98
- export const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or'];
99
-
100
- // Converts Feathers special query parameters and pagination settings
101
- // and returns them separately a `filters` and the rest of the query
102
- // as `query`
103
- export function filterQuery (query: any, options: any = {}) {
104
- const {
105
- filters: additionalFilters = {},
106
- operators: additionalOperators = []
107
- } = options;
108
- const result: { [key: string]: any } = {};
109
-
110
- result.filters = assignFilters({}, query, FILTERS, options);
111
- result.filters = assignFilters(result.filters, query, additionalFilters, options);
112
-
113
- result.query = cleanQuery(query, OPERATORS.concat(additionalOperators), result.filters);
114
-
115
- return result;
116
- }