@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/lib/service.js CHANGED
@@ -1,29 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AdapterService = void 0;
3
+ exports.AdapterBase = void 0;
4
4
  const errors_1 = require("@feathersjs/errors");
5
- const filter_query_1 = require("./filter-query");
6
- const callMethod = (self, name, ...args) => {
7
- if (typeof self[name] !== 'function') {
8
- return Promise.reject(new errors_1.NotImplemented(`Method ${name} not available`));
9
- }
10
- return self[name](...args);
11
- };
5
+ const query_1 = require("./query");
12
6
  const alwaysMulti = {
13
7
  find: true,
14
8
  get: false,
15
9
  update: false
16
10
  };
17
- class AdapterService {
11
+ /**
12
+ * An abstract base class that a database adapter can extend from to implement the
13
+ * `__find`, `__get`, `__update`, `__patch` and `__remove` methods.
14
+ */
15
+ class AdapterBase {
18
16
  constructor(options) {
19
- this.options = Object.assign({
17
+ this.options = {
20
18
  id: 'id',
21
19
  events: [],
22
- paginate: {},
20
+ paginate: false,
23
21
  multi: false,
24
- filters: [],
25
- allow: []
26
- }, options);
22
+ filters: {},
23
+ operators: [],
24
+ ...options
25
+ };
27
26
  }
28
27
  get id() {
29
28
  return this.options.id;
@@ -31,67 +30,138 @@ class AdapterService {
31
30
  get events() {
32
31
  return this.options.events;
33
32
  }
34
- filterQuery(params = {}, opts = {}) {
35
- const paginate = typeof params.paginate !== 'undefined'
36
- ? params.paginate
37
- : this.getOptions(params).paginate;
38
- const { query = {} } = params;
39
- const options = Object.assign({
40
- operators: this.options.whitelist || this.options.allow || [],
41
- filters: this.options.filters,
42
- paginate
43
- }, opts);
44
- const result = (0, filter_query_1.filterQuery)(query, options);
45
- return Object.assign(result, { paginate });
46
- }
33
+ /**
34
+ * Check if this adapter allows multiple updates for a method.
35
+ * @param method The method name to check.
36
+ * @param params The service call params.
37
+ * @returns Wether or not multiple updates are allowed.
38
+ */
47
39
  allowsMulti(method, params = {}) {
48
40
  const always = alwaysMulti[method];
49
41
  if (typeof always !== 'undefined') {
50
42
  return always;
51
43
  }
52
- const { multi: option } = this.getOptions(params);
53
- if (option === true || option === false) {
54
- return option;
44
+ const { multi } = this.getOptions(params);
45
+ if (multi === true || multi === false) {
46
+ return multi;
55
47
  }
56
- return option.includes(method);
48
+ return multi.includes(method);
57
49
  }
50
+ /**
51
+ * Returns the combined options for a service call. Options will be merged
52
+ * with `this.options` and `params.adapter` for dynamic overrides.
53
+ *
54
+ * @param params The parameters for the service method call
55
+ * @returns The actual options for this call
56
+ */
58
57
  getOptions(params) {
58
+ const paginate = params.paginate !== undefined ? params.paginate : this.options.paginate;
59
59
  return {
60
60
  ...this.options,
61
+ paginate,
61
62
  ...params.adapter
62
63
  };
63
64
  }
64
- find(params) {
65
- return callMethod(this, '_find', params);
65
+ /**
66
+ * Sanitize the incoming data, e.g. removing invalid keywords etc.
67
+ *
68
+ * @param data The data to sanitize
69
+ * @param _params Service call parameters
70
+ * @returns The sanitized data
71
+ */
72
+ async sanitizeData(data, _params) {
73
+ return data;
74
+ }
75
+ /**
76
+ * Returns a sanitized version of `params.query`, converting filter values
77
+ * (like $limit and $skip) into the expected type. Will throw an error if
78
+ * a `$` prefixed filter or operator value that is not allowed in `filters`
79
+ * or `operators` is encountered.
80
+ *
81
+ * @param params The service call parameter.
82
+ * @returns A new object containing the sanitized query.
83
+ */
84
+ async sanitizeQuery(params = {}) {
85
+ const options = this.getOptions(params);
86
+ const { query, filters } = (0, query_1.filterQuery)(params.query, options);
87
+ return {
88
+ ...filters,
89
+ ...query
90
+ };
91
+ }
92
+ async _find(params) {
93
+ const query = await this.sanitizeQuery(params);
94
+ return this.$find({
95
+ ...params,
96
+ query
97
+ });
66
98
  }
67
- get(id, params) {
68
- return callMethod(this, '_get', id, params);
99
+ /**
100
+ * Retrieve a single resource matching the given ID, skipping any service-level hooks but sanitize the query
101
+ * with allowed filters and properties by calling `sanitizeQuery`.
102
+ *
103
+ * @param id - ID of the resource to locate
104
+ * @param params - Service call parameters {@link Params}
105
+ * @see {@link HookLessServiceMethods}
106
+ * @see {@link https://docs.feathersjs.com/api/services.html#get-id-params|Feathers API Documentation: .get(id, params)}
107
+ */
108
+ async _get(id, params) {
109
+ const query = await this.sanitizeQuery(params);
110
+ return this.$get(id, {
111
+ ...params,
112
+ query
113
+ });
69
114
  }
70
- create(data, params) {
115
+ async _create(data, params) {
71
116
  if (Array.isArray(data) && !this.allowsMulti('create', params)) {
72
- return Promise.reject(new errors_1.MethodNotAllowed('Can not create multiple entries'));
117
+ throw new errors_1.MethodNotAllowed('Can not create multiple entries');
73
118
  }
74
- return callMethod(this, '_create', data, params);
119
+ const payload = Array.isArray(data)
120
+ ? (await Promise.all(data.map(current => this.sanitizeData(current, params))))
121
+ : (await this.sanitizeData(data, params));
122
+ return this.$create(payload, params);
75
123
  }
76
- update(id, data, params) {
124
+ /**
125
+ * Replace any resources matching the given ID with the given data, skipping any service-level hooks.
126
+ *
127
+ * @param id - ID of the resource to be updated
128
+ * @param data - Data to be put in place of the current resource.
129
+ * @param params - Service call parameters {@link Params}
130
+ * @see {@link HookLessServiceMethods}
131
+ * @see {@link https://docs.feathersjs.com/api/services.html#update-id-data-params|Feathers API Documentation: .update(id, data, params)}
132
+ */
133
+ async _update(id, data, params) {
77
134
  if (id === null || Array.isArray(data)) {
78
- return Promise.reject(new errors_1.BadRequest('You can not replace multiple instances. Did you mean \'patch\'?'));
135
+ throw new errors_1.BadRequest('You can not replace multiple instances. Did you mean \'patch\'?');
79
136
  }
80
- return callMethod(this, '_update', id, data, params);
137
+ const payload = await this.sanitizeData(data, params);
138
+ const query = await this.sanitizeQuery(params);
139
+ return this.$update(id, payload, {
140
+ ...params,
141
+ query
142
+ });
81
143
  }
82
- patch(id, data, params) {
144
+ async _patch(id, data, params) {
83
145
  if (id === null && !this.allowsMulti('patch', params)) {
84
- return Promise.reject(new errors_1.MethodNotAllowed('Can not patch multiple entries'));
146
+ throw new errors_1.MethodNotAllowed('Can not patch multiple entries');
85
147
  }
86
- return callMethod(this, '_patch', id, data, params);
148
+ const query = await this.sanitizeQuery(params);
149
+ const payload = await this.sanitizeData(data, params);
150
+ return this.$patch(id, payload, {
151
+ ...params,
152
+ query
153
+ });
87
154
  }
88
- remove(id, params) {
155
+ async _remove(id, params) {
89
156
  if (id === null && !this.allowsMulti('remove', params)) {
90
- return Promise.reject(new errors_1.MethodNotAllowed('Can not remove multiple entries'));
157
+ throw new errors_1.MethodNotAllowed('Can not remove multiple entries');
91
158
  }
92
- return callMethod(this, '_remove', id, params);
159
+ const query = await this.sanitizeQuery(params);
160
+ return this.$remove(id, {
161
+ ...params,
162
+ query
163
+ });
93
164
  }
94
- async setup() { }
95
165
  }
96
- exports.AdapterService = AdapterService;
166
+ exports.AdapterBase = AdapterBase;
97
167
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":";;;AAAA,+CAAkE;AAGlE,mCAAsC;AAEtC,MAAM,WAAW,GAA+B;IAC9C,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,KAAK;CACd,CAAC;AAEF;;;GAGG;AACH,MAAsB,WAAW;IAQ/B,YAAa,OAAU;QACrB,IAAI,CAAC,OAAO,GAAG;YACb,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE;YACb,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED;;;;;OAKG;IACF,WAAW,CAAE,MAAc,EAAE,SAAY,EAAO;QAC/C,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAEnC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YACjC,OAAO,MAAM,CAAC;SACf;QAED,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE1C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE;YACrC,OAAO,KAAK,CAAC;SACd;QAED,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAE,MAAS;QACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAEzF,OAAO;YACL,GAAG,IAAI,CAAC,OAAO;YACf,QAAQ;YACR,GAAG,MAAM,CAAC,OAAO;SAClB,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAkB,IAAO,EAAE,OAAU;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAa,CAAE,SAAY,EAAO;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAE7D,OAAO;YACL,GAAG,OAAO;YACV,GAAG,KAAK;SACT,CAAC;IACJ,CAAC;IAiBD,KAAK,CAAC,KAAK,CAAE,MAAU;QACrB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,IAAI,CAAC,KAAK,CAAC;YAChB,GAAG,MAAM;YACT,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAID;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAE,EAAM,EAAE,MAAU;QAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;YACnB,GAAG,MAAM;YACT,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAkBD,KAAK,CAAC,OAAO,CAAE,IAA+B,EAAE,MAAU;QACxD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;YAC9D,MAAM,IAAI,yBAAgB,CAAC,iCAAiC,CAAC,CAAC;SAC/D;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAE5C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAID;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CAAE,EAAM,EAAE,IAAO,EAAE,MAAU;QACxC,IAAI,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACtC,MAAM,IAAI,mBAAU,CAClB,iEAAiE,CAClE,CAAC;SACH;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE;YAC/B,GAAG,MAAM;YACT,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAmBD,KAAK,CAAC,MAAM,CAAE,EAAc,EAAE,IAAgB,EAAE,MAAU;QACxD,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACrD,MAAM,IAAI,yBAAgB,CAAC,gCAAgC,CAAC,CAAC;SAC9D;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAEtD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE;YAC9B,GAAG,MAAM;YACT,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAkBD,KAAK,CAAC,OAAO,CAAE,EAAc,EAAE,MAAU;QACvC,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;YACtD,MAAM,IAAI,yBAAgB,CAAC,iCAAiC,CAAC,CAAC;SAC/D;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAE/C,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE;YACtB,GAAG,MAAM;YACT,KAAK;SACN,CAAC,CAAC;IACL,CAAC;CACF;AA/PD,kCA+PC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feathersjs/adapter-commons",
3
- "version": "5.0.0-pre.16",
3
+ "version": "5.0.0-pre.19",
4
4
  "description": "Shared database adapter utility functions",
5
5
  "homepage": "https://feathersjs.com",
6
6
  "keywords": [
@@ -13,7 +13,8 @@
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git://github.com/feathersjs/feathers.git"
16
+ "url": "git://github.com/feathersjs/feathers.git",
17
+ "directory": "packages/adapter-commons"
17
18
  },
18
19
  "author": {
19
20
  "name": "Feathers contributor",
@@ -48,19 +49,19 @@
48
49
  "access": "public"
49
50
  },
50
51
  "dependencies": {
51
- "@feathersjs/commons": "^5.0.0-pre.16",
52
- "@feathersjs/errors": "^5.0.0-pre.16",
53
- "@feathersjs/feathers": "^5.0.0-pre.16"
52
+ "@feathersjs/commons": "^5.0.0-pre.19",
53
+ "@feathersjs/errors": "^5.0.0-pre.19",
54
+ "@feathersjs/feathers": "^5.0.0-pre.19"
54
55
  },
55
56
  "devDependencies": {
56
- "@types/mocha": "^9.0.0",
57
+ "@types/mocha": "^9.1.1",
57
58
  "@types/mongodb": "^4.0.6",
58
- "@types/node": "^17.0.5",
59
- "mocha": "^9.1.3",
60
- "mongodb": "^4.2.2",
61
- "shx": "^0.3.3",
62
- "ts-node": "^10.4.0",
63
- "typescript": "^4.5.4"
59
+ "@types/node": "^17.0.31",
60
+ "mocha": "^10.0.0",
61
+ "mongodb": "^4.5.0",
62
+ "shx": "^0.3.4",
63
+ "ts-node": "^10.7.0",
64
+ "typescript": "^4.6.4"
64
65
  },
65
- "gitHead": "f0cd227a82d159b528193bd33747c97684a48773"
66
+ "gitHead": "57f3e18bb62735e1869ffafee90286498738fdfa"
66
67
  }
@@ -0,0 +1,153 @@
1
+ import { Query, Params, Paginated, Id, NullableId } from '@feathersjs/feathers';
2
+
3
+ export type FilterQueryOptions = {
4
+ filters?: FilterSettings;
5
+ operators?: string[];
6
+ paginate?: PaginationParams;
7
+ }
8
+
9
+ export type QueryFilter = (value: any, options: FilterQueryOptions) => any
10
+
11
+ export type FilterSettings = {
12
+ [key: string]: QueryFilter | true
13
+ }
14
+
15
+ export interface PaginationOptions {
16
+ default?: number;
17
+ max?: number;
18
+ }
19
+
20
+ export type PaginationParams = false | PaginationOptions;
21
+
22
+ export interface AdapterServiceOptions {
23
+ /**
24
+ * Whether to allow multiple updates for everything (`true`) or specific methods (e.g. `['create', 'remove']`)
25
+ */
26
+ multi?: boolean | string[];
27
+ /**
28
+ * The name of the id property
29
+ */
30
+ id?: string;
31
+ /**
32
+ * Pagination settings for this service
33
+ */
34
+ paginate?: PaginationParams;
35
+ /**
36
+ * A list of additional property query operators to allow in a query
37
+ */
38
+ operators?: string[];
39
+ /**
40
+ * An object of additional top level query filters, e.g. `{ $populate: true }`
41
+ * Can also be a converter function like `{ $ignoreCase: (value) => value === 'true' ? true : false }`
42
+ */
43
+ filters?: FilterSettings;
44
+ /**
45
+ * @deprecated Use service `events` option when registering the service with `app.use`.
46
+ */
47
+ events?: string[];
48
+ /**
49
+ * @deprecated renamed to `operators`.
50
+ */
51
+ whitelist?: string[];
52
+ }
53
+
54
+ export interface AdapterQuery extends Query {
55
+ $limit?: number,
56
+ $skip?: number,
57
+ $select?: string[],
58
+ $sort?: { [key: string]: 1|-1 }
59
+ }
60
+ /**
61
+ * Additional `params` that can be passed to an adapter service method call.
62
+ */
63
+ export interface AdapterParams<Q = AdapterQuery, A extends Partial<AdapterServiceOptions> = Partial<AdapterServiceOptions>> extends Params<Q> {
64
+ adapter?: A;
65
+ paginate?: PaginationParams;
66
+ }
67
+
68
+ /**
69
+ * Hook-less (internal) service methods. Directly call database adapter service methods
70
+ * without running any service-level hooks or sanitization. This can be useful if you need the raw data
71
+ * from the service and don't want to trigger any of its hooks.
72
+ *
73
+ * Important: These methods are only available internally on the server, not on the client
74
+ * side and only for the Feathers database adapters.
75
+ *
76
+ * These methods do not trigger events.
77
+ *
78
+ * @see {@link https://docs.feathersjs.com/guides/migrating.html#hook-less-service-methods}
79
+ */
80
+ export interface InternalServiceMethods<T = any, D = Partial<T>, P extends AdapterParams = AdapterParams> {
81
+ /**
82
+ * Retrieve all resources from this service.
83
+ * Does not sanitize the query and should only be used on the server.
84
+ *
85
+ * @param _params - Service call parameters {@link Params}
86
+ */
87
+ $find(_params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>;
88
+ $find(_params?: P & { paginate: false }): Promise<T[]>;
89
+ $find(params?: P): Promise<T[] | Paginated<T>>;
90
+
91
+ /**
92
+ * Retrieve a single resource matching the given ID, skipping any service-level hooks.
93
+ * Does not sanitize the query and should only be used on the server.
94
+ *
95
+ * @param id - ID of the resource to locate
96
+ * @param params - Service call parameters {@link Params}
97
+ * @see {@link HookLessServiceMethods}
98
+ * @see {@link https://docs.feathersjs.com/api/services.html#get-id-params|Feathers API Documentation: .get(id, params)}
99
+ */
100
+ $get(id: Id, params?: P): Promise<T>;
101
+
102
+ /**
103
+ * Create a new resource for this service, skipping any service-level hooks.
104
+ * Does not sanitize data or checks if multiple updates are allowed and should only be used on the server.
105
+ *
106
+ * @param data - Data to insert into this service.
107
+ * @param params - Service call parameters {@link Params}
108
+ * @see {@link HookLessServiceMethods}
109
+ * @see {@link https://docs.feathersjs.com/api/services.html#create-data-params|Feathers API Documentation: .create(data, params)}
110
+ */
111
+ $create(data: Partial<D>, params?: P): Promise<T>;
112
+ $create(data: Partial<D>[], params?: P): Promise<T[]>;
113
+ $create(data: Partial<D> | Partial<D>[], params?: P): Promise<T | T[]>;
114
+
115
+ /**
116
+ * Completely replace the resource identified by id, skipping any service-level hooks.
117
+ * Does not sanitize data or query and should only be used on the server.
118
+ *
119
+ * @param id - ID of the resource to be updated
120
+ * @param data - Data to be put in place of the current resource.
121
+ * @param params - Service call parameters {@link Params}
122
+ * @see {@link HookLessServiceMethods}
123
+ * @see {@link https://docs.feathersjs.com/api/services.html#update-id-data-params|Feathers API Documentation: .update(id, data, params)}
124
+ */
125
+ $update(id: Id, data: D, params?: P): Promise<T>;
126
+
127
+ /**
128
+ * Merge any resources matching the given ID with the given data, skipping any service-level hooks.
129
+ * Does not sanitize the data or query and should only be used on the server.
130
+ *
131
+ * @param id - ID of the resource to be patched
132
+ * @param data - Data to merge with the current resource.
133
+ * @param params - Service call parameters {@link Params}
134
+ * @see {@link HookLessServiceMethods}
135
+ * @see {@link https://docs.feathersjs.com/api/services.html#patch-id-data-params|Feathers API Documentation: .patch(id, data, params)}
136
+ */
137
+ $patch(id: null, data: Partial<D>, params?: P): Promise<T[]>;
138
+ $patch(id: Id, data: Partial<D>, params?: P): Promise<T>;
139
+ $patch(id: NullableId, data: Partial<D>, params?: P): Promise<T | T[]>;
140
+
141
+ /**
142
+ * Remove resources matching the given ID from the this service, skipping any service-level hooks.
143
+ * Does not sanitize query and should only be used on the server.
144
+ *
145
+ * @param id - ID of the resource to be removed
146
+ * @param params - Service call parameters {@link Params}
147
+ * @see {@link HookLessServiceMethods}
148
+ * @see {@link https://docs.feathersjs.com/api/services.html#remove-id-params|Feathers API Documentation: .remove(id, params)}
149
+ */
150
+ $remove(id: null, params?: P): Promise<T[]>;
151
+ $remove(id: Id, params?: P): Promise<T>;
152
+ $remove(id: NullableId, params?: P): Promise<T | T[]>;
153
+ }
package/src/index.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  import { _ } from '@feathersjs/commons';
2
+ import { Params } from '@feathersjs/feathers';
2
3
 
3
- export { AdapterService, InternalServiceMethods, ServiceOptions, AdapterParams } from './service';
4
- export { filterQuery, FILTERS, OPERATORS } from './filter-query';
4
+ export * from './declarations';
5
+ export * from './service';
6
+ export { filterQuery, FILTERS, OPERATORS } from './query';
5
7
  export * from './sort';
6
8
 
7
9
  // Return a function that filters a result object or array
8
10
  // and picks only the fields passed as `params.query.$select`
9
11
  // and additional `otherFields`
10
- export function select (params: any, ...otherFields: string[]) {
12
+ export function select (params: Params, ...otherFields: string[]) {
11
13
  const queryFields: string[] | undefined = params?.query?.$select;
12
14
 
13
15
  if (!queryFields) {
package/src/query.ts ADDED
@@ -0,0 +1,138 @@
1
+ import { _ } from '@feathersjs/commons';
2
+ import { BadRequest } from '@feathersjs/errors';
3
+ import { Query } from '@feathersjs/feathers';
4
+ import { FilterQueryOptions, FilterSettings } from './declarations';
5
+
6
+ const parse = (value: any) => typeof value !== 'undefined' ? parseInt(value, 10) : value;
7
+
8
+ const isPlainObject = (value: any) => _.isObject(value) && value.constructor === {}.constructor;
9
+
10
+ const validateQueryProperty = (query: any, operators: string[] = []): Query => {
11
+ if (!isPlainObject(query)) {
12
+ return query;
13
+ }
14
+
15
+ for (const key of Object.keys(query)) {
16
+ if (key.startsWith('$') && !operators.includes(key)) {
17
+ throw new BadRequest(`Invalid query parameter ${key}`, query);
18
+ }
19
+
20
+ const value = query[key];
21
+
22
+ if (isPlainObject(value)) {
23
+ query[key] = validateQueryProperty(value, operators);
24
+ }
25
+ }
26
+
27
+ return {
28
+ ...query
29
+ }
30
+ }
31
+
32
+ const getFilters = (query: Query, settings: FilterQueryOptions) => {
33
+ const filterNames = Object.keys(settings.filters);
34
+
35
+ return filterNames.reduce((current, key) => {
36
+ const queryValue = query[key];
37
+ const filter = settings.filters[key];
38
+
39
+ if (filter) {
40
+ const value = typeof filter === 'function' ? filter(queryValue, settings) : queryValue;
41
+
42
+ if (value !== undefined) {
43
+ current[key] = value;
44
+ }
45
+ }
46
+
47
+ return current;
48
+ }, {} as { [key: string]: any });
49
+ }
50
+
51
+ const getQuery = (query: Query, settings: FilterQueryOptions) => {
52
+ const keys = Object.keys(query).concat(Object.getOwnPropertySymbols(query) as any as string[]);
53
+
54
+ return keys.reduce((result, key) => {
55
+ if (typeof key === 'string' && key.startsWith('$')) {
56
+ if (settings.filters[key] === undefined) {
57
+ throw new BadRequest(`Invalid filter value ${key}`);
58
+ }
59
+ } else {
60
+ result[key] = validateQueryProperty(query[key], settings.operators);
61
+ }
62
+
63
+ return result;
64
+ }, {} as Query)
65
+ }
66
+
67
+ export const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or'];
68
+
69
+ export const FILTERS: FilterSettings = {
70
+ $skip: (value: any) => parse(value),
71
+ $sort: (sort: any): { [key: string]: number } => {
72
+ if (typeof sort !== 'object' || Array.isArray(sort)) {
73
+ return sort;
74
+ }
75
+
76
+ return Object.keys(sort).reduce((result, key) => {
77
+ result[key] = typeof sort[key] === 'object'
78
+ ? sort[key] : parse(sort[key]);
79
+
80
+ return result;
81
+ }, {} as { [key: string]: number });
82
+ },
83
+ $limit: (_limit: any, { paginate }: FilterQueryOptions) => {
84
+ const limit = parse(_limit);
85
+
86
+ if (paginate && (paginate.default || paginate.max)) {
87
+ const base = paginate.default || 0;
88
+ const lower = typeof limit === 'number' && !isNaN(limit) && limit >= 0 ? limit : base;
89
+ const upper = typeof paginate.max === 'number' ? paginate.max : Number.MAX_VALUE;
90
+
91
+ return Math.min(lower, upper);
92
+ }
93
+
94
+ return limit;
95
+ },
96
+ $select: (select: any) => {
97
+ if (Array.isArray(select)) {
98
+ return select.map(current => `${current}`);
99
+ }
100
+
101
+ return select;
102
+ },
103
+ $or: (or: any, { operators }: FilterQueryOptions) => {
104
+ if (Array.isArray(or)) {
105
+ return or.map(current => validateQueryProperty(current, operators));
106
+ }
107
+
108
+ return or;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Converts Feathers special query parameters and pagination settings
114
+ * and returns them separately as `filters` and the rest of the query
115
+ * as `query`. `options` also gets passed the pagination settings and
116
+ * a list of additional `operators` to allow when querying properties.
117
+ *
118
+ * @param query The initial query
119
+ * @param options Options for filtering the query
120
+ * @returns An object with `query` which contains the query without `filters`
121
+ * and `filters` which contains the converted values for each filter.
122
+ */
123
+ export function filterQuery (_query: Query, options: FilterQueryOptions = {}) {
124
+ const query = _query || {};
125
+ const settings = {
126
+ ...options,
127
+ filters: {
128
+ ...FILTERS,
129
+ ...options.filters
130
+ },
131
+ operators: OPERATORS.concat(options.operators || [])
132
+ }
133
+
134
+ return {
135
+ filters: getFilters(query, settings),
136
+ query: getQuery(query, settings)
137
+ }
138
+ }