import { EventEmitter } from 'events'; import { NextFunction, HookContext as BaseHookContext } from '@feathersjs/hooks'; type SelfOrArray = S | S[]; type OptionalPick = Pick>; type Entries = { [K in keyof T]: [K, T[K]]; }[keyof T][]; type GetKeyByValue = Extract[number], [PropertyKey, Value]>[0]; export type { NextFunction }; /** * The object returned from `.find` call by standard database adapters */ export interface Paginated { total: number; limit: number; skip: number; data: T[]; } /** * Options that can be passed when registering a service via `app.use(name, service, options)` */ export interface ServiceOptions { /** * A list of custom events that this service emits to clients */ events?: string[] | readonly string[]; /** * A list of service methods that should be available __externally__ to clients */ methods?: MethodTypes[] | readonly MethodTypes[]; /** * Provide a full list of events that this service should emit to clients. * Unlike the `events` option, this will not be merged with the default events. */ serviceEvents?: string[] | readonly string[]; /** * Initial data to always add as route params to this service. */ routeParams?: { [key: string]: any; }; } export interface ClientService, PatchData = Data, FindResult = Paginated, P = Params> { find(params?: P): Promise; get(id: Id, params?: P): Promise; create(data: Data[], params?: P): Promise; create(data: Data, params?: P): Promise; update(id: Id, data: Data, params?: P): Promise; update(id: NullableId, data: Data, params?: P): Promise; update(id: null, data: Data, params?: P): Promise; patch(id: NullableId, data: PatchData, params?: P): Promise; patch(id: Id, data: PatchData, params?: P): Promise; patch(id: null, data: PatchData, params?: P): Promise; remove(id: NullableId, params?: P): Promise; remove(id: Id, params?: P): Promise; remove(id: null, params?: P): Promise; } export interface ServiceMethods, ServiceParams = Params, PatchData = Partial> { find(params?: ServiceParams & { paginate?: PaginationParams; }): Promise; get(id: Id, params?: ServiceParams): Promise; create(data: Data, params?: ServiceParams): Promise; update(id: NullableId, data: Data, params?: ServiceParams): Promise; patch(id: NullableId, data: PatchData, params?: ServiceParams): Promise; remove(id: NullableId, params?: ServiceParams): Promise; setup?(app: Application, path: string): Promise; teardown?(app: Application, path: string): Promise; } export interface ServiceOverloads, ServiceParams = Params, PatchData = Partial> { create?(data: Data[], params?: ServiceParams): Promise; update?(id: Id, data: Data, params?: ServiceParams): Promise; update?(id: null, data: Data, params?: ServiceParams): Promise; patch?(id: Id, data: PatchData, params?: ServiceParams): Promise; patch?(id: null, data: PatchData, params?: ServiceParams): Promise; remove?(id: Id, params?: ServiceParams): Promise; remove?(id: null, params?: ServiceParams): Promise; } /** * A complete service interface. The `ServiceInterface` type should be preferred for customs service * implementations */ export type Service, ServiceParams = Params, PatchData = Partial> = ServiceMethods & ServiceOverloads; /** * The `Service` service interface but with none of the methods required. */ export type ServiceInterface, ServiceParams = Params, PatchData = Partial> = Partial>; export interface ServiceAddons extends EventEmitter { id?: string; hooks(options: HookOptions): this; } export interface ServiceHookOverloads { find(params: P & { paginate?: PaginationParams; }, context: HookContext): Promise; get(id: Id, params: P, context: HookContext): Promise; create(data: ServiceGenericData | ServiceGenericData[], params: P, context: HookContext): Promise; update(id: NullableId, data: ServiceGenericData, params: P, context: HookContext): Promise; patch(id: NullableId, data: ServiceGenericData, params: P, context: HookContext): Promise; remove(id: NullableId, params: P, context: HookContext): Promise; } export type FeathersService = S & ServiceAddons & OptionalPick, keyof S>; export type CustomMethods = { [K in keyof T]: (data: T[K][0], params?: Params) => Promise; }; /** * An interface usually use by transport clients that represents a e.g. HTTP or websocket * connection that can be configured on the application. */ export type TransportConnection = { (app: Application): void; Service: any; service: (name: L) => keyof any extends keyof Services ? ServiceInterface : Services[L]; }; /** * A real-time connection object */ export interface RealTimeConnection { [key: string]: any; } /** * The interface for a custom service method. Can e.g. be used to type client side services. */ export type CustomMethod = (data: T, params?: P) => Promise; export type ServiceMixin = (service: FeathersService, path: string, options: ServiceOptions) => void; export type ServiceGenericType = S extends ServiceInterface ? T : any; export type ServiceGenericData = S extends ServiceInterface ? D : any; export type ServiceGenericParams = S extends ServiceInterface ? P : any; export interface FeathersApplication { /** * The Feathers application version */ version: string; /** * A list of callbacks that run when a new service is registered */ mixins: ServiceMixin>[]; /** * The index of all services keyed by their path. * * __Important:__ Services should always be retrieved via `app.service('name')` * not via `app.services`. */ services: Services; /** * The application settings that can be used via * `app.get` and `app.set` */ settings: Settings; /** * A private-ish indicator if `app.setup()` has been called already */ _isSetup: boolean; /** * Retrieve an application setting by name * * @param name The setting name */ get(name: L): Settings[L]; /** * Set an application setting * * @param name The setting name * @param value The setting value */ set(name: L, value: Settings[L]): this; /** * Runs a callback configure function with the current application instance. * * @param callback The callback `(app: Application) => {}` to run */ configure(callback: (this: this, app: this) => void): this; /** * Returns a fallback service instance that will be registered * when no service was found. Usually throws a `NotFound` error * but also used to instantiate client side services. * * @param location The path of the service */ defaultService(location: string): ServiceInterface; /** * Register a new service or a sub-app. When passed another * Feathers application, all its services will be re-registered * with the `path` prefix. * * @param path The path for the service to register * @param service The service object to register or another * Feathers application to use a sub-app under the `path` prefix. * @param options The options for this service */ use(path: L, service: keyof any extends keyof Services ? ServiceInterface | Application : Services[L], options?: ServiceOptions): this; /** * Unregister an existing service. * * @param path The name of the service to unregister */ unuse(path: L): Promise>; /** * Get the Feathers service instance for a path. This will * be the service originally registered with Feathers functionality * like hooks and events added. * * @param path The name of the service. */ service(path: L): FeathersService; /** * Set up the application and call all services `.setup` method if available. * * @param server A server instance (optional) */ setup(server?: any): Promise; /** * Tear down the application and call all services `.teardown` method if available. * * @param server A server instance (optional) */ teardown(server?: any): Promise; /** * Register application level hooks. * * @param map The application hook settings. */ hooks(map: ApplicationHookOptions): this; } export interface Application extends FeathersApplication, EventEmitter { } export type Id = number | string; export type NullableId = Id | null; export interface Query { [key: string]: any; } export interface Params { query?: Q; provider?: string; route?: { [key: string]: any; }; headers?: { [key: string]: any; }; } export interface PaginationOptions { default?: number; max?: number; } export type PaginationParams = false | PaginationOptions; export interface Http { /** * A writeable, optional property with status code override. */ status?: number; /** * A writeable, optional property with headers. */ headers?: { [key: string]: string | string[]; }; /** * A writeable, optional property with `Location` header's value. */ location?: string; } export type HookType = 'before' | 'after' | 'error' | 'around'; type Serv = FA extends Application ? S : never; export interface HookContext extends BaseHookContext> { /** * A read only property that contains the Feathers application object. This can be used to * retrieve other services (via context.app.service('name')) or configuration values. */ readonly app: A; /** * A read only property with the name of the service method (one of find, get, * create, update, patch, remove). */ readonly method: string; /** * A read only property and contains the service name (or path) without leading or * trailing slashes. */ path: 0 extends 1 & S ? keyof Serv & string : GetKeyByValue, S> & string; /** * A read only property and contains the service this hook currently runs on. */ readonly service: S; /** * A read only property with the hook type (one of 'around', 'before', 'after' or 'error'). */ readonly type: HookType; /** * The list of method arguments. Should not be modified, modify the * `params`, `data` and `id` properties instead. */ readonly arguments: any[]; /** * A writeable property containing the data of a create, update and patch service * method call. */ data?: ServiceGenericData; /** * A writeable property with the error object that was thrown in a failed method call. * It is only available in error hooks. */ error?: any; /** * A writeable property and the id for a get, remove, update and patch service * method call. For remove, update and patch context.id can also be null when * modifying multiple entries. In all other cases it will be undefined. */ id?: Id; /** * A writeable property that contains the service method parameters (including * params.query). */ params: ServiceGenericParams; /** * A writeable property containing the result of the successful service method call. * It is only available in after hooks. * * `context.result` can also be set in * * - A before hook to skip the actual service method (database) call * - An error hook to swallow the error and return a result instead */ result?: ServiceGenericType; /** * A writeable, optional property and contains a 'safe' version of the data that * should be sent to any client. If context.dispatch has not been set context.result * will be sent to the client instead. */ dispatch?: ServiceGenericType; /** * A writeable, optional property that allows to override the standard HTTP status * code that should be returned. * * @deprecated Use `http.status` instead. */ statusCode?: number; /** * A writeable, optional property with options specific to HTTP transports. */ http?: Http; /** * The event emitted by this method. Can be set to `null` to skip event emitting. */ event: string | null; } export type HookFunction = (this: S, context: HookContext) => Promise | void> | HookContext | void; export type Hook = HookFunction; type HookMethodMap = { [L in keyof S]?: SelfOrArray>; } & { all?: SelfOrArray>; }; type HookTypeMap = SelfOrArray> | HookMethodMap; export type AroundHookFunction = (context: HookContext, next: NextFunction) => Promise; export type AroundHookMap = { [L in keyof S]?: AroundHookFunction[]; } & { all?: AroundHookFunction[]; }; export type HookMap = { around?: AroundHookMap; before?: HookTypeMap; after?: HookTypeMap; error?: HookTypeMap; }; export type HookOptions = AroundHookMap | AroundHookFunction[] | HookMap; export interface ApplicationHookContext extends BaseHookContext { app: A; server: any; } export type ApplicationHookFunction = (context: ApplicationHookContext, next: NextFunction) => Promise; export type ApplicationHookMap = { setup?: ApplicationHookFunction[]; teardown?: ApplicationHookFunction[]; }; export type ApplicationHookOptions = HookOptions | ApplicationHookMap;