不要怂,就是干,撸起袖子干!

Commit 26547bc9 by Simon Schick Committed by Sushant

feat: add typescript typings (#10287)

1 parent 554b223c
...@@ -16,6 +16,8 @@ install: ...@@ -16,6 +16,8 @@ install:
- npm install -g yarn - npm install -g yarn
- yarn - yarn
- |- - |-
if [ "$TSC" = true ]; then npm run test-typings; fi
- |-
if [ "$DIALECT" = "postgres-native" ]; then yarn add pg-native; fi if [ "$DIALECT" = "postgres-native" ]; then yarn add pg-native; fi
env: env:
...@@ -38,6 +40,8 @@ script: ...@@ -38,6 +40,8 @@ script:
- npm run lint - npm run lint
- |- - |-
if [ "$COVERAGE" = true ]; then npm run cover && bash <(curl -s https://codecov.io/bash) -f coverage/lcov.info; else npm run test; fi if [ "$COVERAGE" = true ]; then npm run cover && bash <(curl -s https://codecov.io/bash) -f coverage/lcov.info; else npm run test; fi
- |-
if [ "$TSC" = true ]; then npm run test-typings; fi
jobs: jobs:
include: include:
...@@ -66,7 +70,7 @@ jobs: ...@@ -66,7 +70,7 @@ jobs:
env: POSTGRES_VER=postgres-95 SEQ_PG_PORT=8990 DIALECT=postgres-native env: POSTGRES_VER=postgres-95 SEQ_PG_PORT=8990 DIALECT=postgres-native
- stage: test - stage: test
node_js: '8' node_js: '8'
env: DIALECT=sqlite COVERAGE=false env: DIALECT=sqlite COVERAGE=false TSC=true
# - stage: release # - stage: release
# node_js: '8' # node_js: '8'
# script: # script:
......
'use strict'; 'use strict';
const _ = require('lodash'); const _ = require('lodash');
const Utils = require('./utils');
const logger = require('./utils/logger'); const logger = require('./utils/logger');
const Promise = require('./promise'); const Promise = require('./promise');
const debug = logger.getLogger().debugContext('hooks'); const debug = logger.getLogger().debugContext('hooks');
...@@ -86,10 +85,9 @@ const Hooks = { ...@@ -86,10 +85,9 @@ const Hooks = {
}); });
}, },
runHooks(hooks) { runHooks(hooks, ...hookArgs) {
if (!hooks) throw new Error('runHooks requires at least 1 argument'); if (!hooks) throw new Error('runHooks requires at least 1 argument');
const hookArgs = Utils.sliceArgs(arguments, 1);
let hookType; let hookType;
if (typeof hooks === 'string') { if (typeof hooks === 'string') {
......
...@@ -852,7 +852,7 @@ class Sequelize { ...@@ -852,7 +852,7 @@ class Sequelize {
* }); * });
*/ */
static fn(fn, ...args) { static fn(fn, ...args) {
return new Utils.Fn(fn, Utils.sliceArgs(args)); return new Utils.Fn(fn, args);
} }
/** /**
...@@ -909,7 +909,7 @@ class Sequelize { ...@@ -909,7 +909,7 @@ class Sequelize {
* @returns {Sequelize.and} * @returns {Sequelize.and}
*/ */
static and(...args) { static and(...args) {
return { [Op.and]: Utils.sliceArgs(args) }; return { [Op.and]: args };
} }
/** /**
...@@ -924,7 +924,7 @@ class Sequelize { ...@@ -924,7 +924,7 @@ class Sequelize {
* @returns {Sequelize.or} * @returns {Sequelize.or}
*/ */
static or(...args) { static or(...args) {
return { [Op.or]: Utils.sliceArgs(args) }; return { [Op.or]: args };
} }
/** /**
...@@ -1067,9 +1067,8 @@ class Sequelize { ...@@ -1067,9 +1067,8 @@ class Sequelize {
return res; return res;
} }
log() { log(...args) {
let options; let options;
let args = Utils.sliceArgs(arguments);
const last = _.last(args); const last = _.last(args);
......
...@@ -323,17 +323,6 @@ function stack() { ...@@ -323,17 +323,6 @@ function stack() {
} }
exports.stack = stack; exports.stack = stack;
function sliceArgs(args, begin) {
begin = begin || 0;
const tmp = new Array(args.length - begin);
for (let i = begin; i < args.length; ++i) {
tmp[i - begin] = args[i];
}
return tmp;
}
exports.sliceArgs = sliceArgs;
const dialects = new Set(['mariadb', 'mysql', 'postgres', 'sqlite', 'mssql']); const dialects = new Set(['mariadb', 'mysql', 'postgres', 'sqlite', 'mssql']);
function now(dialect) { function now(dialect) {
...@@ -433,10 +422,10 @@ class Fn extends SequelizeMethod { ...@@ -433,10 +422,10 @@ class Fn extends SequelizeMethod {
exports.Fn = Fn; exports.Fn = Fn;
class Col extends SequelizeMethod { class Col extends SequelizeMethod {
constructor(col) { constructor(col, ...args) {
super(); super();
if (arguments.length > 1) { if (args.length > 0) {
col = this.sliceArgs(arguments); col = args;
} }
this.col = col; this.col = col;
} }
......
...@@ -18,11 +18,14 @@ ...@@ -18,11 +18,14 @@
"url": "https://github.com/sequelize/sequelize/issues" "url": "https://github.com/sequelize/sequelize/issues"
}, },
"main": "index.js", "main": "index.js",
"types": "types",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
}, },
"files": [ "files": [
"lib" "lib",
"types/index.d.ts",
"types/lib"
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
...@@ -46,6 +49,9 @@ ...@@ -46,6 +49,9 @@
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^7.2.0", "@commitlint/cli": "^7.2.0",
"@commitlint/config-angular": "^7.1.2", "@commitlint/config-angular": "^7.1.2",
"@types/bluebird": "^3.5.25",
"@types/node": "^10.12.18",
"@types/validator": "^9.4.4",
"chai": "^4.x", "chai": "^4.x",
"chai-as-promised": "^7.x", "chai-as-promised": "^7.x",
"chai-datetime": "^1.x", "chai-datetime": "^1.x",
...@@ -75,7 +81,8 @@ ...@@ -75,7 +81,8 @@
"sinon": "^6.3.5", "sinon": "^6.3.5",
"sinon-chai": "^3.2.0", "sinon-chai": "^3.2.0",
"sqlite3": "^4.0.2", "sqlite3": "^4.0.2",
"tedious": "^3.0.1" "tedious": "^3.0.1",
"typescript": "^3.2.2"
}, },
"keywords": [ "keywords": [
"mysql", "mysql",
...@@ -138,6 +145,7 @@ ...@@ -138,6 +145,7 @@
"test-postgresn": "npm run test-postgres-native", "test-postgresn": "npm run test-postgres-native",
"test-mssql": "cross-env DIALECT=mssql npm test", "test-mssql": "cross-env DIALECT=mssql npm test",
"test-all": "npm run test-mariadb && npm run test-mysql && npm run test-sqlite && npm run test-postgres && npm run test-postgres-native && npm run test-mssql", "test-all": "npm run test-mariadb && npm run test-mysql && npm run test-sqlite && npm run test-postgres && npm run test-postgres-native && npm run test-mssql",
"test-typings": "tsc -b types/tsconfig.json && tsc -b types/test/tsconfig.json",
"cover": "rimraf coverage && npm run teaser && npm run cover-integration && npm run cover-unit && npm run merge-coverage", "cover": "rimraf coverage && npm run teaser && npm run cover-integration && npm run cover-unit && npm run merge-coverage",
"cover-integration": "cross-env COVERAGE=true ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --require scripts/mocha-bootload --report lcovonly -- -t 30000 --exit --ui tdd \"test/integration/**/*.test.js\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/integration.info')\"", "cover-integration": "cross-env COVERAGE=true ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --require scripts/mocha-bootload --report lcovonly -- -t 30000 --exit --ui tdd \"test/integration/**/*.test.js\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/integration.info')\"",
"cover-unit": "cross-env COVERAGE=true ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --require scripts/mocha-bootload --report lcovonly -- -t 30000 --exit --ui tdd \"test/unit/**/*.test.js\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/unit.info')\"", "cover-unit": "cross-env COVERAGE=true ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --require scripts/mocha-bootload --report lcovonly -- -t 30000 --exit --ui tdd \"test/unit/**/*.test.js\" && node -e \"require('fs').renameSync('coverage/lcov.info', 'coverage/unit.info')\"",
......
...@@ -132,15 +132,14 @@ module.exports = function(Sequelize) { ...@@ -132,15 +132,14 @@ module.exports = function(Sequelize) {
shimMethod(obj, name, original => { shimMethod(obj, name, original => {
const sequelizeProto = obj === Sequelize.prototype; const sequelizeProto = obj === Sequelize.prototype;
return function() { return function(...args) {
let sequelize = sequelizeProto ? this : this.sequelize; let sequelize = sequelizeProto ? this : this.sequelize;
if (this instanceof Sequelize.Association) sequelize = this.target.sequelize; if (this instanceof Sequelize.Association) sequelize = this.target.sequelize;
if (!sequelize) throw new Error('Object does not have a `sequelize` attribute'); if (!sequelize) throw new Error('Object does not have a `sequelize` attribute');
let args = Sequelize.Utils.sliceArgs(arguments);
const fromTests = calledFromTests(); const fromTests = calledFromTests();
if (conform) args = conform.apply(this, arguments); if (conform) args = conform.apply(this, args);
let options = args[index]; let options = args[index];
......
import DataTypes = require('./lib/data-types');
import Deferrable = require('./lib/deferrable');
import Op = require('./lib/operators');
import QueryTypes = require('./lib/query-types');
import TableHints = require('./lib/table-hints');
import Utils = require('./lib/utils');
export * from './lib/sequelize';
export * from './lib/query-interface';
export * from './lib/data-types';
export * from './lib/model';
export * from './lib/transaction';
export * from './lib/model';
export * from './lib/associations/index';
export * from './lib/errors';
export { BaseError as Error } from './lib/errors';
export { useInflection } from './lib/utils';
export { Promise } from './lib/promise';
export { Utils, QueryTypes, Op, TableHints, DataTypes, Deferrable };
export { Validator as validator } from './lib/utils/validator-extras';
import { ColumnOptions, Model } from '../model';
export abstract class Association {
public associationType: string;
public source: typeof Model;
public target: typeof Model;
public isSelfAssociation: boolean;
public isSingleAssociation: boolean;
public isMultiAssociation: boolean;
public as: string;
public isAliased: boolean;
public foreignKey: string;
public identifier: string;
public inspect(): string;
}
export interface SingleAssociationAccessors {
get: string;
set: string;
create: string;
}
export interface MultiAssociationAccessors {
get: string;
set: string;
addMultiple: string;
add: string;
create: string;
remove: string;
removeMultiple: string;
hasSingle: string;
hasAll: string;
count: string;
}
/** Foreign Key Options */
export interface ForeignKeyOptions extends ColumnOptions {
/** Attribute name for the relation */
name?: string;
}
/**
* Options provided when associating models
*/
export interface AssociationOptions {
/**
* Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade.
* For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks
* for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking
* any hooks.
*
* @default false
*/
hooks?: boolean;
/**
* The alias of this model, in singular form. See also the `name` option passed to `sequelize.define`. If
* you create multiple associations between the same tables, you should provide an alias to be able to
* distinguish between them. If you provide an alias when creating the assocition, you should provide the
* same alias when eager loading and when getting assocated models. Defaults to the singularized name of
* target
*/
as?: string | { singular: string; plural: string };
/**
* The name of the foreign key in the target table or an object representing the type definition for the
* foreign column (see `Sequelize.define` for syntax). When using an object, you can add a `name` property
* to set the name of the column. Defaults to the name of source + primary key of source
*/
foreignKey?: string | ForeignKeyOptions;
/**
* What happens when delete occurs.
*
* Cascade if this is a n:m, and set null if it is a 1:m
*
* @default 'SET NULL' or 'CASCADE'
*/
onDelete?: string;
/**
* What happens when update occurs
*
* @default 'CASCADE'
*/
onUpdate?: string;
/**
* Should on update and on delete constraints be enabled on the foreign key.
*/
constraints?: boolean;
foreignKeyConstraint?: boolean;
scope?: AssociationScope;
}
/**
* Options for Association Scope
*/
export interface AssociationScope {
/**
* The name of the column that will be used for the associated scope and it's value
*/
[scopeName: string]: any;
}
/**
* Options provided for many-to-many relationships
*/
export interface ManyToManyOptions extends AssociationOptions {
/**
* A key/value set that will be used for association create and find defaults on the target.
* (sqlite not supported for N:M)
*/
scope?: AssociationScope;
}
import { DataType } from '../data-types';
import { CreateOptions, FindOptions, Model, SaveOptions } from '../model';
import { Promise } from '../promise';
import { Association, AssociationOptions, SingleAssociationAccessors } from './base';
/**
* Options provided when associating models with belongsTo relationship
*
* @see Association class belongsTo method
*/
export interface BelongsToOptions extends AssociationOptions {
/**
* The name of the field to use as the key for the association in the target table. Defaults to the primary
* key of the target table
*/
targetKey?: string;
/**
* A string or a data type to represent the identifier in the table
*/
keyType?: DataType;
}
export class BelongsTo extends Association {
public accessors: SingleAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: BelongsToOptions);
}
/**
* The options for the getAssociation mixin of the belongsTo association.
* @see BelongsToGetAssociationMixin
*/
export interface BelongsToGetAssociationMixinOptions extends FindOptions {
/**
* Apply a scope on the related model, or remove its default scope by passing false.
*/
scope?: string | string[] | boolean;
}
/**
* The getAssociation mixin applied to models with belongsTo.
* An example of usage is as follows:
*
* ```js
*
* User.belongsTo(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttrib>, UserAttrib {
* getRole: Sequelize.BelongsToGetAssociationMixin<RoleInstance>;
* // setRole...
* // createRole...
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/belongs-to/
* @see Instance
*/
export type BelongsToGetAssociationMixin<TModel> = (options?: BelongsToGetAssociationMixinOptions) => Promise<TModel>;
/**
* The options for the setAssociation mixin of the belongsTo association.
* @see BelongsToSetAssociationMixin
*/
export interface BelongsToSetAssociationMixinOptions extends SaveOptions {
/**
* Skip saving this after setting the foreign key if false.
*/
save?: boolean;
}
/**
* The setAssociation mixin applied to models with belongsTo.
* An example of usage is as follows:
*
* ```js
*
* User.belongsTo(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttributes>, UserAttributes {
* // getRole...
* setRole: Sequelize.BelongsToSetAssociationMixin<RoleInstance, RoleId>;
* // createRole...
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/belongs-to/
* @see Instance
*/
export type BelongsToSetAssociationMixin<TModel, TPrimaryKey> = (
newAssociation?: TModel | TPrimaryKey,
options?: BelongsToSetAssociationMixinOptions
) => Promise<void>;
/**
* The options for the createAssociation mixin of the belongsTo association.
* @see BelongsToCreateAssociationMixin
*/
export interface BelongsToCreateAssociationMixinOptions extends CreateOptions, BelongsToSetAssociationMixinOptions {}
/**
* The createAssociation mixin applied to models with belongsTo.
* An example of usage is as follows:
*
* ```js
*
* User.belongsTo(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttributes>, UserAttributes {
* // getRole...
* // setRole...
* createRole: Sequelize.BelongsToCreateAssociationMixin<RoleAttributes>;
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/belongs-to/
* @see Instance
*/
export type BelongsToCreateAssociationMixin<TModel> = (
values?: { [attribute: string]: any },
options?: BelongsToCreateAssociationMixinOptions
) => Promise<TModel>;
export default BelongsTo;
import { DataType } from '../data-types';
import { CreateOptions, FindOptions, Model, SaveOptions } from '../model';
import { Promise } from '../promise';
import { Association, AssociationOptions, SingleAssociationAccessors } from './base';
/**
* Options provided when associating models with hasOne relationship
*/
export interface HasOneOptions extends AssociationOptions {
/**
* A string or a data type to represent the identifier in the table
*/
keyType?: DataType;
}
export class HasOne extends Association {
public accessors: SingleAssociationAccessors;
constructor(source: typeof Model, target: typeof Model, options: HasOneOptions);
}
/**
* The options for the getAssociation mixin of the hasOne association.
* @see HasOneGetAssociationMixin
*/
export interface HasOneGetAssociationMixinOptions extends FindOptions {
/**
* Apply a scope on the related model, or remove its default scope by passing false.
*/
scope?: string | string[] | boolean;
}
/**
* The getAssociation mixin applied to models with hasOne.
* An example of usage is as follows:
*
* ```js
*
* User.hasOne(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttrib>, UserAttrib {
* getRole: Sequelize.HasOneGetAssociationMixin<RoleInstance>;
* // setRole...
* // createRole...
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/has-one/
* @see Instance
*/
export type HasOneGetAssociationMixin<TModel> = (options?: HasOneGetAssociationMixinOptions) => Promise<TModel>;
/**
* The options for the setAssociation mixin of the hasOne association.
* @see HasOneSetAssociationMixin
*/
export interface HasOneSetAssociationMixinOptions extends HasOneGetAssociationMixinOptions, SaveOptions {
/**
* Skip saving this after setting the foreign key if false.
*/
save?: boolean;
}
/**
* The setAssociation mixin applied to models with hasOne.
* An example of usage is as follows:
*
* ```js
*
* User.hasOne(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttributes>, UserAttributes {
* // getRole...
* setRole: Sequelize.HasOneSetAssociationMixin<RoleInstance, RoleId>;
* // createRole...
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/has-one/
* @see Instance
*/
export type HasOneSetAssociationMixin<TModel, TModelPrimaryKey> = (
newAssociation?: TModel | TModelPrimaryKey,
options?: HasOneSetAssociationMixinOptions
) => Promise<void>;
/**
* The options for the createAssociation mixin of the hasOne association.
* @see HasOneCreateAssociationMixin
*/
export interface HasOneCreateAssociationMixinOptions extends HasOneSetAssociationMixinOptions, CreateOptions {}
/**
* The createAssociation mixin applied to models with hasOne.
* An example of usage is as follows:
*
* ```js
*
* User.hasOne(Role);
*
* interface UserInstance extends Sequelize.Instance<UserInstance, UserAttributes>, UserAttributes {
* // getRole...
* // setRole...
* createRole: Sequelize.HasOneCreateAssociationMixin<RoleAttributes>;
* }
* ```
*
* @see http://docs.sequelizejs.com/en/latest/api/associations/has-one/
* @see Instance
*/
export type HasOneCreateAssociationMixin<TModel> = (
values?: { [attribute: string]: any },
options?: HasOneCreateAssociationMixinOptions
) => Promise<TModel>;
export * from './base';
export * from './belongs-to';
export * from './has-one';
export * from './has-many';
export * from './belongs-to-many';
import { Promise } from './promise';
export interface GetConnectionOptions {
/**
* Set which replica to use. Available options are `read` and `write`
*/
type: 'read' | 'write';
/**
* Force master or write replica to get connection from
*/
useMaster?: boolean;
}
export type Connection = object;
export interface ConnectionManager {
refreshTypeParser(dataTypes: object): void;
/**
* Drain the pool and close it permanently
*/
close(): Promise<void>;
/**
* Initialize connection pool. By default pool autostart is set to false, so no connection will be
* be created unless `pool.acquire` is called.
*/
initPools(): void;
/**
* Get connection from pool. It sets database version if it's not already set.
* Call pool.acquire to get a connection.
*/
getConnection(opts: GetConnectionOptions): Promise<Connection>;
/**
* Release a pooled connection so it can be utilized by other connection requests
*/
releaseConnection(conn: Connection): Promise<void>;
}
/**
* Can be used to
* make foreign key constraints deferrable and to set the constaints within a
* transaction. This is only supported in PostgreSQL.
*
* The foreign keys can be configured like this. It will create a foreign key
* that will check the constraints immediately when the data was inserted.
*
* ```js
* sequelize.define('Model', {
* foreign_id: {
* type: Sequelize.INTEGER,
* references: {
* model: OtherModel,
* key: 'id',
* deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
* }
* }
* });
* ```
*
* The constraints can be configured in a transaction like this. It will
* trigger a query once the transaction has been started and set the constraints
* to be checked at the very end of the transaction.
*
* ```js
* sequelize.transaction({
* deferrable: Sequelize.Deferrable.SET_DEFERRED
* });
* ```
*/
/**
*
*/
export interface AbstractDeferrableStatic {
new (): Deferrable;
(): Deferrable;
}
export interface Deferrable {
toString(): string;
toSql(): string;
}
export interface InitiallyDeferredDeferrableStatic extends AbstractDeferrableStatic {
new (): InitiallyDeferredDeferrable;
(): InitiallyDeferredDeferrable;
}
export interface InitiallyDeferredDeferrable extends Deferrable {}
export const INITIALLY_DEFERRED: InitiallyDeferredDeferrableStatic;
export interface InitiallyImmediateDeferrableStatic extends AbstractDeferrableStatic {
new (): InitiallyImmediateDeferrable;
(): InitiallyImmediateDeferrable;
}
export interface InitiallyImmediateDeferrable extends Deferrable {}
export const INITIALLY_IMMEDIATE: InitiallyImmediateDeferrableStatic;
export interface NotDeferrableStatic extends AbstractDeferrableStatic {
new (): NotDeferrable;
(): NotDeferrable;
}
export interface NotDeferrable extends Deferrable {}
/**
* Will set the constraints to not deferred. This is the default in PostgreSQL and it make
* it impossible to dynamically defer the constraints within a transaction.
*/
export const NOT: NotDeferrableStatic;
export interface SetDeferredDeferrableStatic extends AbstractDeferrableStatic {
/**
* @param constraints An array of constraint names. Will defer all constraints by default.
*/
new (constraints: string[]): SetDeferredDeferrable;
/**
* @param constraints An array of constraint names. Will defer all constraints by default.
*/
(constraints: string[]): SetDeferredDeferrable;
}
export interface SetDeferredDeferrable extends Deferrable {}
/**
* Will trigger an additional query at the beginning of a
* transaction which sets the constraints to deferred.
*/
export const SET_DEFERRED: SetDeferredDeferrableStatic;
export interface SetImmediateDeferrableStatic extends AbstractDeferrableStatic {
/**
* @param constraints An array of constraint names. Will defer all constraints by default.
*/
new (constraints: string[]): SetImmediateDeferrable;
/**
* @param constraints An array of constraint names. Will defer all constraints by default.
*/
(constraints: string[]): SetImmediateDeferrable;
}
export interface SetImmediateDeferrable extends Deferrable {}
/**
* Will trigger an additional query at the beginning of a
* transaction which sets the constraints to immediately.
*
* @param constraints An array of constraint names. Will defer all constraints by default.
*/
export const SET_IMMEDIATE: SetImmediateDeferrableStatic;
/**
* The Base Error all Sequelize Errors inherit from.
*/
export class BaseError extends Error {
public name: string;
}
/**
* Scope Error. Thrown when the sequelize cannot query the specified scope.
*/
export class SequelizeScopeError extends BaseError {}
export class ValidationError extends BaseError {
/** Array of ValidationErrorItem objects describing the validation errors */
public readonly errors: ValidationErrorItem[];
/**
* Validation Error. Thrown when the sequelize validation has failed. The error contains an `errors`
* property, which is an array with 1 or more ValidationErrorItems, one for each validation that failed.
*
* @param message Error message
* @param errors Array of ValidationErrorItem objects describing the validation errors
*/
constructor(message: string, errors?: ValidationErrorItem[]);
/**
* Gets all validation error items for the path / field specified.
*
* @param path The path to be checked for error items
*/
public get(path: string): ValidationErrorItem[];
}
export class ValidationErrorItem {
/** An error message */
public readonly message: string;
/** The type of the validation error */
public readonly type: string;
/** The field that triggered the validation error */
public readonly path: string;
/** The value that generated the error */
public readonly value: string;
public readonly original: Error;
/**
* Validation Error Item
* Instances of this class are included in the `ValidationError.errors` property.
*
* @param message An error message
* @param type The type of the validation error
* @param path The field that triggered the validation error
* @param value The value that generated the error
*/
constructor(message?: string, type?: string, path?: string, value?: string);
}
export interface CommonErrorProperties {
/** The database specific error which triggered this one */
readonly parent: Error;
/** The database specific error which triggered this one */
readonly original: Error;
/** The SQL that triggered the error */
readonly sql: string;
}
/**
* Thrown when a record was not found, Usually used with rejectOnEmpty mode (see message for details)
*/
export class EmptyResultError extends BaseError {
}
export class DatabaseError extends BaseError implements CommonErrorProperties {
public readonly parent: Error;
public readonly original: Error;
public readonly sql: string;
/**
* A base class for all database related errors.
* @param parent The database specific error which triggered this one
*/
constructor(parent: Error);
}
/** Thrown when a database query times out because of a deadlock */
export class TimeoutError extends DatabaseError {}
export interface UniqueConstraintErrorOptions {
parent?: Error;
message?: string;
errors?: ValidationErrorItem[];
fields?: { [key: string]: any };
original?: Error;
}
/**
* Thrown when a unique constraint is violated in the database
*/
export class UniqueConstraintError extends ValidationError implements CommonErrorProperties {
public readonly parent: Error;
public readonly original: Error;
public readonly sql: string;
public readonly fields: { [key: string]: any };
constructor(options?: UniqueConstraintErrorOptions);
}
/**
* Thrown when a foreign key constraint is violated in the database
*/
export class ForeignKeyConstraintError extends DatabaseError {
public table: string;
public fields: { [field: string]: string };
public value: any;
public index: string;
constructor(options: { parent?: Error; message?: string; index?: string; fields?: string[]; table?: string });
}
/**
* Thrown when an exclusion constraint is violated in the database
*/
export class ExclusionConstraintError extends DatabaseError {
public constraint: string;
public fields: { [field: string]: string };
public table: string;
constructor(options: { parent?: Error; message?: string; constraint?: string; fields?: string[]; table?: string });
}
/**
* A base class for all connection related errors.
*/
export class ConnectionError extends BaseError {
public parent: Error;
public original: Error;
constructor(parent: Error);
}
/**
* Thrown when a connection to a database is refused
*/
export class ConnectionRefusedError extends ConnectionError {}
/**
* Thrown when a connection to a database is refused due to insufficient privileges
*/
export class AccessDeniedError extends ConnectionError {}
/**
* Thrown when a connection to a database has a hostname that was not found
*/
export class HostNotFoundError extends ConnectionError {}
/**
* Thrown when a connection to a database has a hostname that was not reachable
*/
export class HostNotReachableError extends ConnectionError {}
/**
* Thrown when a connection to a database has invalid values for any of the connection parameters
*/
export class InvalidConnectionError extends ConnectionError {}
/**
* Thrown when a connection to a database times out
*/
export class ConnectionTimedOutError extends ConnectionError {}
import { ValidationOptions } from './instance-validator';
import Model, {
BulkCreateOptions,
CountOptions,
CreateOptions,
DestroyOptions,
FindOptions,
InstanceDestroyOptions,
InstanceUpdateOptions,
ModelAttributes,
ModelOptions,
UpdateOptions,
} from './model';
import { Config, Options, Sequelize, SyncOptions } from './sequelize';
export type HookReturn = Promise<void> | void;
/**
* Options for Model.init. We mostly duplicate the Hooks here, since there is no way to combine the two
* interfaces.
*/
export interface ModelHookOptions<M extends Model = Model> {
beforeValidate(instance: M, options: ValidationOptions): HookReturn;
afterValidate(instance: M, options: ValidationOptions): HookReturn;
beforeCreate(attributes: M, options: CreateOptions): HookReturn;
afterCreate(attributes: M, options: CreateOptions): HookReturn;
beforeDestroy(instance: M, options: InstanceDestroyOptions): HookReturn;
afterDestroy(instance: M, options: InstanceDestroyOptions): HookReturn;
beforeUpdate(instance: M, options: InstanceUpdateOptions): HookReturn;
afterUpdate(instance: M, options: InstanceUpdateOptions): HookReturn;
beforeBulkCreate(instances: M[], options: BulkCreateOptions): HookReturn;
afterBulkCreate(instances: M[], options: BulkCreateOptions): HookReturn;
beforeBulkDestroy(options: DestroyOptions): HookReturn;
afterBulkDestroy(options: DestroyOptions): HookReturn;
beforeBulkUpdate(options: UpdateOptions): HookReturn;
afterBulkUpdate(options: UpdateOptions): HookReturn;
beforeFind(options: FindOptions): HookReturn;
beforeCount(options: CountOptions): HookReturn;
beforeFindAfterExpandIncludeAll(options: FindOptions): HookReturn;
beforeFindAfterOptions(options: FindOptions): HookReturn;
afterFind(instancesOrInstance: M[] | M, options: FindOptions): HookReturn;
beforeSync(options: SyncOptions): HookReturn;
afterSync(options: SyncOptions): HookReturn;
beforeBulkSync(options: SyncOptions): HookReturn;
afterBulkSync(options: SyncOptions): HookReturn;
}
export interface AllModelHooks extends ModelHookOptions {
beforeDefine(attributes: ModelAttributes, options: ModelOptions<Model>): void;
afterDefine(model: typeof Model): void;
beforeInit(config: Config, options: Options): void;
afterInit(sequelize: Sequelize): void;
}
export interface SequelizeHooks extends AllModelHooks {
beforeConnect(config: Config): HookReturn;
afterConnect(connection: any, config: Config): HookReturn;
}
/**
* Virtual class for deduplication
*/
export class Hooks {
/**
* Add a hook to the model
*
* @param name Provide a name for the hook function. It can be used to remove the hook later or to order
* hooks based on some sort of priority system in the future.
*/
public static addHook<C extends typeof Hooks, K extends keyof SequelizeHooks>(
hookType: K,
name: string,
fn: SequelizeHooks[K]
): C;
public static addHook<C extends typeof Hooks, K extends keyof SequelizeHooks>(
hookType: K,
fn: SequelizeHooks[K]
): C;
/**
* Remove hook from the model
*/
public static removeHook<C extends typeof Hooks, K extends keyof SequelizeHooks>(hookType: K, name: string): C;
/**
* Check whether the mode has any hooks of this type
*/
public static hasHook<K extends keyof SequelizeHooks>(hookType: K): boolean;
public static hasHooks<K extends keyof SequelizeHooks>(hookType: K): boolean;
/**
* Add a hook to the model
*
* @param name Provide a name for the hook function. It can be used to remove the hook later or to order
* hooks based on some sort of priority system in the future.
*/
public addHook<K extends keyof SequelizeHooks>(hookType: K, name: string, fn: SequelizeHooks[K]): this;
public addHook<K extends keyof SequelizeHooks>(hookType: K, fn: SequelizeHooks[K]): this;
/**
* Remove hook from the model
*/
public removeHook<K extends keyof SequelizeHooks>(hookType: K, name: string): this;
/**
* Check whether the mode has any hooks of this type
*/
public hasHook<K extends keyof SequelizeHooks>(hookType: K): boolean;
public hasHooks<K extends keyof SequelizeHooks>(hookType: K): boolean;
}
export interface ValidationOptions {
/**
* An array of strings. All properties that are in this array will not be validated
*/
skip?: string[];
/**
* An array of strings. Only the properties that are in this array will be validated
*/
fields?: string[];
/**
* Run before and after validate hooks.
* @default true.
*/
hooks?: boolean;
}
import { Model } from './model';
import { Sequelize } from './sequelize';
export class ModelManager {
public sequelize: Sequelize;
public models: typeof Model[];
public all: typeof Model[];
constructor(sequelize: Sequelize);
public addModel<T extends typeof Model>(model: T): T;
public removeModel(model: typeof Model): void;
public getModel(against: any, options?: { attribute?: string }): typeof Model;
}
export default ModelManager;
/**
* object that holds all operator symbols
*/
declare const Op: {
readonly adjacent: unique symbol;
readonly all: unique symbol;
readonly and: unique symbol;
readonly any: unique symbol;
readonly between: unique symbol;
readonly col: unique symbol;
readonly contained: unique symbol;
readonly contains: unique symbol;
readonly endsWith: unique symbol;
readonly eq: unique symbol;
readonly gt: unique symbol;
readonly gte: unique symbol;
readonly iLike: unique symbol;
readonly in: unique symbol;
readonly iRegexp: unique symbol;
readonly is: unique symbol;
readonly like: unique symbol;
readonly lt: unique symbol;
readonly lte: unique symbol;
readonly ne: unique symbol;
readonly noExtendLeft: unique symbol;
readonly noExtendRight: unique symbol;
readonly not: unique symbol;
readonly notBetween: unique symbol;
readonly notILike: unique symbol;
readonly notIn: unique symbol;
readonly notIRegexp: unique symbol;
readonly notLike: unique symbol;
readonly notRegexp: unique symbol;
readonly or: unique symbol;
readonly overlap: unique symbol;
readonly placeholder: unique symbol;
readonly regexp: unique symbol;
readonly startsWith: unique symbol;
readonly strictLeft: unique symbol;
readonly strictRight: unique symbol;
readonly substring: unique symbol;
};
export = Op;
// tslint:disable-next-line:no-implicit-dependencies
import * as Bluebird from 'bluebird';
export const Promise: typeof Bluebird;
export type Promise<T> = Bluebird<T>;
export default Promise;
declare enum QueryTypes {
SELECT = 'SELECT',
INSERT = 'INSERT',
UPDATE = 'UPDATE',
BULKUPDATE = 'BULKUPDATE',
BULKDELETE = 'BULKDELETE',
DELETE = 'DELETE',
UPSERT = 'UPSERT',
VERSION = 'VERSION',
SHOWTABLES = 'SHOWTABLES',
SHOWINDEXES = 'SHOWINDEXES',
DESCRIBE = 'DESCRIBE',
RAW = 'RAW',
FOREIGNKEYS = 'FOREIGNKEYS',
}
export = QueryTypes;
export type Escapable = undefined | null | boolean | number | string | Date;
export function escapeId(val: string, forbidQualified?: boolean): string;
export function escape(val: Escapable | Escapable[], timeZone?: string, dialect?: string, format?: string): string;
export function format(sql: string, values: any[], timeZone?: string, dialect?: string): string;
export function formatNamedParameters(sql: string, values: any[], timeZone?: string, dialect?: string): string;
declare enum TableHints {
NOLOCK = 'NOLOCK',
READUNCOMMITTED = 'READUNCOMMITTED',
UPDLOCK = 'UPDLOCK',
REPEATABLEREAD = 'REPEATABLEREAD',
SERIALIZABLE = 'SERIALIZABLE',
READCOMMITTED = 'READCOMMITTED',
TABLOCK = 'TABLOCK',
TABLOCKX = 'TABLOCKX',
PAGLOCK = 'PAGLOCK',
ROWLOCK = 'ROWLOCK',
NOWAIT = 'NOWAIT',
READPAST = 'READPAST',
XLOCK = 'XLOCK',
SNAPSHOT = 'SNAPSHOT',
NOEXPAND = 'NOEXPAND',
}
export = TableHints;
import { Deferrable } from './deferrable';
import { Logging } from './model';
import { Promise } from './promise';
import { Sequelize } from './sequelize';
/**
* The transaction object is used to identify a running transaction. It is created by calling
* `Sequelize.transaction()`.
*
* To run a query under a transaction, you should pass the transaction in the options object.
*/
export class Transaction {
constructor(sequelize: Sequelize, options: TransactionOptions);
/**
* Commit the transaction
*/
public commit(): Promise<void>;
/**
* Rollback (abort) the transaction
*/
public rollback(): Promise<void>;
/**
* Adds hook that is run after a transaction is committed
*/
public afterCommit(fn: (transaction: this) => void | Promise<void>): void;
}
// tslint:disable-next-line no-namespace
export namespace Transaction {
/**
* Isolations levels can be set per-transaction by passing `options.isolationLevel` to `sequelize.transaction`.
* Default to `REPEATABLE_READ` but you can override the default isolation level by passing `options.isolationLevel` in `new Sequelize`.
*
* The possible isolations levels to use when starting a transaction:
*
* ```js
* {
* READ_UNCOMMITTED: "READ UNCOMMITTED",
* READ_COMMITTED: "READ COMMITTED",
* REPEATABLE_READ: "REPEATABLE READ",
* SERIALIZABLE: "SERIALIZABLE"
* }
* ```
*
* Pass in the desired level as the first argument:
*
* ```js
* return sequelize.transaction({isolationLevel: Sequelize.Transaction.SERIALIZABLE}, transaction => {
*
* // your transactions
*
* }).then(result => {
* // transaction has been committed. Do something after the commit if required.
* }).catch(err => {
* // do something with the err.
* });
* ```
*/
const enum ISOLATION_LEVELS {
READ_UNCOMMITTED = 'READ UNCOMMITTED',
READ_COMMITTED = 'READ COMMITTED',
REPEATABLE_READ = 'REPEATABLE READ',
SERIALIZABLE = 'SERIALIZABLE',
}
const enum TYPES {
DEFERRED = 'DEFERRED',
IMMEDIATE = 'IMMEDIATE',
EXCLUSIVE = 'EXCLUSIVE',
}
/**
* Possible options for row locking. Used in conjunction with `find` calls:
*
* ```js
* t1 // is a transaction
* t1.LOCK.UPDATE,
* t1.LOCK.SHARE,
* t1.LOCK.KEY_SHARE, // Postgres 9.3+ only
* t1.LOCK.NO_KEY_UPDATE // Postgres 9.3+ only
* ```
*
* Usage:
* ```js
* t1 // is a transaction
* Model.findAll({
* where: ...,
* transaction: t1,
* lock: t1.LOCK...
* });
* ```
*
* Postgres also supports specific locks while eager loading by using OF:
* ```js
* UserModel.findAll({
* where: ...,
* include: [TaskModel, ...],
* transaction: t1,
* lock: {
* level: t1.LOCK...,
* of: UserModel
* }
* });
* ```
* UserModel will be locked but TaskModel won't!
*/
const enum LOCK {
UPDATE = 'UPDATE',
SHARE = 'SHARE',
/**
* Postgres 9.3+ only
*/
KEY_SHARE = 'KEY SHARE',
/**
* Postgres 9.3+ only
*/
NO_KEY_UPDATE = 'NO KEY UPDATE',
}
}
/**
* Options provided when the transaction is created
*/
export interface TransactionOptions extends Logging {
autocommit?: boolean;
isolationLevel?: Transaction.ISOLATION_LEVELS;
type?: Transaction.TYPES;
deferrable?: string | Deferrable;
}
export default Transaction;
import { DataType } from './data-types';
export type Primitive = 'string' | 'number' | 'boolean';
export interface Inflector {
singularize(str: string): string;
pluralize(str: string): string;
}
export function useInflection(inflection: Inflector): void;
export function camelizeIf(string: string, condition?: boolean): string;
export function underscoredIf(string: string, condition?: boolean): string;
export function isPrimitive(val: unknown): val is Primitive;
/** Same concept as _.merge, but don't overwrite properties that have already been assigned */
export function mergeDefaults<T>(a: T, b: Partial<T>): T;
export function spliceStr(str: string, index: number, count: number, add: string): string;
export function camelize(str: string): string;
export function format(arr: string[], dialect: string): string;
export function formatNamedParameters(sql: string, parameters: {
[key: string]: string | number | boolean;
}, dialect: string): string;
export function cloneDeep<T>(obj: T, fn?: (el: any) => any): T;
/** Expand and normalize finder options */
export function mapFinderOptions(options: any, Model: any): any;
/* Used to map field names in attributes and where conditions */
export function mapOptionFieldNames(options: any, Model: any): any;
export function mapWhereFieldNames(attributes: any, Model: any): any;
/** Used to map field names in values */
export function mapValueFieldNames(dataValues: any, fields: any, Model: any): any;
export function isColString(value: string): boolean;
export function canTreatArrayAsAnd(arr: unknown[]): boolean;
export function combineTableNames(tableName1: string, tableName2: string): string;
export function singularize(s: string): string;
export function pluralize(s: string): string;
export function toDefaultValue(value: any): any;
/**
* Determine if the default value provided exists and can be described
* in a db schema using the DEFAULT directive.
*
* @param value Any default value.
*/
export function defaultValueSchemable(hash: DataType): boolean;
export function stack(): NodeJS.CallSite[];
export function now(dialect: string): Date;
// Note: Use the `quoteIdentifier()` and `escape()` methods on the
// `QueryInterface` instead for more portable code.
export const TICK_CHAR: string;
export function addTicks(s: string, tickChar?: string): string;
export function removeTicks(s: string, tickChar?: string): string;
export class SequelizeMethod {
}
/*
* Utility functions for representing SQL functions, and columns that should be escaped.
* Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
*/
export class Fn extends SequelizeMethod {
constructor(fn: string, args: any);
public clone(): this;
}
export class Col extends SequelizeMethod {
public col: string;
constructor(col: string);
}
export class Cast extends SequelizeMethod {
public val: any;
public type: string;
constructor(val: any, type?: string);
}
export class Literal extends SequelizeMethod {
public val: any;
constructor(val: any);
}
export class Json extends SequelizeMethod {
public conditions: object;
public path: string;
public value: string | number | boolean;
constructor(conditionsOrPath: string | object, value?: string | number | boolean);
}
export class Where extends SequelizeMethod {
public attribute: object;
public comparator: string;
public logic: string | object;
constructor(attr: object, comparator: string, logic: string | object);
constructor(attr: object, logic: string | object);
}
export { Promise } from './promise';
export interface LoggerConfig {
/**
* @default `sequelize`
*/
context?: string;
/**
* @default `true`
*/
debug?: boolean;
}
export class Logger {
constructor(config: LoggerConfig)
public deprecate(message: string): void;
public debug(message: string): void;
public warn(message: string): void;
public debugContext(message: string): (message: string) => void;
}
export function deprecate(message: string): void;
export function warn(message: string): void;
export function getLogger(): Logger;
// tslint:disable-next-line:no-implicit-dependencies
import * as val from 'validator';
type OrigValidator = typeof val;
export interface Extensions {
notEmpty(str: string): boolean;
len(str: string, min: number, max: number): boolean;
isUrl(str: string): boolean;
isIPv6(str: string): boolean;
isIPv4(str: string): boolean;
notIn(str: string, values: string[]): boolean;
regex(str: string, pattern: string, modifiers: string): boolean;
notRegex(str: string, pattern: string, modifiers: string): boolean;
min(str: string, val: number): boolean;
max(str: string, val: number): boolean;
not(str: string, pattern: string, modifiers: string): boolean;
contains(str: string, elem: string[]): boolean;
notContains(str: string, elem: string[]): boolean;
is(str: string, pattern: string, modifiers: string): boolean;
}
export const extensions: Extensions;
export interface Validator extends OrigValidator, Extensions {
contains(str: string, elem: string[]): boolean;
}
export const validator: Validator;
import { QueryTypes, Sequelize, SyncOptions } from 'sequelize';
export const sequelize = new Sequelize('uri');
sequelize.afterBulkSync((options: SyncOptions) => {
console.log('synced');
});
sequelize
.query('SELECT * FROM `test`', {
type: QueryTypes.SELECT,
})
.then(rows => {
rows.forEach(row => {
console.log(row);
});
});
sequelize
.query('INSERT into test set test=1', {
type: QueryTypes.INSERT,
})
.then(([aiId, affected]) => {
console.log(aiId, affected);
});
import { DataTypes, Model } from 'sequelize';
import { sequelize } from './connection';
// I really wouldn't recommend this, but if you want you can still use define() and interfaces
interface User extends Model {
id: number;
username: string;
firstName: string;
lastName: string;
createdAt: Date;
updatedAt: Date;
}
type UserModel = {
new (): User
customStaticMethod(): any
} & typeof Model;
const User = sequelize.define('User', { firstName: DataTypes.STRING }, { tableName: 'users' }) as UserModel;
async function test() {
User.customStaticMethod();
const user: User = new User();
const user2: User = (await User.findOne()) as User;
user2.firstName = 'John';
await user2.save();
}
// Error === BaseError
import { BaseError, EmptyResultError, Error, UniqueConstraintError } from 'sequelize';
import { User } from './models/User';
async function test() {
try {
await User.create({ username: 'john_doe' });
} catch (e) {
if (e instanceof UniqueConstraintError) {
console.error((e as UniqueConstraintError).sql);
}
}
try {
await User.findOne({
rejectOnEmpty: true,
where: {
username: 'something_that_doesnt_exist',
},
});
} catch (e) {
if (!(e instanceof EmptyResultError)) {
console.error('should return emptyresulterror');
}
}
}
import { User } from './models/User';
User.findByPk(Buffer.from('asdf'));
import { Model, Sequelize } from 'sequelize';
class MyModel extends Model {}
class AssociatedModel extends Model {}
MyModel.findAll({
include: [
{
limit: 1,
model: AssociatedModel,
order: [['id', 'DESC']],
separate: true,
where: { state: Sequelize.col('project.state') },
},
],
});
MyModel.findAll({
include: [{ all: true }],
});
import {
BelongsTo,
BelongsToCreateAssociationMixin,
BelongsToGetAssociationMixin,
BelongsToSetAssociationMixin,
DataTypes,
FindOptions,
Model,
} from 'sequelize';
import { sequelize } from '../connection';
export class User extends Model {
public static associations: {
group: BelongsTo
};
public id: number;
public username: string;
public firstName: string;
public lastName: string;
public createdAt: Date;
public updatedAt: Date;
// mixins for association (optional)
public groupId: number;
public group: UserGroup;
public getGroup: BelongsToGetAssociationMixin<UserGroup>;
public setGroup: BelongsToSetAssociationMixin<UserGroup, number>;
public createGroup: BelongsToCreateAssociationMixin<UserGroup>;
}
User.init(
{
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
username: DataTypes.STRING,
},
{
scopes: {
custom(a: number) {
return {
where: {
firstName: a,
},
};
}
},
sequelize,
}
);
// Hooks
User.afterFind((users, options) => {
console.log('found');
});
// TODO: VSCode shows the typing being correctly narrowed but doesn't do it correctly
User.addHook('beforeFind', 'test', (options: FindOptions) => {
return undefined;
});
// associate
// it is important to import _after_ the model above is already exported so the circular reference works.
import { UserGroup } from './UserGroup';
export const Group = User.belongsTo(UserGroup, { as: 'group', foreignKey: 'groupId' });
import {
DataTypes,
HasMany,
HasManyAddAssociationMixin,
HasManyAddAssociationsMixin,
HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin,
HasManyGetAssociationsMixin,
HasManyHasAssociationMixin,
HasManyRemoveAssociationMixin,
HasManyRemoveAssociationsMixin,
HasManySetAssociationsMixin,
Model,
} from 'sequelize';
import { sequelize } from '../connection';
export class UserGroup extends Model {
public static associations: {
users: HasMany
};
public id: number;
public name: string;
// mixins for association (optional)
public users: User[];
public getUsers: HasManyGetAssociationsMixin<User>;
public setUsers: HasManySetAssociationsMixin<User, number>;
public addUser: HasManyAddAssociationMixin<User, number>;
public addUsers: HasManyAddAssociationsMixin<User, number>;
public createUser: HasManyCreateAssociationMixin<number>;
public countUsers: HasManyCountAssociationsMixin;
public hasUser: HasManyHasAssociationMixin<User, number>;
public removeUser: HasManyRemoveAssociationMixin<User, number>;
public removeUsers: HasManyRemoveAssociationsMixin<User, number>;
}
// attach all the metadata to the model
// instead of this, you could also use decorators
UserGroup.init({ name: DataTypes.STRING }, { sequelize });
// associate
// it is important to import _after_ the model above is already exported so the circular reference works.
import { User } from './User';
export const Users = UserGroup.hasMany(User, { as: 'users', foreignKey: 'groupId' });
import { Promise } from 'sequelize';
let promise: Promise<number> = Promise.resolve(1);
promise.then((arg: number) => ({})).then((a: {}) => void 0);
promise = new Promise<number>(resolve => resolve());
import { DataTypes } from 'sequelize';
// tslint:disable-next-line:no-submodule-imports
import { QueryInterface } from 'sequelize/lib/query-interface';
declare let queryInterface: QueryInterface;
queryInterface.createTable(
'nameOfTheNewTable',
{
attr1: DataTypes.STRING,
attr2: DataTypes.INTEGER,
attr3: {
allowNull: false,
defaultValue: false,
type: DataTypes.BOOLEAN,
},
// foreign key usage
attr4: {
onDelete: 'cascade',
onUpdate: 'cascade',
references: {
key: 'id',
model: 'another_table_name',
},
type: DataTypes.INTEGER,
},
createdAt: {
type: DataTypes.DATE,
},
id: {
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
updatedAt: {
type: DataTypes.DATE,
},
},
{
charset: 'latin1', // default: null
collate: 'latin1_general_ci',
engine: 'MYISAM', // default: 'InnoDB'
uniqueKeys: {
test: {
customIndex: true,
fields: ['attr2', 'attr3'],
}
}
}
);
queryInterface.dropTable('nameOfTheExistingTable');
queryInterface.dropAllTables();
queryInterface.renameTable('Person', 'User');
queryInterface.showAllTables().then(tableNames => {
// do nothing
});
queryInterface.describeTable('Person').then(attributes => {
/*
attributes will be something like:
{
name: {
type: 'VARCHAR(255)', // this will be 'CHARACTER VARYING' for pg!
allowNull: true,
defaultValue: null
},
isBetaMember: {
type: 'TINYINT(1)', // this will be 'BOOLEAN' for pg!
allowNull: false,
defaultValue: false
}
}
*/
});
queryInterface.addColumn('nameOfAnExistingTable', 'nameOfTheNewAttribute', DataTypes.STRING);
// or
queryInterface.addColumn(
{ tableName: 'nameOfAnExistingTable', schema: 'nameOfSchema' },
'nameOfTheNewAttribute',
DataTypes.STRING
);
// or
queryInterface.addColumn('nameOfAnExistingTable', 'nameOfTheNewAttribute', {
allowNull: false,
type: DataTypes.STRING,
});
queryInterface.removeColumn('Person', 'signature');
// or
queryInterface.removeColumn({ tableName: 'Person', schema: 'nameOfSchema' }, 'signature');
queryInterface.changeColumn('nameOfAnExistingTable', 'nameOfAnExistingAttribute', {
allowNull: false,
defaultValue: 0.0,
type: DataTypes.FLOAT,
});
// or
queryInterface.changeColumn(
{ tableName: 'nameOfAnExistingTable', schema: 'nameOfSchema' },
'nameOfAnExistingAttribute',
{
allowNull: false,
defaultValue: 0.0,
type: DataTypes.FLOAT,
}
);
queryInterface.renameColumn('Person', 'signature', 'sig');
// This example will create the index person_firstname_lastname
queryInterface.addIndex('Person', ['firstname', 'lastname']);
// This example will create a unique index with the name SuperDuperIndex using the optional 'options' field.
// Possible options:
// - indicesType: UNIQUE|FULLTEXT|SPATIAL
// - indexName: The name of the index. Default is __
// - parser: For FULLTEXT columns set your parser
// - indexType: Set a type for the index, e.g. BTREE. See the documentation of the used dialect
// - logging: A function that receives the sql query, e.g. console.log
queryInterface.addIndex('Person', ['firstname', 'lastname'], {
indexName: 'SuperDuperIndex',
indicesType: 'UNIQUE',
});
queryInterface.removeIndex('Person', 'SuperDuperIndex');
// or
queryInterface.removeIndex('Person', ['firstname', 'lastname']);
queryInterface.addConstraint('Person', ['firstname', 'lastname'], {
name: 'firstnamexlastname',
type: 'unique',
});
queryInterface.removeConstraint('Person', 'firstnamexlastname');
import { Config, Sequelize } from 'sequelize';
export const sequelize = new Sequelize('uri');
const conn = sequelize.connectionManager;
// hooks
sequelize.beforeCreate('test', () => {
// noop
});
sequelize
.addHook('beforeConnect', (config: Config) => {
// noop
})
.addHook('beforeBulkSync', () => {
// noop
});
Sequelize.addHook('beforeCreate', () => {
// noop
}).addHook('beforeBulkCreate', () => {
// noop
});
import { Deferrable, Sequelize, Transaction } from 'sequelize';
import { User } from './models/User';
export const sequelize = new Sequelize('uri');
async function trans() {
const a: number = await sequelize.transaction(async transaction => {
transaction.afterCommit(() => console.log('transaction complete'));
User.create(
{
data: 123,
},
{
transaction,
}
);
return 1;
});
}
async function transact() {
const t = await sequelize.transaction({
deferrable: Deferrable.SET_DEFERRED(['test']),
isolationLevel: Transaction.ISOLATION_LEVELS.READ_COMMITTED,
type: Transaction.TYPES.DEFERRED,
});
await t.commit();
await t.rollback();
}
transact();
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noEmit": true,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": ".",
"paths": {
"sequelize": ["../"],
"sequelize/*": ["../"]
},
"types": ["node"],
"lib": ["es2016"]
},
"include": ["../index.d.ts", "./**/sequelize.d.ts", "./**/*.ts"]
}
import { Group, User } from './models/User';
async function test(): Promise<void> {
let user = await User.findOne({ include: [Group] });
if (!user) {
return;
}
User.update({}, { where: {} });
user.firstName = 'John';
await user.save();
await user.setGroup(2);
user = new User();
user = new User({ firstName: 'John' });
user = await User.findOne();
const user2 = await User.create({ firstName: 'John', groupId: 1 });
await User.findAndCountAll({ distinct: true });
}
import { AndOperator, fn, Model, Op, OrOperator, Sequelize, WhereOperators, WhereOptions } from 'sequelize';
import Transaction from '../lib/transaction';
class MyModel extends Model {
public hi: number;
}
let where: WhereOptions;
// From http://docs.sequelizejs.com/en/v4/docs/querying/
// Operators
const and: AndOperator = {
[Op.and]: { a: 5 }, // AND (a = 5)
};
const or: OrOperator = {
[Op.or]: [{ a: 5 }, { a: 6 }], // (a = 5 OR a = 6)
};
let operators: WhereOperators = {
[Op.gt]: 6, // > 6
[Op.gte]: 6, // >= 6
[Op.lt]: 10, // < 10
[Op.lte]: 10, // <= 10
[Op.ne]: 20, // != 20
[Op.not]: true, // IS NOT TRUE
[Op.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat', // NOT LIKE '%hat'
[Op.iLike]: '%hat', // ILIKE '%hat' (case insensitive) (PG only)
[Op.notILike]: '%hat', // NOT ILIKE '%hat' (PG only)
[Op.startsWith]: 'hat',
[Op.endsWith]: 'hat',
[Op.substring]: 'hat',
[Op.overlap]: [1, 2], // && [1, 2] (PG array overlap operator)
[Op.contains]: [1, 2], // @> [1, 2] (PG array contains operator)
[Op.contained]: [1, 2], // <@ [1, 2] (PG array contained by operator)
[Op.any]: [2, 3], // ANY ARRAY[2, 3]::INTEGER (PG only)
};
operators = {
[Op.like]: { [Op.any]: ['cat', 'hat'] }, // LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
};
// Combinations
MyModel.findOne({ where: or });
MyModel.findOne({ where: and });
where = Sequelize.and();
where = Sequelize.or();
where = { [Op.and]: [] };
where = {
rank: Sequelize.and({ [Op.lt]: 1000 }, { [Op.eq]: null }),
};
where = {
rank: Sequelize.or({ [Op.lt]: 1000 }, { [Op.eq]: null }),
};
where = {
rank: {
[Op.or]: {
[Op.lt]: 1000,
[Op.eq]: null,
},
},
};
// rank < 1000 OR rank IS NULL
where = {
createdAt: {
[Op.lt]: new Date(),
[Op.gt]: new Date(Date.now() - 24 * 60 * 60 * 1000),
},
};
// createdAt < [timestamp] AND createdAt > [timestamp]
where = {
[Op.or]: [
{
title: {
[Op.like]: 'Boat%',
},
},
{
description: {
[Op.like]: '%boat%',
},
},
],
};
// title LIKE 'Boat%' OR description LIKE '%boat%'
// Containment
where = {
meta: {
[Op.contains]: {
site: {
url: 'http://google.com',
},
},
},
};
// Relations / Associations
// Find all projects with a least one task where task.state === project.task
MyModel.findAll({
include: [
{
model: MyModel,
where: { state: Sequelize.col('project.state') },
},
],
});
MyModel.findOne({
include: [
{
include: [{ model: MyModel, where }],
model: MyModel,
where,
},
],
where,
});
MyModel.destroy({ where });
MyModel.update({ hi: 1 }, { where });
// From http://docs.sequelizejs.com/en/v4/docs/models-usage/
// find multiple entries
MyModel.findAll().then(projects => {
// projects will be an array of all MyModel instances
});
// search for specific attributes - hash usage
MyModel.findAll({ where: { name: 'A MyModel', enabled: true } }).then(projects => {
// projects will be an array of MyModel instances with the specified name
});
// search within a specific range
MyModel.findAll({ where: { id: [1, 2, 3] } }).then(projects => {
// projects will be an array of MyModels having the id 1, 2 or 3
// this is actually doing an IN query
});
// locks
MyModel.findAll({ lock: Transaction.LOCK.KEY_SHARE }).then(projects => {
// noop
});
// locks on model
MyModel.findAll({ lock: { level: Transaction.LOCK.KEY_SHARE, of: MyModel} }).then(projects => {
// noop
});
MyModel.findAll({
where: {
// tslint:disable-next-line:no-object-literal-type-assertion
id: {
// casting here to check a missing operator is not accepted as field name
[Op.and]: { a: 5 }, // AND (a = 5)
[Op.or]: [{ a: 5 }, { a: 6 }], // (a = 5 OR a = 6)
[Op.gt]: 6, // id > 6
[Op.gte]: 6, // id >= 6
[Op.lt]: 10, // id < 10
[Op.lte]: 10, // id <= 10
[Op.ne]: 20, // id != 20
[Op.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat', // NOT LIKE '%hat'
[Op.iLike]: '%hat', // ILIKE '%hat' (case insensitive) (PG only)
[Op.notILike]: '%hat', // NOT ILIKE '%hat' (PG only)
[Op.overlap]: [1, 2], // && [1, 2] (PG array overlap operator)
[Op.contains]: [1, 2], // @> [1, 2] (PG array contains operator)
[Op.contained]: [1, 2], // <@ [1, 2] (PG array contained by operator)
[Op.any]: [2, 3], // ANY ARRAY[2, 3]::INTEGER (PG only)
} as WhereOperators,
status: {
[Op.not]: false, // status NOT FALSE
},
},
});
// Complex filtering / NOT queries
where = {
name: 'a project',
[Op.or]: [{ id: [1, 2, 3] }, { id: { [Op.gt]: 10 } }],
};
where = {
id: {
[Op.or]: [[1, 2, 3], { [Op.gt]: 10 }],
},
name: 'a project',
};
where = {
name: 'a project',
type: {
[Op.and]: [['a', 'b'], { [Op.notLike]: '%z' }],
},
};
// [Op.not] example:
where = {
name: 'a project',
[Op.not]: [{ id: [1, 2, 3] }, { array: { [Op.contains]: [3, 4, 5] } }],
};
// JSONB
// Nested object
where = {
meta: {
video: {
url: {
[Op.ne]: null,
},
},
},
};
// Nested key
where = {
'meta.audio.length': {
[Op.gt]: 20,
},
};
// Operator symbols
where = {
[Op.and]: [{ id: [1, 2, 3] }, { array: { [Op.contains]: [3, 4, 5] } }],
};
// Fn as value
where = {
[Op.gt]: fn('NOW'),
};
{
"compilerOptions": {
"strict": true,
"module": "commonjs",
"moduleResolution": "node",
"noEmit": true,
"lib": ["es2016"]
},
"types": ["node"],
"include": ["lib/**/*.d.ts", "index.d.ts"]
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!