UNPKG

@loopback/repository

Version:

Define and implement a common set of interfaces for interacting with databases

377 lines (376 loc) 18.5 kB
import { Application, Binding, BindingFromClassOptions, BindingScope, Component, Constructor, MixinTarget } from '@loopback/core'; import { Class } from '../common-types'; import { SchemaMigrationOptions } from '../datasource'; import { Model } from '../model'; import { juggler, Repository } from '../repositories'; /** * A mixin class for Application that creates a .repository() * function to register a repository automatically. Also overrides * component function to allow it to register repositories automatically. * * @example * ```ts * class MyApplication extends RepositoryMixin(Application) {} * ``` * * Please note: the members in the mixin function are documented in a dummy class * called <a href="#RepositoryMixinDoc">RepositoryMixinDoc</a> * * @param superClass - Application class * @returns A new class that extends the super class with repository related * methods * * @typeParam T - Type of the application class as the target for the mixin * */ export declare function RepositoryMixin<T extends MixinTarget<Application>>(superClass: T): { new (...args: any[]): { /** * Add a repository to this application. * * @param repoClass - The repository to add. * @param nameOrOptions - Name or options for the binding * * @example * ```ts * * class NoteRepo { * model: any; * * constructor() { * const ds: juggler.DataSource = new juggler.DataSource({ * name: 'db', * connector: 'memory', * }); * * this.model = ds.createModel( * 'note', * {title: 'string', content: 'string'}, * {} * ); * } * }; * * app.repository(NoteRepo); * ``` */ repository<R extends Repository<any>>(repoClass: Class<R>, nameOrOptions?: string | BindingFromClassOptions): Binding<R>; /** * Retrieve the repository instance from the given Repository class * * @param repo - The repository class to retrieve the instance of */ getRepository<R_1 extends Repository<any>>(repo: Class<R_1>): Promise<R_1>; /** * Add the dataSource to this application. * * @param dataSource - The dataSource to add. * @param nameOrOptions - The binding name or options of the datasource; * defaults to dataSource.name * * @example * ```ts * * const ds: juggler.DataSource = new juggler.DataSource({ * name: 'db', * connector: 'memory', * }); * * app.dataSource(ds); * * // The datasource can be injected with * constructor(@inject('datasources.db') dataSource: DataSourceType) { * * } * ``` */ dataSource<D extends juggler.DataSource>(dataSource: D | Class<D>, nameOrOptions?: string | BindingFromClassOptions): Binding<D>; /** * Register a model class as a binding in the target context * @param modelClass - Model class */ model<M extends Class<unknown>>(modelClass: M): Binding<M>; /** * Add a component to this application. Also mounts * all the components repositories. * * @param component - The component to add. * @param nameOrOptions - Name or options for the binding. * * @example * ```ts * * export class ProductComponent { * controllers = [ProductController]; * repositories = [ProductRepo, UserRepo]; * providers = { * [AUTHENTICATION_STRATEGY]: AuthStrategy, * [AUTHORIZATION_ROLE]: Role, * }; * }; * * app.component(ProductComponent); * ``` */ component<C extends Component = Component>(componentCtor: Constructor<C>, nameOrOptions?: string | BindingFromClassOptions): Binding<C>; /** * Get an instance of a component and mount all it's * repositories. This function is intended to be used internally * by `component()`. * * NOTE: Calling `mountComponentRepositories` with a component class * constructor is deprecated. You should instantiate the component * yourself and provide the component instance instead. * * @param componentInstanceOrClass - The component to mount repositories of * @internal */ mountComponentRepositories(componentInstanceOrClass: Class<unknown> | RepositoryComponent): void; /** * Bind all model classes provided by a component. * @param component * @internal */ mountComponentModels(component: RepositoryComponent): void; /** * Update or recreate the database schema for all repositories. * * **WARNING**: By default, `migrateSchema()` will attempt to preserve data * while updating the schema in your target database, but this is not * guaranteed to be safe. * * Please check the documentation for your specific connector(s) for * a detailed breakdown of behaviors for automigrate! * * @param options - Migration options, e.g. whether to update tables * preserving data or rebuild everything from scratch. */ migrateSchema(options?: SchemaMigrationOptions): Promise<void>; readonly options: import("@loopback/core").ApplicationConfig; readonly state: string; controller: <T>(controllerCtor: import("@loopback/core").ControllerClass<T>, nameOrOptions?: string | BindingFromClassOptions | undefined) => Binding<T>; server: <T_1 extends import("@loopback/core").Server>(ctor: Constructor<T_1>, nameOrOptions?: string | BindingFromClassOptions | undefined) => Binding<T_1>; servers: <T_2 extends import("@loopback/core").Server>(ctors: Constructor<T_2>[]) => Binding<any>[]; getServer: <T_3 extends import("@loopback/core").Server>(target: string | Constructor<T_3>) => Promise<T_3>; init: () => Promise<void>; onInit: (fn: () => import("@loopback/core").ValueOrPromise<void>) => Binding<import("@loopback/core").LifeCycleObserver>; start: () => Promise<void>; onStart: (fn: () => import("@loopback/core").ValueOrPromise<void>) => Binding<import("@loopback/core").LifeCycleObserver>; stop: () => Promise<void>; onStop: (fn: () => import("@loopback/core").ValueOrPromise<void>) => Binding<import("@loopback/core").LifeCycleObserver>; setMetadata: (metadata: import("@loopback/core").ApplicationMetadata) => void; lifeCycleObserver: <T_4 extends import("@loopback/core").LifeCycleObserver>(ctor: Constructor<T_4>, nameOrOptions?: string | BindingFromClassOptions | undefined) => Binding<T_4>; service: <S>(cls: import("@loopback/core").ServiceOrProviderClass<S>, nameOrOptions?: string | import("@loopback/core").ServiceOptions | undefined) => Binding<S>; interceptor: (interceptor: import("@loopback/core").Interceptor | Constructor<import("@loopback/core").Provider<import("@loopback/core").Interceptor>>, nameOrOptions?: string | import("@loopback/core").InterceptorBindingOptions | undefined) => Binding<import("@loopback/core").Interceptor>; readonly name: string; readonly subscriptionManager: import("@loopback/core").ContextSubscriptionManager; scope: BindingScope; readonly parent: import("@loopback/core").Context | undefined; emitEvent: <T_5 extends import("@loopback/core").ContextEvent>(type: string, event: T_5) => void; emitError: (err: unknown) => void; bind: <ValueType = any>(key: import("@loopback/core").BindingAddress<ValueType>) => Binding<ValueType>; add: (binding: Binding<unknown>) => Application; configure: <ConfigValueType = any>(key?: import("@loopback/core").BindingAddress | undefined) => Binding<ConfigValueType>; getConfigAsValueOrPromise: <ConfigValueType_1>(key: import("@loopback/core").BindingAddress, propertyPath?: string | undefined, resolutionOptions?: import("@loopback/core").ResolutionOptions | undefined) => import("@loopback/core").ValueOrPromise<ConfigValueType_1 | undefined>; getConfig: <ConfigValueType_2>(key: import("@loopback/core").BindingAddress, propertyPath?: string | undefined, resolutionOptions?: import("@loopback/core").ResolutionOptions | undefined) => Promise<ConfigValueType_2 | undefined>; getConfigSync: <ConfigValueType_3>(key: import("@loopback/core").BindingAddress, propertyPath?: string | undefined, resolutionOptions?: import("@loopback/core").ResolutionOptions | undefined) => ConfigValueType_3 | undefined; unbind: (key: import("@loopback/core").BindingAddress) => boolean; subscribe: (observer: import("@loopback/core").ContextEventObserver) => import("@loopback/core").Subscription; unsubscribe: (observer: import("@loopback/core").ContextEventObserver) => boolean; close: () => void; isSubscribed: (observer: import("@loopback/core").ContextObserver) => boolean; createView: <T_6 = unknown>(filter: import("@loopback/core").BindingFilter, comparator?: import("@loopback/core").BindingComparator | undefined, options?: Omit<import("@loopback/core").ResolutionOptions, "session"> | undefined) => import("@loopback/core").ContextView<T_6>; contains: (key: import("@loopback/core").BindingAddress) => boolean; isBound: (key: import("@loopback/core").BindingAddress) => boolean; getOwnerContext: (keyOrBinding: import("@loopback/core").BindingAddress | Readonly<Binding<unknown>>) => import("@loopback/core").Context | undefined; getScopedContext: (scope: BindingScope.APPLICATION | BindingScope.SERVER | BindingScope.REQUEST) => import("@loopback/core").Context | undefined; getResolutionContext: (binding: Readonly<Binding<unknown>>) => import("@loopback/core").Context | undefined; isVisibleTo: (ctx: import("@loopback/core").Context) => boolean; find: <ValueType_1 = any>(pattern?: string | RegExp | import("@loopback/core").BindingFilter | undefined) => Readonly<Binding<ValueType_1>>[]; findByTag: <ValueType_2 = any>(tagFilter: RegExp | import("@loopback/core").BindingTag) => Readonly<Binding<ValueType_2>>[]; get: { <ValueType_3>(keyWithPath: import("@loopback/core").BindingAddress<ValueType_3>, session?: import("@loopback/core").ResolutionSession | undefined): Promise<ValueType_3>; <ValueType_4>(keyWithPath: import("@loopback/core").BindingAddress<ValueType_4>, options: import("@loopback/core").ResolutionOptions): Promise<ValueType_4 | undefined>; }; getSync: { <ValueType_5>(keyWithPath: import("@loopback/core").BindingAddress<ValueType_5>, session?: import("@loopback/core").ResolutionSession | undefined): ValueType_5; <ValueType_6>(keyWithPath: import("@loopback/core").BindingAddress<ValueType_6>, options?: import("@loopback/core").ResolutionOptions | undefined): ValueType_6 | undefined; }; getBinding: { <ValueType_7 = any>(key: import("@loopback/core").BindingAddress<ValueType_7>): Binding<ValueType_7>; <ValueType_8>(key: import("@loopback/core").BindingAddress<ValueType_8>, options?: { optional?: boolean | undefined; } | undefined): Binding<ValueType_8> | undefined; }; findOrCreateBinding: <T_7>(key: import("@loopback/core").BindingAddress<T_7>, policy?: import("@loopback/core").BindingCreationPolicy | undefined) => Binding<T_7>; getValueOrPromise: <ValueType_9>(keyWithPath: import("@loopback/core").BindingAddress<ValueType_9>, optionsOrSession?: import("@loopback/core").ResolutionOptionsOrSession | undefined) => import("@loopback/core").ValueOrPromise<ValueType_9 | undefined>; toJSON: () => import("@loopback/core").JSONObject; inspect: (options?: import("@loopback/core").ContextInspectOptions | undefined) => import("@loopback/core").JSONObject; on: { (eventName: "bind" | "unbind", listener: import("@loopback/core").ContextEventListener): Application; (event: string | symbol, listener: (...args: any[]) => void): Application; }; once: { (eventName: "bind" | "unbind", listener: import("@loopback/core").ContextEventListener): Application; (event: string | symbol, listener: (...args: any[]) => void): Application; }; addListener: (eventName: string | symbol, listener: (...args: any[]) => void) => Application; removeListener: (eventName: string | symbol, listener: (...args: any[]) => void) => Application; off: (eventName: string | symbol, listener: (...args: any[]) => void) => Application; removeAllListeners: (event?: string | symbol | undefined) => Application; setMaxListeners: (n: number) => Application; getMaxListeners: () => number; listeners: (eventName: string | symbol) => Function[]; rawListeners: (eventName: string | symbol) => Function[]; emit: (eventName: string | symbol, ...args: any[]) => boolean; listenerCount: (eventName: string | symbol) => number; prependListener: (eventName: string | symbol, listener: (...args: any[]) => void) => Application; prependOnceListener: (eventName: string | symbol, listener: (...args: any[]) => void) => Application; eventNames: () => (string | symbol)[]; }; } & T; /** * This interface describes additional Component properties * allowing components to contribute Repository-related artifacts. */ export interface RepositoryComponent { /** * An optional list of Repository classes to bind for dependency injection * via `app.repository()` API. */ repositories?: Class<Repository<Model>>[]; /** * An optional list of Model classes to bind for dependency injection * via `app.model()` API. */ models?: Class<Model>[]; } /** * Interface for an Application mixed in with RepositoryMixin */ export interface ApplicationWithRepositories extends Application { repository<R extends Repository<any>>(repo: Class<R>, name?: string): Binding<R>; getRepository<R extends Repository<any>>(repo: Class<R>): Promise<R>; dataSource<D extends juggler.DataSource>(dataSource: Class<D> | D, name?: string): Binding<D>; model<M extends Class<unknown>>(modelClass: M): Binding<M>; component(component: Class<unknown>, name?: string): Binding; mountComponentRepositories(component: Class<unknown>): void; migrateSchema(options?: SchemaMigrationOptions): Promise<void>; } /** * A dummy class created to generate the tsdoc for the members in repository * mixin. Please don't use it. * * The members are implemented in function * <a href="#RepositoryMixin">RepositoryMixin</a> */ export declare class RepositoryMixinDoc { constructor(...args: any[]); /** * Add a repository to this application. * * @param repo - The repository to add. * * @example * ```ts * * class NoteRepo { * model: any; * * constructor() { * const ds: juggler.DataSource = new juggler.DataSource({ * name: 'db', * connector: 'memory', * }); * * this.model = ds.createModel( * 'note', * {title: 'string', content: 'string'}, * {} * ); * } * }; * * app.repository(NoteRepo); * ``` */ repository(repo: Class<Repository<any>>): Binding; /** * Retrieve the repository instance from the given Repository class * * @param repo - The repository class to retrieve the instance of */ getRepository<R extends Repository<any>>(repo: Class<R>): Promise<R>; /** * Add the dataSource to this application. * * @param dataSource - The dataSource to add. * @param name - The binding name of the datasource; defaults to dataSource.name * * @example * ```ts * * const ds: juggler.DataSource = new juggler.DataSource({ * name: 'db', * connector: 'memory', * }); * * app.dataSource(ds); * * // The datasource can be injected with * constructor(@inject('datasources.db') dataSource: DataSourceType) { * * } * ``` */ dataSource(dataSource: Class<juggler.DataSource> | juggler.DataSource, name?: string): Binding; /** * Add a component to this application. Also mounts * all the components repositories. * * @param component - The component to add. * * @example * ```ts * * export class ProductComponent { * controllers = [ProductController]; * repositories = [ProductRepo, UserRepo]; * providers = { * [AUTHENTICATION_STRATEGY]: AuthStrategy, * [AUTHORIZATION_ROLE]: Role, * }; * }; * * app.component(ProductComponent); * ``` */ component(component: Class<{}>): Binding; /** * Get an instance of a component and mount all it's * repositories. This function is intended to be used internally * by component() * * @param component - The component to mount repositories of */ mountComponentRepository(component: Class<{}>): void; /** * Update or recreate the database schema for all repositories. * * **WARNING**: By default, `migrateSchema()` will attempt to preserve data * while updating the schema in your target database, but this is not * guaranteed to be safe. * * Please check the documentation for your specific connector(s) for * a detailed breakdown of behaviors for automigrate! * * @param options - Migration options, e.g. whether to update tables * preserving data or rebuild everything from scratch. */ migrateSchema(options?: SchemaMigrationOptions): Promise<void>; } /** * Create a binding for the given model class * @param modelClass - Model class */ export declare function createModelClassBinding<M extends Class<unknown>>(modelClass: M): Binding<M>;