Skip to content

Commit 3b2ca0a

Browse files
authored
feat(typescript): Improve adapter typings (#2605)
1 parent 77d8fda commit 3b2ca0a

16 files changed

Lines changed: 402 additions & 223 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { Query, Params, Paginated, Id, NullableId } from '@feathersjs/feathers';
2+
3+
export type FilterSettings = string[]|{
4+
[key: string]: (value: any, options: any) => any
5+
}
6+
7+
export interface PaginationOptions {
8+
default?: number;
9+
max?: number;
10+
}
11+
12+
export type PaginationParams = false|PaginationOptions;
13+
14+
export type FilterQueryOptions = {
15+
filters?: FilterSettings;
16+
operators?: string[];
17+
paginate?: PaginationParams;
18+
}
19+
20+
export interface AdapterServiceOptions {
21+
events?: string[];
22+
multi?: boolean|string[];
23+
id?: string;
24+
paginate?: PaginationOptions
25+
/**
26+
* @deprecated renamed to `allow`.
27+
*/
28+
whitelist?: string[];
29+
allow?: string[];
30+
filters?: string[];
31+
}
32+
33+
export interface AdapterOptions<M = any> extends Pick<AdapterServiceOptions, 'multi'|'allow'|'paginate'> {
34+
Model?: M;
35+
}
36+
37+
export interface AdapterParams<Q = Query, M = any> extends Params<Q> {
38+
adapter?: Partial<AdapterOptions<M>>;
39+
paginate?: PaginationParams;
40+
}
41+
42+
/**
43+
* Hook-less (internal) service methods. Directly call database adapter service methods
44+
* without running any service-level hooks. This can be useful if you need the raw data
45+
* from the service and don't want to trigger any of its hooks.
46+
*
47+
* Important: These methods are only available internally on the server, not on the client
48+
* side and only for the Feathers database adapters.
49+
*
50+
* These methods do not trigger events.
51+
*
52+
* @see {@link https://docs.feathersjs.com/guides/migrating.html#hook-less-service-methods}
53+
*/
54+
export interface InternalServiceMethods<T = any, D = Partial<T>, P extends AdapterParams = AdapterParams> {
55+
/**
56+
* Retrieve all resources from this service, skipping any service-level hooks.
57+
*
58+
* @param params - Service call parameters {@link Params}
59+
* @see {@link HookLessServiceMethods}
60+
* @see {@link https://docs.feathersjs.com/api/services.html#find-params|Feathers API Documentation: .find(params)}
61+
*/
62+
_find (_params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>;
63+
_find (_params?: P & { paginate: false }): Promise<T[]>;
64+
_find (params?: P): Promise<T | T[] | Paginated<T>>;
65+
66+
/**
67+
* Retrieve a single resource matching the given ID, skipping any service-level hooks.
68+
*
69+
* @param id - ID of the resource to locate
70+
* @param params - Service call parameters {@link Params}
71+
* @see {@link HookLessServiceMethods}
72+
* @see {@link https://docs.feathersjs.com/api/services.html#get-id-params|Feathers API Documentation: .get(id, params)}
73+
*/
74+
_get (id: Id, params?: P): Promise<T>;
75+
76+
/**
77+
* Create a new resource for this service, skipping any service-level hooks.
78+
*
79+
* @param data - Data to insert into this service.
80+
* @param params - Service call parameters {@link Params}
81+
* @see {@link HookLessServiceMethods}
82+
* @see {@link https://docs.feathersjs.com/api/services.html#create-data-params|Feathers API Documentation: .create(data, params)}
83+
*/
84+
_create (data: Partial<D>, params?: P): Promise<T>;
85+
_create (data: Partial<D>[], params?: P): Promise<T[]>;
86+
_create (data: Partial<D>|Partial<D>[], params?: P): Promise<T|T[]>;
87+
88+
/**
89+
* Replace any resources matching the given ID with the given data, skipping any service-level hooks.
90+
*
91+
* @param id - ID of the resource to be updated
92+
* @param data - Data to be put in place of the current resource.
93+
* @param params - Service call parameters {@link Params}
94+
* @see {@link HookLessServiceMethods}
95+
* @see {@link https://docs.feathersjs.com/api/services.html#update-id-data-params|Feathers API Documentation: .update(id, data, params)}
96+
*/
97+
_update (id: Id, data: D, params?: P): Promise<T>;
98+
99+
/**
100+
* Merge any resources matching the given ID with the given data, skipping any service-level hooks.
101+
*
102+
* @param id - ID of the resource to be patched
103+
* @param data - Data to merge with the current resource.
104+
* @param params - Service call parameters {@link Params}
105+
* @see {@link HookLessServiceMethods}
106+
* @see {@link https://docs.feathersjs.com/api/services.html#patch-id-data-params|Feathers API Documentation: .patch(id, data, params)}
107+
*/
108+
_patch (id: null, data: Partial<D>, params?: P): Promise<T[]>;
109+
_patch (id: Id, data: Partial<D>, params?: P): Promise<T>;
110+
_patch (id: NullableId, data: Partial<D>, params?: P): Promise<T|T[]>;
111+
112+
/**
113+
* Remove resources matching the given ID from the this service, skipping any service-level hooks.
114+
*
115+
* @param id - ID of the resource to be removed
116+
* @param params - Service call parameters {@link Params}
117+
* @see {@link HookLessServiceMethods}
118+
* @see {@link https://docs.feathersjs.com/api/services.html#remove-id-params|Feathers API Documentation: .remove(id, params)}
119+
*/
120+
_remove (id: null, params?: P): Promise<T[]>;
121+
_remove (id: Id, params?: P): Promise<T>;
122+
_remove (id: NullableId, params?: P): Promise<T|T[]>;
123+
}

packages/adapter-commons/src/filter-query.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { _ } from '@feathersjs/commons';
22
import { BadRequest } from '@feathersjs/errors';
3+
import { Query } from '@feathersjs/feathers';
4+
import { FilterQueryOptions, FilterSettings } from './declarations';
35

46
function parse (number: any) {
57
if (typeof number !== 'undefined') {
@@ -37,7 +39,7 @@ function convertSort (sort: any) {
3739
}, {} as { [key: string]: number });
3840
}
3941

40-
function cleanQuery (query: any, operators: any, filters: any): any {
42+
function cleanQuery (query: Query, operators: any, filters: any): any {
4143
if (Array.isArray(query)) {
4244
return query.map(value => cleanQuery(value, operators, filters));
4345
} else if (_.isObject(query) && query.constructor === {}.constructor) {
@@ -68,7 +70,7 @@ function cleanQuery (query: any, operators: any, filters: any): any {
6870
return query;
6971
}
7072

71-
function assignFilters (object: any, query: any, filters: any, options: any) {
73+
function assignFilters (object: any, query: Query, filters: FilterSettings, options: any): { [key: string]: any } {
7274
if (Array.isArray(filters)) {
7375
_.each(filters, (key) => {
7476
if (query[key] !== undefined) {
@@ -88,7 +90,7 @@ function assignFilters (object: any, query: any, filters: any, options: any) {
8890
return object;
8991
}
9092

91-
export const FILTERS = {
93+
export const FILTERS: FilterSettings = {
9294
$sort: (value: any) => convertSort(value),
9395
$limit: (value: any, options: any) => getLimit(parse(value), options.paginate),
9496
$skip: (value: any) => parse(value),
@@ -100,17 +102,16 @@ export const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$
100102
// Converts Feathers special query parameters and pagination settings
101103
// and returns them separately a `filters` and the rest of the query
102104
// as `query`
103-
export function filterQuery (query: any, options: any = {}) {
105+
export function filterQuery (query: Query, options: FilterQueryOptions = {}) {
104106
const {
105-
filters: additionalFilters = {},
107+
filters: additionalFilters = [],
106108
operators: additionalOperators = []
107109
} = options;
108-
const result: { [key: string]: any } = {};
110+
const baseFilters = assignFilters({}, query, FILTERS, options);
111+
const filters = assignFilters(baseFilters, query, additionalFilters, options);
109112

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;
113+
return {
114+
filters,
115+
query: cleanQuery(query, OPERATORS.concat(additionalOperators), filters) as Query
116+
}
116117
}

packages/adapter-commons/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { _ } from '@feathersjs/commons';
2+
import { Params } from '@feathersjs/feathers';
23

3-
export { AdapterService, InternalServiceMethods, ServiceOptions, AdapterParams } from './service';
4+
export * from './declarations';
5+
export * from './service';
46
export { filterQuery, FILTERS, OPERATORS } from './filter-query';
57
export * from './sort';
68

79
// Return a function that filters a result object or array
810
// and picks only the fields passed as `params.query.$select`
911
// and additional `otherFields`
10-
export function select (params: any, ...otherFields: string[]) {
12+
export function select (params: Params, ...otherFields: string[]) {
1113
const queryFields: string[] | undefined = params?.query?.$select;
1214

1315
if (!queryFields) {

0 commit comments

Comments
 (0)