Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(typescript): Improve adapter typings #2605

Merged
merged 1 commit into from
Apr 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions packages/adapter-commons/src/declarations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Query, Params, Paginated, Id, NullableId } from '@feathersjs/feathers';

export type FilterSettings = string[]|{
[key: string]: (value: any, options: any) => any
}

export interface PaginationOptions {
default?: number;
max?: number;
}

export type PaginationParams = false|PaginationOptions;

export type FilterQueryOptions = {
filters?: FilterSettings;
operators?: string[];
paginate?: PaginationParams;
}

export interface AdapterServiceOptions {
events?: string[];
multi?: boolean|string[];
id?: string;
paginate?: PaginationOptions
/**
* @deprecated renamed to `allow`.
*/
whitelist?: string[];
allow?: string[];
filters?: string[];
}

export interface AdapterOptions<M = any> extends Pick<AdapterServiceOptions, 'multi'|'allow'|'paginate'> {
Model?: M;
}

export interface AdapterParams<Q = Query, M = any> extends Params<Q> {
adapter?: Partial<AdapterOptions<M>>;
paginate?: PaginationParams;
}

/**
* Hook-less (internal) service methods. Directly call database adapter service methods
* without running any service-level hooks. This can be useful if you need the raw data
* from the service and don't want to trigger any of its hooks.
*
* Important: These methods are only available internally on the server, not on the client
* side and only for the Feathers database adapters.
*
* These methods do not trigger events.
*
* @see {@link https://docs.feathersjs.com/guides/migrating.html#hook-less-service-methods}
*/
export interface InternalServiceMethods<T = any, D = Partial<T>, P extends AdapterParams = AdapterParams> {
/**
* Retrieve all resources from this service, skipping any service-level hooks.
*
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#find-params|Feathers API Documentation: .find(params)}
*/
_find (_params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>>;
_find (_params?: P & { paginate: false }): Promise<T[]>;
_find (params?: P): Promise<T | T[] | Paginated<T>>;

/**
* Retrieve a single resource matching the given ID, skipping any service-level hooks.
*
* @param id - ID of the resource to locate
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#get-id-params|Feathers API Documentation: .get(id, params)}
*/
_get (id: Id, params?: P): Promise<T>;

/**
* Create a new resource for this service, skipping any service-level hooks.
*
* @param data - Data to insert into this service.
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#create-data-params|Feathers API Documentation: .create(data, params)}
*/
_create (data: Partial<D>, params?: P): Promise<T>;
_create (data: Partial<D>[], params?: P): Promise<T[]>;
_create (data: Partial<D>|Partial<D>[], params?: P): Promise<T|T[]>;

/**
* Replace any resources matching the given ID with the given data, skipping any service-level hooks.
*
* @param id - ID of the resource to be updated
* @param data - Data to be put in place of the current resource.
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#update-id-data-params|Feathers API Documentation: .update(id, data, params)}
*/
_update (id: Id, data: D, params?: P): Promise<T>;

/**
* Merge any resources matching the given ID with the given data, skipping any service-level hooks.
*
* @param id - ID of the resource to be patched
* @param data - Data to merge with the current resource.
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#patch-id-data-params|Feathers API Documentation: .patch(id, data, params)}
*/
_patch (id: null, data: Partial<D>, params?: P): Promise<T[]>;
_patch (id: Id, data: Partial<D>, params?: P): Promise<T>;
_patch (id: NullableId, data: Partial<D>, params?: P): Promise<T|T[]>;

/**
* Remove resources matching the given ID from the this service, skipping any service-level hooks.
*
* @param id - ID of the resource to be removed
* @param params - Service call parameters {@link Params}
* @see {@link HookLessServiceMethods}
* @see {@link https://docs.feathersjs.com/api/services.html#remove-id-params|Feathers API Documentation: .remove(id, params)}
*/
_remove (id: null, params?: P): Promise<T[]>;
_remove (id: Id, params?: P): Promise<T>;
_remove (id: NullableId, params?: P): Promise<T|T[]>;
}
25 changes: 13 additions & 12 deletions packages/adapter-commons/src/filter-query.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { _ } from '@feathersjs/commons';
import { BadRequest } from '@feathersjs/errors';
import { Query } from '@feathersjs/feathers';
import { FilterQueryOptions, FilterSettings } from './declarations';

function parse (number: any) {
if (typeof number !== 'undefined') {
Expand Down Expand Up @@ -37,7 +39,7 @@ function convertSort (sort: any) {
}, {} as { [key: string]: number });
}

function cleanQuery (query: any, operators: any, filters: any): any {
function cleanQuery (query: Query, operators: any, filters: any): any {
if (Array.isArray(query)) {
return query.map(value => cleanQuery(value, operators, filters));
} else if (_.isObject(query) && query.constructor === {}.constructor) {
Expand Down Expand Up @@ -68,7 +70,7 @@ function cleanQuery (query: any, operators: any, filters: any): any {
return query;
}

function assignFilters (object: any, query: any, filters: any, options: any) {
function assignFilters (object: any, query: Query, filters: FilterSettings, options: any): { [key: string]: any } {
if (Array.isArray(filters)) {
_.each(filters, (key) => {
if (query[key] !== undefined) {
Expand All @@ -88,7 +90,7 @@ function assignFilters (object: any, query: any, filters: any, options: any) {
return object;
}

export const FILTERS = {
export const FILTERS: FilterSettings = {
$sort: (value: any) => convertSort(value),
$limit: (value: any, options: any) => getLimit(parse(value), options.paginate),
$skip: (value: any) => parse(value),
Expand All @@ -100,17 +102,16 @@ export const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$
// Converts Feathers special query parameters and pagination settings
// and returns them separately a `filters` and the rest of the query
// as `query`
export function filterQuery (query: any, options: any = {}) {
export function filterQuery (query: Query, options: FilterQueryOptions = {}) {
const {
filters: additionalFilters = {},
filters: additionalFilters = [],
operators: additionalOperators = []
} = options;
const result: { [key: string]: any } = {};
const baseFilters = assignFilters({}, query, FILTERS, options);
const filters = assignFilters(baseFilters, query, additionalFilters, options);

result.filters = assignFilters({}, query, FILTERS, options);
result.filters = assignFilters(result.filters, query, additionalFilters, options);

result.query = cleanQuery(query, OPERATORS.concat(additionalOperators), result.filters);

return result;
return {
filters,
query: cleanQuery(query, OPERATORS.concat(additionalOperators), filters) as Query
}
}
6 changes: 4 additions & 2 deletions packages/adapter-commons/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { _ } from '@feathersjs/commons';
import { Params } from '@feathersjs/feathers';

export { AdapterService, InternalServiceMethods, ServiceOptions, AdapterParams } from './service';
export * from './declarations';
export * from './service';
export { filterQuery, FILTERS, OPERATORS } from './filter-query';
export * from './sort';

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

if (!queryFields) {
Expand Down
Loading