@loopback/repository
Version:
Define and implement a common set of interfaces for interacting with databases
377 lines (376 loc) • 18.5 kB
TypeScript
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>;