Add typescript type definitions

This commit is contained in:
Raymond Feng 2018-05-02 16:21:49 -07:00
parent cc99cd8f0f
commit 77a2c9ab3b
19 changed files with 3017 additions and 3 deletions

2
.gitignore vendored
View File

@ -13,5 +13,5 @@ npm-debug.log
.project
test/memory.json
.nyc_output
dist

View File

@ -11,4 +11,5 @@ docs/html
npm-debug.log
.travis.yml
.nyc_output
dist

36
index.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// Type definitions for loopback-datasource-juggler 3.x
// Project: https://github.com/strongloop/loopback-datasource-juggler
// Definitions by: Raymond Feng <https://github.com/raymondfeng>
// TypeScript Version: 2.8
/**
* Experimental TypeScript definitions to capture types of the key artifacts
* from `loopback-datasource-juggler` module. One of the main purposes is to
* leverage such types in `LoopBack 4`'s bridge to juggler.
*
* Please note some of the classes, properties, methods, and functions are
* intentionally not included in the definitions because of one of the following
* factors:
*
* - They are internal
* - They are to be deprecated
*/
export * from './types/common';
export * from './types/model';
export * from './types/relation';
export * from './types/query';
export * from './types/datasource';
export * from './types/kv-model';
export * from './types/persisted-model';
export * from './types/scope';
export * from './types/transaction-mixin';
export * from './types/relation-mixin';
export * from './types/observer-mixin';
export * from './types/validation-mixin';
export * from './types/inclusion-mixin';
export * from './types/connector';

View File

@ -22,14 +22,16 @@
"url": "https://github.com/strongloop/loopback-datasource-juggler"
},
"main": "index.js",
"types": "index.d.ts",
"browser": {
"depd": "./lib/browser.depd.js"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint .",
"tsc": "tsc -p tsconfig.json --outDir dist",
"test": "nyc mocha",
"posttest": "npm run lint"
"posttest": "npm run tsc && npm run lint"
},
"devDependencies": {
"async-iterators": "^0.2.2",
@ -40,9 +42,11 @@
"loopback-connector-throwing": "file:./test/fixtures/loopback-connector-throwing",
"mocha": "^3.2.0",
"nyc": "^11.1.0",
"should": "^8.4.0"
"should": "^8.4.0",
"typescript": "^2.8.3"
},
"dependencies": {
"@types/node": "^10.0.3",
"async": "~2.1.4",
"bluebird": "^3.1.1",
"debug": "^3.1.0",

18
tsconfig.json Normal file
View File

@ -0,0 +1,18 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noImplicitAny": true,
"strictNullChecks": true,
"lib": ["es2018", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"target": "es2017",
"sourceMap": true,
"declaration": true
},
"include": ["types/", "index.d.ts"],
"exclude": ["node_modules/**"]
}

28
types/common.d.ts vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
/**
* Objects with open properties
*/
export interface AnyObject<T = any> {
[property: string]: T;
}
/**
* Type alias for options object
*/
export type Options = AnyObject<any>;
/**
* Type alias for Node.js callback functions
*/
export type Callback<T = any> = (err: any, result?: T) => void;
/**
* Return export type for promisified Node.js async methods.
*
* Note that juggler uses Bluebird, not the native Promise.
*/
export type PromiseOrVoid<T = any> = PromiseLike<T> | void;

46
types/connector.d.ts vendored Normal file
View File

@ -0,0 +1,46 @@
import {Callback, DataSource, Options, PromiseOrVoid} from '..';
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
/**
* Connector from `loopback-connector` module
*/
export interface Connector {
name: string; // Name/type of the connector
dataSource?: DataSource;
connect(callback?: Callback): PromiseOrVoid; // Connect to the underlying system
disconnect(callback?: Callback): PromiseOrVoid; // Disconnect from the underlying system
ping(callback?: Callback): PromiseOrVoid; // Ping the underlying system
execute?(...args: any[]): Promise<any>;
}
/**
* Base connector class
*/
export declare class ConnectorBase implements Connector {
name: string; // Name/type of the connector;
dataSource?: DataSource;
connect(callback?: Callback): PromiseOrVoid; // Connect to the underlying system
disconnect(callback?: Callback): PromiseOrVoid; // Disconnect from the underlying system
ping(callback?: Callback): PromiseOrVoid; // Ping the underlying system
execute?(...args: any[]): Promise<any>;
/**
* Initialize the connector against the given data source
*
* @param {DataSource} dataSource The dataSource
* @param {Function} [callback] The callback function
*/
static initialize(dataSource: DataSource, callback?: Callback): void;
constructor(settings?: Options);
}
export declare class Memory extends ConnectorBase {}
export declare class KeyValueMemoryConnector extends ConnectorBase {}
export declare class Transient extends ConnectorBase {}

177
types/datasource.d.ts vendored Normal file
View File

@ -0,0 +1,177 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {AnyObject, Callback, Options, PromiseOrVoid} from './common';
import {Connector} from './connector';
import {
ModelBaseClass,
ModelBuilder,
ModelDefinition,
PropertyDefinition,
} from './model';
/**
* LoopBack models can manipulate data via the DataSource object.
* Attaching a `DataSource` to a `Model` adds instance methods and static methods to the `Model`.
*
* Define a data source to persist model data.
* To create a DataSource programmatically, call `createDataSource()` on the LoopBack object; for example:
* ```js
* var oracle = loopback.createDataSource({
* connector: 'oracle',
* host: '111.22.333.44',
* database: 'MYDB',
* username: 'username',
* password: 'password'
* });
* ```
*
* All classes in single dataSource share same the connector type and
* one database connection.
*
* For example, the following creates a DataSource, and waits for a connection callback.
*
* ```
* var dataSource = new DataSource('mysql', { database: 'myapp_test' });
* dataSource.define(...);
* dataSource.on('connected', function () {
* // work with database
* });
* ```
* @class DataSource
* @param {String} [name] Optional name for datasource.
* @options {Object} settings Database-specific settings to establish connection (settings depend on specific connector).
* The table below lists a typical set for a relational database.
* @property {String} connector Database connector to use. For any supported connector, can be any of:
*
* - The connector module from `require(connectorName)`.
* - The full name of the connector module, such as 'loopback-connector-oracle'.
* - The short name of the connector module, such as 'oracle'.
* - A local module under `./connectors/` folder.
* @property {String} host Database server host name.
* @property {String} port Database server port number.
* @property {String} username Database user name.
* @property {String} password Database password.
* @property {String} database Name of the database to use.
* @property {Boolean} debug Display debugging information. Default is false.
*
* The constructor allows the following styles:
*
* 1. new DataSource(dataSourceName, settings). For example:
* - new DataSource('myDataSource', {connector: 'memory'});
* - new DataSource('myDataSource', {name: 'myDataSource', connector: 'memory'});
* - new DataSource('myDataSource', {name: 'anotherDataSource', connector: 'memory'});
*
* 2. new DataSource(settings). For example:
* - new DataSource({name: 'myDataSource', connector: 'memory'});
* - new DataSource({connector: 'memory'});
*
* 3. new DataSource(connectorModule, settings). For example:
* - new DataSource(connectorModule, {name: 'myDataSource})
* - new DataSource(connectorModule)
*/
export declare class DataSource {
name: string;
settings: Options;
connected?: boolean;
connecting?: boolean;
connector?: Connector;
DataAccessObject: AnyObject & {prototype: AnyObject};
constructor(name?: string, settings?: Options, modelBuilder?: ModelBuilder);
constructor(
connectorModule: Connector,
settings?: Options,
modelBuilder?: ModelBuilder,
);
/**
* Create a model class
* @param name Name of the model
* @param properties An object of property definitions
* @param options Options for model settings
*/
createModel<T extends ModelBaseClass>(
name: string,
properties?: AnyObject,
options?: Options,
): T;
getModel(modelName: string): ModelBaseClass | undefined;
/**
* Attach an existing model to a data source.
* This will mixin all of the data access object functions (DAO) into your
* modelClass definition.
* @param {ModelBaseClass} modelClass The model constructor that will be enhanced
* by DataAccessObject mixins.
*/
attach(modelClass: ModelBaseClass): ModelBaseClass;
automigrate(models: string | string[], callback?: Callback): PromiseOrVoid;
autoupdate(models: string | string[], callback?: Callback): PromiseOrVoid;
discoverModelDefinitions(
options?: Options,
callback?: Callback<ModelDefinition[]>,
): PromiseOrVoid<ModelDefinition[]>;
discoverModelProperties(
modelName: string,
options?: Options,
callback?: Callback<PropertyDefinition[]>,
): PromiseOrVoid<PropertyDefinition[]>;
discoverPrimaryKeys(
modelName: string,
options?: Options,
callback?: Callback<PropertyDefinition[]>,
): PromiseOrVoid<PropertyDefinition[]>;
discoverForeignKeys(
modelName: string,
options?: Options,
callback?: Callback<PropertyDefinition[]>,
): PromiseOrVoid<PropertyDefinition[]>;
discoverExportedForeignKeys(
modelName: string,
options?: Options,
callback?: Callback<PropertyDefinition[]>,
): PromiseOrVoid<PropertyDefinition[]>;
discoverAndBuildModels(
modelName: string,
options?: Options,
callback?: Callback<{[name: string]: ModelBaseClass}>,
): PromiseOrVoid<{[name: string]: ModelBaseClass}>;
discoverSchema(
tableName: string,
options?: Options,
callback?: Callback<AnyObject>,
): PromiseOrVoid<AnyObject>;
discoverSchemas(
tableName: string,
options?: Options,
callback?: Callback<AnyObject[]>,
): PromiseOrVoid<AnyObject[]>;
buildModelFromInstance(
modelName: string,
jsonObject: AnyObject,
options?: Options,
): ModelBaseClass;
connect(callback?: Callback): PromiseOrVoid;
disconnect(callback?: Callback): PromiseOrVoid;
ping(callback?: Callback): PromiseOrVoid;
}

44
types/inclusion-mixin.d.ts vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {PersistedData, PersistedModel} from '..';
import {Callback, Options, PromiseOrVoid} from './common';
import {Inclusion} from './query';
/**
* Inclusion mixin
*/
export interface InclusionMixin {
/**
* Enables you to load relations of several objects and optimize numbers of requests.
*
* Examples:
*
* Load all users' posts with only one additional request:
* `User.include(users, 'posts', function() {});`
* Or
* `User.include(users, ['posts'], function() {});`
*
* Load all users posts and passports with two additional requests:
* `User.include(users, ['posts', 'passports'], function() {});`
*
* Load all passports owner (users), and all posts of each owner loaded:
*```Passport.include(passports, {owner: 'posts'}, function() {});
*``` Passport.include(passports, {owner: ['posts', 'passports']});
*``` Passport.include(passports, {owner: [{posts: 'images'}, 'passports']});
*
* @param {Array} objects Array of instances
* @param {String|Object|Array} include Which relations to load.
* @param {Object} [options] Options for CRUD
* @param {Function} cb Callback called when relations are loaded
*
*/
include<T extends PersistedModel>(
objects: PersistedData<T>[],
include: Inclusion,
options?: Options,
callback?: Callback<PersistedData<T>[]>,
): PromiseOrVoid<PersistedData<T>[]>;
}

168
types/kv-model.d.ts vendored Normal file
View File

@ -0,0 +1,168 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Callback, Options, PromiseOrVoid} from './common';
import {ModelBase, ModelData} from './model';
import {Filter} from './query';
/**
* Data object for KV models
*/
export type KVData = ModelData<KeyValueModel>;
/**
* Key/Value model
*/
export declare class KeyValueModel extends ModelBase {
/**
* Return the value associated with a given key.
*
* @param {String} key Key to use when searching the database.
* @options {Object} options
* @callback {Function} callback
* @param {Error} err Error object.
* @param {Any} result Value associated with the given key.
* @promise
*
* @header KeyValueModel.get(key, cb)
*/
get(
key: string,
options?: Options,
callback?: Callback<KVData>,
): PromiseOrVoid<KVData>;
/**
* Persist a value and associate it with the given key.
*
* @param {String} key Key to associate with the given value.
* @param {Any} value Value to persist.
* @options {Number|Object} options Optional settings for the key-value
* pair. If a Number is provided, it is set as the TTL (time to live) in ms
* (milliseconds) for the key-value pair.
* @property {Number} ttl TTL for the key-value pair in ms.
* @callback {Function} callback
* @param {Error} err Error object.
* @promise
*
* @header KeyValueModel.set(key, value, cb)
*/
set(
key: string,
value: KVData,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Set the TTL (time to live) in ms (milliseconds) for a given key. TTL is the
* remaining time before a key-value pair is discarded from the database.
*
* @param {String} key Key to use when searching the database.
* @param {Number} ttl TTL in ms to set for the key.
* @options {Object} options
* @callback {Function} callback
* @param {Error} err Error object.
* @promise
*
* @header KeyValueModel.expire(key, ttl, cb)
*/
expire(
key: string,
ttl: number,
options?: Options,
callback?: Callback<number>,
): PromiseOrVoid<number>;
/**
* Return the TTL (time to live) for a given key. TTL is the remaining time
* before a key-value pair is discarded from the database.
*
* @param {String} key Key to use when searching the database.
* @options {Object} options
* @callback {Function} callback
* @param {Error} error
* @param {Number} ttl Expiration time for the key-value pair. `undefined` if
* TTL was not initially set.
* @promise
*
* @header KeyValueModel.ttl(key, cb)
*/
ttl(
key: string,
options?: Options,
callback?: Callback<number>,
): PromiseOrVoid<number>;
/**
* Return all keys in the database.
*
* **WARNING**: This method is not suitable for large data sets as all
* key-values pairs are loaded into memory at once. For large data sets,
* use `iterateKeys()` instead.
*
* @param {Object} filter An optional filter object with the following
* @param {String} filter.match Glob string used to filter returned
* keys (i.e. `userid.*`). All connectors are required to support `*` and
* `?`, but may also support additional special characters specific to the
* database.
* @param {Object} options
* @callback {Function} callback
* @promise
*
* @header KeyValueModel.keys(filter, cb)
*/
keys(
filter?: Filter,
options?: Options,
callback?: Callback<string[]>,
): PromiseOrVoid<string[]>;
/**
* Asynchronously iterate all keys in the database. Similar to `.keys()` but
* instead allows for iteration over large data sets without having to load
* everything into memory at once.
*
* Callback example:
* ```js
* // Given a model named `Color` with two keys `red` and `blue`
* var iterator = Color.iterateKeys();
* it.next(function(err, key) {
* // key contains `red`
* it.next(function(err, key) {
* // key contains `blue`
* });
* });
* ```
*
* Promise example:
* ```js
* // Given a model named `Color` with two keys `red` and `blue`
* var iterator = Color.iterateKeys();
* Promise.resolve().then(function() {
* return it.next();
* })
* .then(function(key) {
* // key contains `red`
* return it.next();
* });
* .then(function(key) {
* // key contains `blue`
* });
* ```
*
* @param {Object} filter An optional filter object with the following
* @param {String} filter.match Glob string to use to filter returned
* keys (i.e. `userid.*`). All connectors are required to support `*` and
* `?`. They may also support additional special characters that are
* specific to the backing database.
* @param {Object} options
* @returns {AsyncIterator} An Object implementing `next(cb) -> Promise`
* function that can be used to iterate all keys.
*
* @header KeyValueModel.iterateKeys(filter)
*/
iterateKeys(filter?: Filter, options?: Options): Iterator<Promise<string>>;
}

253
types/model.d.ts vendored Normal file
View File

@ -0,0 +1,253 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
/// <reference types="node" />
import {EventEmitter} from 'events';
import {AnyObject, Options} from './common';
import {DataSource} from './datasource';
/**
* Property types
*/
export type PropertyType =
| string
| Function
| {[property: string]: PropertyType};
/**
* Property definition
*/
export interface PropertyDefinition extends AnyObject {
name: string;
type?: PropertyType;
}
/**
* Schema definition
*/
export interface Schema {
name: string;
properties: {[property: string]: PropertyDefinition};
settings?: AnyObject;
}
/**
* ID definition
*/
export interface IdDefinition {
name: string;
id: number;
property: AnyObject;
}
/**
* Index definition
*/
export interface IndexDefinition extends AnyObject {}
/**
* Column metadata
*/
export interface ColumnMetadata extends AnyObject {
name: string;
}
/**
* Model definition
*/
export declare class ModelDefinition extends EventEmitter implements Schema {
name: string;
properties: AnyObject;
rawProperties: AnyObject;
settings?: AnyObject;
relations?: AnyObject[];
constructor(
modelBuilder: ModelBuilder | null | undefined,
name: string,
properties?: {[name: string]: PropertyDefinition},
settings?: AnyObject,
);
constructor(modelBuilder: ModelBuilder | null | undefined, schema: Schema);
tableName(connectorType: string): string;
columnName(connectorType: string, propertyName: string): string;
columnNames(connectorType: string): string[];
columnMetadata(connectorType: string, propertyName: string): ColumnMetadata;
ids(): IdDefinition[];
idName(): string;
idNames(): string[];
defineProperty(
propertyName: string,
propertyDefinition: PropertyDefinition,
): void;
indexes(): {[name: string]: IndexDefinition};
build(forceRebuild?: boolean): AnyObject;
toJSON(forceRebuild?: boolean): AnyObject;
}
/**
* Base model class
*/
export declare class ModelBase {
static dataSource?: DataSource;
static modelName: string;
static definition: ModelDefinition;
/**
* Attach the model class to a data source
* @param ds The data source
*/
static attachTo(ds: DataSource): void;
/**
* Get model property type.
* @param {string} propName Property name
* @returns {string} Name of property type
*/
static getPropertyType(propName: string): string | null;
/**
* Checks if property is hidden.
* @param {string} propertyName Property name
* @returns {Boolean} true or false if hidden or not.
*/
static isHiddenProperty(propertyName: string): boolean;
/**
* Checks if property is protected.
* @param {string} propertyName Property name
* @returns {Boolean} true or false if protected or not.
*/
static isProtectedProperty(propertyName: string): boolean;
/**
* Gets properties defined with 'updateOnly' flag set to true from the model.
* This flag is also set to true internally for the id property, if this
* property is generated and IdInjection is true.
* @returns {updateOnlyProps} List of properties with updateOnly set to true.
*/
static getUpdateOnlyProperties(): string[];
/**
* Model class: base class for all persistent objects.
*
* `ModelBaseClass` mixes `Validatable` and `Hookable` classes methods
*
* @class
* @param {AnyObject} data Initial object data
* @param {Options} options An object to control the instantiation
*/
constructor(data: AnyObject, options?: Options);
/**
* Convert the model instance to a plain json object
*/
toJSON(): AnyObject;
/**
* Populate properties from a JSON object
* @param obj The source object
*/
fromObject(obj: AnyObject): void;
/**
* Convert model instance to a plain JSON object.
* Returns a canonical object representation (no getters and setters).
*
* @param {boolean} onlySchema Restrict properties to dataSource only.
* Default is false. If true, the function returns only properties defined
* in the schema; Otherwise it returns all enumerable properties.
* @param {boolean} removeHidden Boolean flag as part of the transformation.
* If true, then hidden properties should not be brought out.
* @param {boolean} removeProtected Boolean flag as part of the transformation.
* If true, then protected properties should not be brought out.
* @returns {object} returns Plain JSON object
*/
toObject(
onlySchema?: boolean,
removeHidden?: boolean,
removeProtected?: boolean,
): AnyObject;
/**
* Define a property on the model.
* @param {string} prop Property name
* @param definition Various property configuration
*/
defineProperty(
propertyName: string,
definition: Partial<PropertyDefinition>,
): void;
getDataSource(): DataSource;
/**
*
* @param {string} anotherClass could be string or class. Name of the class
* or the class itself
* @param {Object} options An object to control the instantiation
* @returns {ModelClass}
*/
static mixin(
anotherClass: string | ModelBaseClass | object,
options?: Options,
): ModelBaseClass;
}
export type ModelBaseClass = typeof ModelBase;
export declare class ModelBuilder extends EventEmitter {
static defaultInstance: ModelBuilder;
models: {[name: string]: ModelBaseClass};
definitions: {[name: string]: ModelDefinition};
settings: AnyObject;
getModel(name: string, forceCreate?: boolean): ModelBaseClass;
getModelDefinition(name: string): ModelDefinition | undefined;
define(
className: string,
properties?: AnyObject,
settings?: AnyObject,
parent?: ModelBaseClass,
): ModelBaseClass;
defineProperty(
modelName: string,
propertyName: string,
propertyDefinition: AnyObject,
): void;
defineValueType(type: string, aliases?: string[]): void;
extendModel(modelName: string, properties: AnyObject): void;
getSchemaName(name?: string): string;
resolveType(type: any): any;
buildModels(
schemas: AnyObject,
createModel?: Function,
): {[name: string]: ModelBaseClass};
buildModelFromInstance(
name: string,
json: AnyObject,
options: Options,
): ModelBaseClass;
}
/**
* Union export type for model instance or plain object representing the model
* instance
*/
export type ModelData<T extends ModelBase = ModelBase> = T | AnyObject;

157
types/observer-mixin.d.ts vendored Normal file
View File

@ -0,0 +1,157 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Callback, PromiseOrVoid} from './common';
export type Listener = (ctx: object, next: (err?: any) => void) => void;
export interface ObserverMixin {
/**
* Register an asynchronous observer for the given operation (event).
*
* Example:
*
* Registers a `before save` observer for a given model.
*
* ```javascript
* MyModel.observe('before save', function filterProperties(ctx, next) {
* if (ctx.options && ctx.options.skipPropertyFilter) return next();
* if (ctx.instance) {
* FILTERED_PROPERTIES.forEach(function(p) {
* ctx.instance.unsetAttribute(p);
* });
* } else {
* FILTERED_PROPERTIES.forEach(function(p) {
* delete ctx.data[p];
* });
* }
* next();
* });
* ```
*
* @param {String} operation The operation name.
* @callback {function} listener The listener function. It will be invoked with
* `this` set to the model constructor, e.g. `User`.
* @end
*/
observe(operation: string, listener: Listener): void;
/**
* Unregister an asynchronous observer for the given operation (event).
*
* Example:
*
* ```javascript
* MyModel.removeObserver('before save', function removedObserver(ctx, next) {
* // some logic user want to apply to the removed observer...
* next();
* });
* ```
*
* @param {String} operation The operation name.
* @callback {function} listener The listener function.
* @end
*/
removeObserver(operation: string, listener: Listener): Listener | undefined;
/**
* Unregister all asynchronous observers for the given operation (event).
*
* Example:
*
* Remove all observers connected to the `before save` operation.
*
* ```javascript
* MyModel.clearObservers('before save');
* ```
*
* @param {String} operation The operation name.
* @end
*/
clearObservers(operation: string): void;
/**
* Invoke all async observers for the given operation(s).
*
* Example:
*
* Notify all async observers for the `before save` operation.
*
* ```javascript
* var context = {
* Model: Model,
* instance: obj,
* isNewInstance: true,
* hookState: hookState,
* options: options,
* };
* Model.notifyObserversOf('before save', context, function(err) {
* if (err) return cb(err);
* // user can specify the logic after the observers have been notified
* });
* ```
*
* @param {String|String[]} operation The operation name(s).
* @param {Object} context Operation-specific context.
* @callback {function(Error=)} callback The callback to call when all observers
* have finished.
*/
notifyObserversOf(
operation: string,
context: object,
callback?: Callback,
): PromiseOrVoid;
_notifyBaseObservers(
operation: string,
context: object,
callback?: Callback,
): PromiseOrVoid;
/**
* Run the given function with before/after observers.
*
* It's done in three serial asynchronous steps:
*
* - Notify the registered observers under 'before ' + operation
* - Execute the function
* - Notify the registered observers under 'after ' + operation
*
* If an error happens, it fails first and calls the callback with err.
*
* Example:
*
* ```javascript
* var context = {
* Model: Model,
* instance: obj,
* isNewInstance: true,
* hookState: hookState,
* options: options,
* };
* function work(done) {
* process.nextTick(function() {
* done(null, 1);
* });
* }
* Model.notifyObserversAround('execute', context, work, function(err) {
* if (err) return cb(err);
* // user can specify the logic after the observers have been notified
* });
* ```
*
* @param {String} operation The operation name
* @param {Context} context The context object
* @param {Function} fn The task to be invoked as fn(done) or fn(context, done)
* @callback {Function} callback The callback function
* @returns {*}
*/
notifyObserversAround(
operation: string,
context: object,
fn: Function,
callback?: Callback,
): PromiseOrVoid;
}

518
types/persisted-model.d.ts vendored Normal file
View File

@ -0,0 +1,518 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Callback, Options, PromiseOrVoid} from './common';
import {ModelBase, ModelData} from './model';
import {Filter, Where} from './query';
/**
* Data object for persisted models
*/
export type PersistedData<
T extends PersistedModel = PersistedModel
> = ModelData<T>;
/**
* Type of affected count
*/
export interface Count {
count: number;
}
/**
* Persisted model
*/
export declare class PersistedModel extends ModelBase {
/**
* Create new instance of Model, and save to database.
*
* @param {Object|Object[]} [data] Optional data argument. Can be either a
* single model instance or an array of instances.
*
* @callback {Function} callback Callback function called with `cb(err, obj)` signature.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} models Model instances or null.
*/
static create(
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Update or insert a model instance
* @param {Object} data The model instance data to insert.
* @callback {Function} callback Callback function called with `cb(err, obj)` signature.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} model Updated model instance.
*/
static upsert(
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
static updateOrCreate(
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
static patchOrCreate(
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Update or insert a model instance based on the search criteria.
* If there is a single instance retrieved, update the retrieved model.
* Creates a new model if no model instances were found.
* Returns an error if multiple instances are found.
* @param {Object} [where] `where` filter, like
* ```
* { key: val, key2: {gt: 'val2'}, ...}
* ```
* <br/>see
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-other-methods).
* @param {Object} data The model instance data to insert.
* @callback {Function} callback Callback function called with `cb(err, obj)` signature.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} model Updated model instance.
*/
static upsertWithWhere(
where: Where,
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
static patchOrCreateWithWhere(
where: Where,
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Replace or insert a model instance; replace existing record if one is found,
* such that parameter `data.id` matches `id` of model instance; otherwise,
* insert a new record.
* @param {Object} data The model instance data.
* @options {Object} [options] Options for replaceOrCreate
* @property {Boolean} validate Perform validation before saving. Default is true.
* @callback {Function} callback Callback function called with `cb(err, obj)` signature.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} model Replaced model instance.
*/
static replaceOrCreate(
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Finds one record matching the optional filter object. If not found, creates
* the object using the data provided as second argument. In this sense it is
* the same as `find`, but limited to one object. Returns an object, not
* collection. If you don't provide the filter object argument, it tries to
* locate an existing object that matches the `data` argument.
*
* @options {Object} [filter] Optional Filter object; see below.
* @property {String|Object|Array} fields Identify fields to include in return result.
* <br/>See [Fields filter](http://loopback.io/doc/en/lb2/Fields-filter.html).
* @property {String|Object|Array} include See PersistedModel.include documentation.
* <br/>See [Include filter](http://loopback.io/doc/en/lb2/Include-filter.html).
* @property {Number} limit Maximum number of instances to return.
* <br/>See [Limit filter](http://loopback.io/doc/en/lb2/Limit-filter.html).
* @property {String} order Sort order: either "ASC" for ascending or "DESC" for descending.
* <br/>See [Order filter](http://loopback.io/doc/en/lb2/Order-filter.html).
* @property {Number} skip Number of results to skip.
* <br/>See [Skip filter](http://loopback.io/doc/en/lb2/Skip-filter.html).
* @property {Object} where Where clause, like
* ```
* {where: {key: val, key2: {gt: val2}, ...}}
* ```
* <br/>See
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-queries).
* @param {Object} data Data to insert if object matching the `where` filter is not found.
* @callback {Function} callback Callback function called with `cb(err, instance, created)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Model instance matching the `where` filter, if found.
* @param {Boolean} created True if the instance does not exist and gets created.
*/
static findOrCreate(
filter: Filter,
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Check whether a model instance exists in database.
*
* @param {id} id Identifier of object (primary key value).
*
* @callback {Function} callback Callback function called with `(err, exists)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Boolean} exists True if the instance with the specified ID exists; false otherwise.
*/
static exists(
id: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Find object by ID with an optional filter for include/fields.
*
* @param {*} id Primary key value
* @options {Object} [filter] Optional Filter JSON object; see below.
* @property {String|Object|Array} fields Identify fields to include in return result.
* <br/>See [Fields filter](http://loopback.io/doc/en/lb2/Fields-filter.html).
* @property {String|Object|Array} include See PersistedModel.include documentation.
* <br/>See [Include filter](http://loopback.io/doc/en/lb2/Include-filter.html).
* @callback {Function} callback Callback function called with `(err, instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Model instance matching the specified ID or null if no instance matches.
*/
static findById(
id: any,
filter?: Filter,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<PersistedData>;
/**
* Find all model instances that match `filter` specification.
* See [Querying models](http://loopback.io/doc/en/lb2/Querying-data.html).
*
* @options {Object} [filter] Optional Filter JSON object; see below.
* @property {String|Object|Array} fields Identify fields to include in return result.
* <br/>See [Fields filter](http://loopback.io/doc/en/lb2/Fields-filter.html).
* @property {String|Object|Array} include See PersistedModel.include documentation.
* <br/>See [Include filter](http://loopback.io/doc/en/lb2/Include-filter.html).
* @property {Number} limit Maximum number of instances to return.
* <br/>See [Limit filter](http://loopback.io/doc/en/lb2/Limit-filter.html).
* @property {String} order Sort order: either "ASC" for ascending or "DESC" for descending.
* <br/>See [Order filter](http://loopback.io/doc/en/lb2/Order-filter.html).
* @property {Number} skip Number of results to skip.
* <br/>See [Skip filter](http://loopback.io/doc/en/lb2/Skip-filter.html).
* @property {Object} where Where clause, like
* ```
* { where: { key: val, key2: {gt: 'val2'}, ...} }
* ```
* <br/>See
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-queries).
*
* @callback {Function} callback Callback function called with `(err, returned-instances)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Array} models Model instances matching the filter, or null if none found.
*/
static find(
filter?: Filter,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData[]>;
/**
* Find one model instance that matches `filter` specification.
* Same as `find`, but limited to one result;
* Returns object, not collection.
*
* @options {Object} [filter] Optional Filter JSON object; see below.
* @property {String|Object|Array} fields Identify fields to include in return result.
* <br/>See [Fields filter](http://loopback.io/doc/en/lb2/Fields-filter.html).
* @property {String|Object|Array} include See PersistedModel.include documentation.
* <br/>See [Include filter](http://loopback.io/doc/en/lb2/Include-filter.html).
* @property {String} order Sort order: either "ASC" for ascending or "DESC" for descending.
* <br/>See [Order filter](http://loopback.io/doc/en/lb2/Order-filter.html).
* @property {Number} skip Number of results to skip.
* <br/>See [Skip filter](http://loopback.io/doc/en/lb2/Skip-filter.html).
* @property {Object} where Where clause, like
* ```
* {where: { key: val, key2: {gt: 'val2'}, ...} }
* ```
* <br/>See
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-queries).
*
* @callback {Function} callback Callback function called with `(err, returned-instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Array} model First model instance that matches the filter or null if none found.
*/
static findOne(
filter?: Filter,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Destroy all model instances that match the optional `where` specification.
*
* @param {Object} [where] Optional where filter, like:
* ```
* {key: val, key2: {gt: 'val2'}, ...}
* ```
* <br/>See
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-other-methods).
*
* @callback {Function} callback Optional callback function called with `(err, info)` arguments.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} info Additional information about the command outcome.
* @param {Number} info.count Number of instances (rows, documents) destroyed.
*/
static destroyAll(
where?: Where,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
static remove(
where?: Where,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
static deleteAll(
where?: Where,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
/**
* Update multiple instances that match the where clause.
*
* Example:
*
*```js
* Employee.updateAll({managerId: 'x001'}, {managerId: 'x002'}, function(err, info) {
* ...
* });
* ```
*
* @param {Object} [where] Optional `where` filter, like
* ```
* { key: val, key2: {gt: 'val2'}, ...}
* ```
* <br/>see
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-other-methods).
* @param {Object} data Object containing data to replace matching instances, if AnyType.
*
* @callback {Function} callback Callback function called with `(err, info)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} info Additional information about the command outcome.
* @param {Number} info.count Number of instances (rows, documents) updated.
*
*/
static updateAll(
where?: Where,
data?: PersistedData,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
static update(
where?: Where,
data?: PersistedData,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
/**
* Destroy model instance with the specified ID.
* @param {*} id The ID value of model instance to delete.
* @callback {Function} callback Callback function called with `(err)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
*/
static destroyById(
id: any,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
static removeById(
id: any,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
static deleteById(
id: any,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
/**
* Replace attributes for a model instance whose id is the first input
* argument and persist it into the datasource.
* Performs validation before replacing.
*
* @param {*} id The ID value of model instance to replace.
* @param {Object} data Data to replace.
* @options {Object} [options] Options for replace
* @property {Boolean} validate Perform validation before saving. Default is true.
* @callback {Function} callback Callback function called with `(err, instance)` arguments.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Replaced instance.
*/
static replaceById(
id: any,
data: PersistedData,
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Return the number of records that match the optional "where" filter.
* @param {Object} [where] Optional where filter, like
* ```
* { key: val, key2: {gt: 'val2'}, ...}
* ```
* <br/>See
* [Where filter](http://loopback.io/doc/en/lb2/Where-filter.html#where-clause-for-other-methods).
* @callback {Function} callback Callback function called with `(err, count)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Number} count Number of instances.
*/
static count(
where?: Where,
options?: Options,
callback?: Callback<number>,
): PromiseOrVoid<number>;
/**
* Save model instance. If the instance doesn't have an ID, then calls [create](#persistedmodelcreatedata-cb) instead.
* Triggers: validate, save, update, or create.
* @options {Object} [options] See below.
* @property {Boolean} validate Perform validation before saving. Default is true.
* @property {Boolean} throws If true, throw a validation error; WARNING: This can crash Node.
* If false, report the error via callback. Default is false.
* @callback {Function} callback Optional callback function called with `(err, obj)` arguments.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Model instance saved or created.
*/
save(options?: Options, callback?: Callback<boolean>): PromiseOrVoid<boolean>;
/**
* Determine if the data model is new.
* @returns {Boolean} Returns true if the data model is new; false otherwise.
*/
isNewRecord(): boolean;
/**
* Deletes the model from persistence.
* Triggers `destroy` hook (async) before and after destroying object.
* @param {Function} callback Callback function.
*/
destroy(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
remove(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
delete(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Update a single attribute.
* Equivalent to `updateAttributes({name: 'value'}, cb)`
*
* @param {String} name Name of property.
* @param {Mixed} value Value of property.
* @callback {Function} callback Callback function called with `(err, instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Updated instance.
*/
updateAttribute(
name: string,
value: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Update set of attributes. Performs validation before updating.
*
* Triggers: `validation`, `save` and `update` hooks
* @param {Object} data Data to update.
* @callback {Function} callback Callback function called with `(err, instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Updated instance.
*/
updateAttributes(
data: PersistedData,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Replace attributes for a model instance and persist it into the datasource.
* Performs validation before replacing.
*
* @param {Object} data Data to replace.
* @options {Object} [options] Options for replace
* @property {Boolean} validate Perform validation before saving. Default is true.
* @callback {Function} callback Callback function called with `(err, instance)` arguments.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Replaced instance.
*/
replaceAttributes(
data: PersistedData,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
/**
* Reload object from persistence. Requires `id` member of `object` to be able to call `find`.
* @callback {Function} callback Callback function called with `(err, instance)` arguments. Required.
* @param {Error} err Error object; see [Error object](http://loopback.io/doc/en/lb2/Error-object.html).
* @param {Object} instance Model instance.
*/
reload(
options?: Options,
callback?: Callback<PersistedData>,
): PromiseOrVoid<PersistedData>;
/**
* Set the correct `id` property for the `PersistedModel`. Uses the `setId` method if the model is attached to
* connector that defines it. Otherwise, uses the default lookup.
* Override this method to handle complex IDs.
*
* @param {*} val The `id` value. Will be converted to the export type that the `id` property specifies.
*/
setId(val: any): void;
/**
* Get the `id` value for the `PersistedModel`.
*
* @returns {*} The `id` value
*/
getId(): any;
/**
* Get the `id` property name of the constructor.
*
* @returns {String} The `id` property name
*/
getIdName(): string;
/**
* Get the `id` property name of the constructor.
*
* @returns {String} The `id` property name
*/
static getIdName(): string;
}
export type PersistedModelClass = typeof PersistedModel;

108
types/query.d.ts vendored Normal file
View File

@ -0,0 +1,108 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
/**
* Operators for where clauses
*/
export declare enum Operators {
/**
* Equal operator (=)
*/
eq = 'eq',
/**
* Not equal operator (!=)
*/
neq = 'neq',
/**
* Greater than operator (>)
*/
gt = 'gt',
/**
* Greater than or equal operator (>=)
*/
gte = 'gte',
/**
* Less than operator (<)
*/
lt = 'lt',
/**
* Less than or equal (<=)
*/
lte = 'lte',
/**
* IN operator. For example, `{type: {inq: ['a', 'b', 'c']}}`
*/
inq = 'inq',
/**
* Between operator. For example, `{age: {between: [18, 40]}}`
*/
between = 'between',
/**
* Exists operator
*/
exists = 'exists',
/**
* AND operator
*/
and = 'and',
/**
* OR operator
*/
or = 'or',
}
/**
* Matching criteria
*/
export interface Condition {
eq?: any;
neq?: any;
gt?: any;
gte?: any;
lt?: any;
lte?: any;
inq?: any[];
between?: any[];
exists?: boolean;
and?: Where[];
or?: Where[];
}
/**
* Where object
*/
export interface Where {
and?: Where[]; // AND
or?: Where[]; // OR
[property: string]: Condition | any;
}
/**
* Selection of fields
*/
export interface Fields {
[property: string]: boolean;
}
/**
* Inclusion of related items
*/
export interface Inclusion {
relation: string;
scope?: Filter;
}
/**
* Query filter object
*/
export interface Filter {
where?: Where;
fields?: string | string[] | Fields;
order?: string | string[];
limit?: number;
skip?: number;
offset?: number;
include?: string | string[] | Inclusion[];
}

586
types/relation-mixin.d.ts vendored Normal file
View File

@ -0,0 +1,586 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Options} from './common';
import {RelationDefinition} from './relation';
import {PersistedModelClass} from './persisted-model';
/**
* Methods defined on this interface are mixed into a model class so that they
* can be used to set up relations between models programmatically.
*/
export interface RelationMixin {
/**
* Define a "one to many" relationship by specifying the model name.
*
* Examples:
* ```
* User.hasMany(Post, {as: 'posts', foreignKey: 'authorId'});
* ```
*
* ```
* Book.hasMany(Chapter);
* ```
* Or, equivalently:
* ```
* Book.hasMany('chapters', {model: Chapter});
* ```
*
* Query and create related models:
*
* ```js
* Book.create(function(err, book) {
*
* // Create a chapter instance ready to be saved in the data source.
* var chapter = book.chapters.build({name: 'Chapter 1'});
*
* // Save the new chapter
* chapter.save();
*
* // you can also call the Chapter.create method with the `chapters` property which will build a chapter
* // instance and save the it in the data source.
* book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
* // this callback is optional
* });
*
* // Query chapters for the book
* book.chapters(function(err, chapters) {
* // all chapters with bookId = book.id
* console.log(chapters);
* });
*
* // Query chapters for the book with a filter
* book.chapters({where: {name: 'test'}, function(err, chapters) {
* // All chapters with bookId = book.id and name = 'test'
* console.log(chapters);
* });
* });
* ```
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} foreignKey Property name of foreign key field.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {String} through Name of the through model.
* @property {String} keyThrough Property name of the foreign key in the through model.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Boolean} invert Specify if the relation is inverted.
* @property {Object} model The model object.
*/
hasMany(modelTo: PersistedModelClass, params?: Options): RelationDefinition;
/**
* Declare "belongsTo" relation that sets up a one-to-one connection with another model, such that each
* instance of the declaring model "belongs to" one instance of the other model.
*
* For example, if an application includes users and posts, and each post can be written by exactly one user.
* The following code specifies that `Post` has a reference called `author` to the `User` model via the `userId` property of `Post`
* as the foreign key.
* ```
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
* ```
* You can then access the author in one of the following styles.
* Get the User object for the post author asynchronously:
* ```
* post.author(callback);
* ```
* Get the User object for the post author synchronously:
* ```
* post.author();
* ```
* Set the author to be the given user:
* ```
* post.author(user)
* ```
* Examples:
*
* Suppose the model Post has a *belongsTo* relationship with User (the author of the post). You could declare it this way:
* ```js
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
* ```
*
* When a post is loaded, you can load the related author with:
* ```js
* post.author(function(err, user) {
* // the user variable is your user object
* });
* ```
*
* The related object is cached, so if later you try to get again the author, no additional request will be made.
* But there is an optional boolean parameter in first position that set whether or not you want to reload the cache:
* ```js
* post.author(true, function(err, user) {
* // The user is reloaded, even if it was already cached.
* });
* ```
* This optional parameter default value is false, so the related object will be loaded from cache if available.
*
* @param {Class|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} primaryKey Property name of primary key field.
* @property {String} foreignKey Name of foreign key property.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Object} options Property level options.
* @property {Boolean} options.invertProperties Specify if the properties should be inverted.
*/
belongsTo(modelTo: PersistedModelClass, params?: Options): RelationDefinition;
/**
* A hasAndBelongsToMany relation creates a direct many-to-many connection with another model, with no intervening model.
*
* For example, if your application includes users and groups, with each group having many users and each user appearing
* in many groups, you could declare the models this way:
* ```
* User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
* ```
* Then, to get the groups to which the user belongs:
* ```
* user.groups(callback);
* ```
* Create a new group and connect it with the user:
* ```
* user.groups.create(data, callback);
* ```
* Connect an existing group with the user:
* ```
* user.groups.add(group, callback);
* ```
* Remove the user from the group:
* ```
* user.groups.remove(group, callback);
* ```
*
* @param {String|Object} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} foreignKey Property name of foreign key field.
* @property {String} throughTable The table name of the through model.
* @property {String} through Name of the through model.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} model The model object.
*/
hasAndBelongsToMany(
modelTo: PersistedModelClass,
params?: Options,
): RelationDefinition;
/**
* Define a "one to one" relationship by specifying the model name.
*
* Examples:
* ```
* Supplier.hasOne(Account, {as: 'account', foreignKey: 'supplierId'});
* ```
*
* If the target model doesnt have a foreign key property, LoopBack will add a property with the same name.
*
* The type of the property will be the same as the type of the target models id property.
*
* Please note the foreign key property is defined on the target model (in this example, Account).
*
* If you dont specify them, then LoopBack derives the relation name and foreign key as follows:
* - Relation name: Camel case of the model name, for example, for the supplier model the relation is supplier.
* - Foreign key: The relation name appended with Id, for example, for relation name supplier the default foreign key is supplierId.
*
* Build a new account for the supplier with the supplierId to be set to the id of the supplier.
* ```js
* var supplier = supplier.account.build(data);
* ```
*
* Create a new account for the supplier. If there is already an account, an error will be reported.
* ```js
* supplier.account.create(data, function(err, account) {
* ...
* });
* ```
*
* Find the supplier's account model.
* ```js
* supplier.account(function(err, account) {
* ...
* });
* ```
*
* Update the associated account.
* ```js
* supplier.account.update({balance: 100}, function(err, account) {
* ...
* });
* ```
*
* Remove the account for the supplier.
* ```js
* supplier.account.destroy(function(err) {
* ...
* });
* ```
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} primaryKey Property name of primary key field.
* @property {String} foreignKey Property name of foreign key field.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} model The model object.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
hasOne(modelTo: PersistedModelClass, params?: Options): RelationDefinition;
/**
* References one or more instances of the target model.
*
* For example, a Customer model references one or more instances of the Account model.
*
* Define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"accounts": {
"type": "referencesMany",
"model": "Account",
"foreignKey": "accountIds",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of Account model:
* ```json
* {
"name": "Account",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"balance": {
"type": "number"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* On the bootscript, create a customer instance and for that customer instance reference many account instances.
*
* For example:
* ```javascript
* var Customer = app.models.Customer;
var accounts = [
{
name: 'Checking',
balance: 5000
},
{
name: 'Saving',
balance: 2000
}
];
Customer.create({name: 'Mary Smith'}, function(err, customer) {
console.log('Customer:', customer);
async.each(accounts, function(account, done) {
customer.accounts.create(account, done);
}, function(err) {
console.log('Customer with accounts:', customer);
customer.accounts(console.log);
cb(err);
});
});
* ```
*
* Sample referencesMany model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
accounts: [
"saving-01", "checking-01",
]
}
* ```
*
* Supported helper methods:
* - customer.accounts()
* - customer.accounts.create()
* - customer.accounts.build()
* - customer.accounts.findById()
* - customer.accounts.destroy()
* - customer.accounts.updateById()
* - customer.accounts.exists()
* - customer.accounts.add()
* - customer.accounts.remove()
* - customer.accounts.at()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {String} foreignKey Property name of foreign key field.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
referencesMany(
modelTo: PersistedModelClass,
params?: Options,
): RelationDefinition;
/**
* Represent a model that embeds another model.
*
* For example, a Customer embeds one billingAddress from the Address model.
*
* - Define the relation in bootscript:
* ```js
* Customer.embedsOne(Address, {
* as: 'address', // default to the relation name - address
* property: 'billingAddress' // default to addressItem
* });
* ```
*
* OR, define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"address": {
"type": "embedsOne",
"model": "Address",
"property": "billingAddress",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of Address model:
* ```json
* {
"name": "Address",
"base": "Model",
"idInjection": true,
"properties": {
"street": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"zipCode": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* Sample embedded model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
billingAddress: {
street: '123 Main St',
city: 'San Jose',
state: 'CA',
zipCode: '95124'
}
}
* ```
*
* Supported helper methods:
* - customer.address()
* - customer.address.build()
* - customer.address.create()
* - customer.address.update()
* - customer.address.destroy()
* - customer.address.value()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} property Name of the property for the embedded item.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
embedsOne(modelTo: PersistedModelClass, params?: Options): RelationDefinition;
/**
* Represent a model that can embed many instances of another model.
*
* For example, a Customer can have multiple email addresses and each email address is a complex object that contains label and address.
*
* Define the relation code in bootscript:
* ```javascript
Customer.embedsMany(EmailAddress, {
as: 'emails', // default to the relation name - emailAddresses
property: 'emailList' // default to emailAddressItems
});
* ```
*
* OR, define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"emails": {
"type": "embedsMany",
"model": "EmailAddress",
"property": "emailList",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of EmailAddress model:
* ```json
* {
"name": "EmailAddress",
"base": "Model",
"idInjection": true,
"properties": {
"label": {
"type": "string"
},
"address": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* Sample embedded model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
emails: [{
label: 'work',
address: 'john@xyz.com'
}, {
label: 'home',
address: 'john@gmail.com'
}]
}
* ```
*
* Supported helper methods:
* - customer.emails()
* - customer.emails.create()
* - customer.emails.build()
* - customer.emails.findById()
* - customer.emails.destroyById()
* - customer.emails.updateById()
* - customer.emails.exists()
* - customer.emails.add()
* - customer.emails.remove()
* - customer.emails.at()
* - customer.emails.value()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} property Name of the property for the embedded item.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
embedsMany(
modelTo: PersistedModelClass,
params?: Options,
): RelationDefinition;
}

407
types/relation.d.ts vendored Normal file
View File

@ -0,0 +1,407 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {AnyObject, Callback, Options, PromiseOrVoid} from './common';
import {ModelData} from './model';
import {
Count,
PersistedData,
PersistedModel,
PersistedModelClass,
} from './persisted-model';
import {Filter, Where} from './query';
/**
* Relation types
*/
export enum RelationType {
belongsTo = 'belongsTo',
hasMany = 'hasMany',
hasOne = 'hasOne',
hasAndBelongsToMany = 'hasAndBelongsToMany',
referencesMany = 'referencesMany',
embedsOne = 'embedsOne',
embedsMany = 'embedsMany',
}
/**
* Relation definition
*/
export declare class RelationDefinition {
name: string;
type: RelationType;
modelFrom: PersistedModelClass | string;
keyFrom: string;
modelTo: PersistedModelClass | string;
keyTo: string;
polymorphic: AnyObject | boolean;
modelThrough?: PersistedModelClass | string;
keyThrough?: string;
multiple: boolean;
properties: AnyObject;
options: Options;
scope: AnyObject;
embed?: boolean;
methods?: AnyObject<Function>;
toJSON(): AnyObject;
defineMethod(name: string, fn: Function): Function;
applyScope(modelInstance: PersistedData, filter: Filter): void;
applyProperties(modelInstance: PersistedData, obj: AnyObject): void;
}
/**
* Relation of a given model instance
*/
export declare class Relation<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> {
constructor(definition: RelationDefinition, modelInstance: S);
resetCache(cache: T): void;
getCache(): AnyObject<T>;
callScopeMethod(methodName: string, ...args: any[]): any;
fetch(
condOrRefresh: boolean | AnyObject,
options?: Options,
callback?: Callback<T | T[]>,
): PromiseOrVoid<T | T[]>;
}
export declare class BelongsTo<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
create(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
build(targetModelData: PersistedData<T>): T;
update(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroy(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
related(
condOrRefresh: boolean | AnyObject,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
get(options?: Options, callback?: Callback<T>): PromiseOrVoid<T>;
}
export declare class HasMany<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
removeFromCache(id: any): T | null;
addToCache(inst: T): void;
findById(
fkId: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
exists(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
updateById(
fkId: any,
data: ModelData,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroyById(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
}
export declare class HasManyThrough<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
findById(
fkId: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
destroyById(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
create(
data: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
add(
acInst: any,
data: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
exists(
acInst: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
remove(
acInst: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
}
export declare class HasOne<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
create(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
update(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroy(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
build(targetModelData: PersistedData<T>): T;
related(
condOrRefresh: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
get(options?: Options, callback?: Callback<T>): PromiseOrVoid<T>;
}
export declare class HasAndBelongsToMany<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {}
export declare class ReferencesMany<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
related(
receiver: PersistedModelClass,
scopeParams: AnyObject,
condOrRefresh: any,
options?: Options,
callback?: Callback<ModelData>,
): PromiseOrVoid<ModelData>;
findById(
fkId: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
exists(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
updateById(
fkId: any,
data: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroyById(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
at(
index: number,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
create(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
build(targetModelData: PersistedData<T>): T;
add(
acInst: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
remove(
acInst: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
}
export declare class EmbedsOne<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
related(
condOrRefresh: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
prepareEmbeddedInstance(inst: T): void;
embeddedValue(modelInstance: S): T;
create(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
build(targetModelData: PersistedData<T>): T;
update(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroy(
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
}
export declare class EmbedsMany<
S extends PersistedModel = PersistedModel,
T extends PersistedModel = PersistedModel
> extends Relation<S, T> {
prepareEmbeddedInstance(inst: T): void;
embeddedList(modelInstance: T[]): void;
embeddedValue(modelInstance: S): T[];
related(
receiver: PersistedModelClass,
scopeParams: AnyObject,
condOrRefresh: any,
options?: Options,
callback?: Callback<ModelData>,
): PromiseOrVoid<ModelData>;
findById(
fkId: any,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
get(
fkId: any,
options?: Options,
callback?: Callback<ModelData>,
): PromiseOrVoid<ModelData>;
exists(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
updateById(
fkId: any,
data: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
set(
fkId: any,
data: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroyById(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
unset(
fkId: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
destroyAll(
where: Where,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
at(index: number, callback?: Callback<T>): PromiseOrVoid<T>;
create(
targetModelData: PersistedData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
build(targetModelData: PersistedData<T>): T;
add(
acInst: any,
data: PersistedData<T>,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
remove(
acInst: any,
options?: Options,
callback?: Callback<boolean>,
): PromiseOrVoid<boolean>;
}

113
types/scope.d.ts vendored Normal file
View File

@ -0,0 +1,113 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {AnyObject, Callback, Options, PromiseOrVoid} from './common';
import {ModelBase, ModelBaseClass, ModelData} from './model';
import {Count} from './persisted-model';
import {Filter, Where} from './query';
/**
* Definition metadata for scopes
*/
export declare class ScopeDefinition {
constructor(definition: AnyObject);
isStatic: boolean;
modelFrom?: ModelBaseClass;
modelTo?: ModelBaseClass;
name: string;
params?: AnyObject;
methods?: AnyObject<Function>;
options?: Options;
targetModel(receiver: ModelBaseClass | (() => ModelBaseClass)): void;
/**
* Find related model instances
* @param {*} receiver The target model class/prototype
* @param {Object|Function} scopeParams
* @param {Boolean|Object} [condOrRefresh] true for refresh or object as a filter
* @param {Object} [options]
* @param {Function} cb
* @returns {*}
*/
related(
receiver: ModelBaseClass | (() => ModelBaseClass),
scopeParams: AnyObject | (() => AnyObject),
condOrRefresh: boolean | AnyObject,
options?: Options,
callback?: Callback,
): PromiseOrVoid;
/**
* Define a scope method
* @param {String} name of the method
* @param {Function} function to define
*/
defineMethod(name: string, fn: Function): Function;
}
/**
* Define a scope to the class
* @param {Model} cls The class where the scope method is added
* @param {Model} targetClass The class that a query to run against
* @param {String} name The name of the scope
* @param {Object|Function} params The parameters object for the query or a function
* to return the query object
* @param methods An object of methods keyed by the method name to be bound to the class
*/
export declare function defineScope(
cls: ModelBaseClass,
targetClass: ModelBaseClass,
name: string,
params: AnyObject,
methods: AnyObject<Function>,
options?: Options,
): ScopeDefinition;
/**
* Methods injected by scopes
*/
export interface ScopedMethods<T extends ModelBase = ModelBase> {
build(data: ModelData<T>): T;
create(
data: ModelData<T>,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
destroyAll(
where?: Where,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
updateAll(
where?: Where,
data?: ModelData<T>,
options?: Options,
callback?: Callback<Count>,
): PromiseOrVoid<Count>;
findById(
id: any,
filter: Filter,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
findOne(
filter: Filter,
options?: Options,
callback?: Callback<T>,
): PromiseOrVoid<T>;
count(
where: Where,
options?: Options,
callback?: Callback<number>,
): PromiseOrVoid<number>;
}

47
types/transaction-mixin.d.ts vendored Normal file
View File

@ -0,0 +1,47 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Callback, Options, PromiseOrVoid} from './common';
/**
* Local transaction
*/
export interface Transaction {
/**
* Commit the transaction
* @param callback
*/
commit(callback?: Callback): PromiseOrVoid;
/**
* Rollback the transaction
* @param callback
*/
rollback(callback?: Callback): PromiseOrVoid;
}
/**
* Isolation level
*/
export enum IsolationLevel {
READ_COMMITTED = 'READ COMMITTED', // default
READ_UNCOMMITTED = 'READ UNCOMMITTED',
SERIALIZABLE = 'SERIALIZABLE',
REPEATABLE_READ = 'REPEATABLE READ',
}
/**
* Mixin for transaction support
*/
export interface TransactionMixin {
/**
* Begin a new transaction
* @param options
* @param callback
*/
beginTransaction(
options?: IsolationLevel | Options,
callback?: Callback<Transaction>,
): PromiseOrVoid<Transaction>;
}

303
types/validation-mixin.d.ts vendored Normal file
View File

@ -0,0 +1,303 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
import {Callback, Options, PromiseOrVoid} from './common';
/**
* This class provides methods that add validation cababilities to models.
* Each of the validations runs when the `obj.isValid()` method is called.
*
* All of the methods have an options object parameter that has a
* `message` property. When there is only a single error message, this
* property is just a string;
* for example: `Post.validatesPresenceOf('title', { message: 'can not be blank' });`
*
* In more complicated cases it can be a set of messages, for each possible
* error condition; for example:
* `User.validatesLengthOf('password', { min: 6, max: 20, message: {min: 'too short', max: 'too long'}});`
*
*/
export interface Validatable {
/**
* Validate presence of one or more specified properties.
*
* Requires a model to include a property to be considered valid; fails when validated field is blank.
*
* For example, validate presence of title
* ```
* Post.validatesPresenceOf('title');
* ```
* Validate that model has first, last, and age properties:
* ```
* User.validatesPresenceOf('first', 'last', 'age');
* ```
* Example with custom message
* ```
* Post.validatesPresenceOf('title', {message: 'Cannot be blank'});
* ```
*
* @param {String} propertyName One or more property names.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
validatesPresenceOf(...propertyNames: string[]): void;
validatesPresenceOf(propertyName: string, options?: Options): void;
/**
* Validate absence of one or more specified properties.
*
* A model should not include a property to be considered valid; fails when validated field is not blank.
*
* For example, validate absence of reserved
* ```
* Post.validatesAbsenceOf('reserved', { unless: 'special' });
* ```
*
* @param {String} propertyName One or more property names.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
validatesAbsenceOf(...propertyNames: string[]): void;
validatesAbsenceOf(propertyName: string, options?: Options): void;
/**
* Validate length.
*
* Require a property length to be within a specified range.
*
* There are three kinds of validations: min, max, is.
*
* Default error messages:
*
* - min: too short
* - max: too long
* - is: length is wrong
*
* Example: length validations
* ```
* User.validatesLengthOf('password', {min: 7});
* User.validatesLengthOf('email', {max: 100});
* User.validatesLengthOf('state', {is: 2});
* User.validatesLengthOf('nick', {min: 3, max: 15});
* ```
* Example: length validations with custom error messages
* ```
* User.validatesLengthOf('password', {min: 7, message: {min: 'too weak'}});
* User.validatesLengthOf('state', {is: 2, message: {is: 'is not valid state name'}});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {Number} is Value that property must equal to validate.
* @property {Number} min Value that property must be less than to be valid.
* @property {Number} max Value that property must be less than to be valid.
* @property {Object} message Optional object with string properties for custom error message for each validation: is, min, or max.
*/
validatesLengthOf(propertyName: string, options?: Options): void;
/**
* Validate numericality.
*
* Requires a value for property to be either an integer or number.
*
* Example
* ```
* User.validatesNumericalityOf('age', { message: { number: 'is not a number' }});
* User.validatesNumericalityOf('age', {int: true, message: { int: 'is not an integer' }});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {Boolean} int If true, then property must be an integer to be valid.
* @property {Boolean} allowBlank Allow property to be blank.
* @property {Boolean} allowNull Allow property to be null.
* @property {Object} message Optional object with string properties for 'int' for integer validation. Default error messages:
* - number: is not a number
* - int: is not an integer
*/
validatesNumericalityOf(propertyName: string, options?: Options): void;
/**
* Validate inclusion in set.
*
* Require a value for property to be in the specified array.
*
* Example:
* ```
* User.validatesInclusionOf('gender', {in: ['male', 'female']});
* User.validatesInclusionOf('role', {
* in: ['admin', 'moderator', 'user'], message: 'is not allowed'
* });
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {Array} in Property must match one of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid.
* Default error message: "is not included in the list".
* @property {Boolean} allowNull Whether null values are allowed.
*/
validatesInclusionOf(propertyName: string, options?: Options): void;
/**
* Validate exclusion in a set.
*
* Require a property value not be in the specified array.
*
* Example: `Company.validatesExclusionOf('domain', {in: ['www', 'admin']});`
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {Array} in Property must not match any of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid. Default error message: "is reserved".
* @property {Boolean} allowNull Whether null values are allowed.
*/
validatesExclusionOf(propertyName: string, options?: Options): void;
/**
* Validate format.
*
* Require a model to include a property that matches the given format.
*
* Example: `User.validatesFormatOf('name', {with: /\w+/});`
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {RegExp} with Regular expression to validate format.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
validatesFormatOf(propertyName: string, options?: Options): void;
/**
* Validate using custom validation function.
*
* Example:
*```javascript
* User.validate('name', customValidator, {message: 'Bad name'});
* function customValidator(err) {
* if (this.name === 'bad') err();
* });
* var user = new User({name: 'Peter'});
* user.isValid(); // true
* user.name = 'bad';
* user.isValid(); // false
* ```
*
* @param {String} propertyName Property name to validate.
* @param {Function} validatorFn Custom validation function.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
validate(
propertyName: string,
validatorFn: Function,
options?: Options,
): void;
/**
* Validate using custom asynchronous validation function.
*
* Example:
*```js
* User.validateAsync('name', customValidator, {message: 'Bad name'});
* function customValidator(err, done) {
* process.nextTick(function () {
* if (this.name === 'bad') err();
* done();
* });
* });
* var user = new User({name: 'Peter'});
* user.isValid(); // false (because async validation setup)
* user.isValid(function (isValid) {
* isValid; // true
* })
* user.name = 'bad';
* user.isValid(); // false
* user.isValid(function (isValid) {
* isValid; // false
* })
* ```
*
* @param {String} propertyName Property name to validate.
* @param {Function} validatorFn Custom validation function.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
validateAsync(
propertyName: string,
validatorFn: Function,
options?: Options,
): void;
/**
* Validate uniqueness of the value for a property in the collection of models.
*
* Not available for all connectors. Currently supported with these connectors:
* - In Memory
* - Oracle
* - MongoDB
*
* ```
* // The login must be unique across all User instances.
* User.validatesUniquenessOf('login');
*
* // Assuming SiteUser.belongsTo(Site)
* // The login must be unique within each Site.
* SiteUser.validateUniquenessOf('login', { scopedTo: ['siteId'] });
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {RegExp} with Regular expression to validate format.
* @property {Array.<String>} scopedTo List of properties defining the scope.
* @property {String} message Optional error message if property is not valid. Default error message: "is not unique".
* @property {Boolean} allowNull Whether null values are allowed.
* @property {String} ignoreCase Make the validation case insensitive.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
validatesUniquenessOf(
propertyName: string,
validatorFn: Function,
options?: Options,
): void;
/**
* Validate if a value for a property is a Date.
*
* Example
* ```
* User.validatesDateOf('today', {message: 'today is not a date!'});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
*/
validatesDateOf(
propertyName: string,
validatorFn: Function,
options?: Options,
): void;
}
/**
* ValidationError
*/
export declare class ValidationError extends Error {
statusCode?: number;
details: {
context: any;
codes: string[];
messages: string[];
};
}