sequelize-mv-support
Version:
Adds materialized views support to Sequelize.
138 lines (121 loc) • 3.71 kB
text/typescript
import {
DropOptions,
Model as ModelOrig,
ModelOptions,
SyncOptions,
} from 'sequelize';
import type { Sequelize, QueryInterfaceWithViews } from './SequelizeWithViews';
/**
* Interface describing the options property on a model
*
* @export
* @interface ModelOptionsWithViews
* @extends {ModelOptions}
*/
export interface ModelOptionsWithViews<M extends ModelOrig>
extends ModelOptions<M> {
treatAsView?: boolean;
treatAsMaterializedView?: boolean;
viewDefinition?: string;
materializedViewDefinition?: string;
}
export type DropOptionsType = DropOptions & {
treatAsView?: boolean;
treatAsMaterializedView?: boolean;
viewDefinition?: string;
};
export type OptionsType = ModelOptionsWithViews<ModelOrig> & {
sequelize: Sequelize;
};
/**
* Model with view support added
*
* @export
* @class Model
* @extends {ModelOrig}
*/
export class Model<
/* eslint-disable @typescript-eslint/ban-types */
TModelAttributes extends {} = any,
TCreationAttributes extends {} = TModelAttributes
/* eslint-enable @typescript-eslint/ban-types */
> extends ModelOrig<TModelAttributes, TCreationAttributes> {
/** @inheritdoc */
public static override readonly options: OptionsType;
/** @inheritdoc */
public static queryInterface: QueryInterfaceWithViews;
/** @inheritdoc */
public static override drop(options: DropOptionsType = {}): any {
const method = this.options.treatAsView
? 'dropView'
: this.options.treatAsMaterializedView
? 'dropMaterializedView'
: 'dropTable';
return this.queryInterface[method](this.getTableName(), options);
}
/** @inheritdoc */
public static override sync(options: SyncOptions): any {
if (this.options.treatAsView || this.options.treatAsMaterializedView)
return Promise.resolve();
return super.sync(options);
}
/**
* Executes the query to create a view
*
* @static
* @returns {Promise<[unknown[], unknown]>} Result of the create view request
* @memberof Model
*/
public static syncView(): Promise<[unknown[], unknown]> {
const definition = this.getViewDefinition();
if (!definition) throw new Error('cannot sync view with no definition');
return this.queryInterface.createView(this.getTableName(), definition);
}
/**
* Executes the query to create a materialized view
*
* @static
* @returns {Promise<[unknown[], unknown]>} Result of the create materialized view request
* @memberof Model
*/
public static syncMaterializedView(): Promise<[unknown[], unknown]> {
const definition = this.getMaterializedViewDefinition();
if (!definition)
throw new Error('cannot sync materialised view with no definition');
return this.queryInterface.createMaterializedView(
this.getTableName(),
definition
);
}
/**
* Gets the sql definition for this view
*
* @static
* @returns {string} SQL query string to create a view
* @memberof Model
*/
public static getViewDefinition(): string | undefined {
return this.options.viewDefinition;
}
/**
* Gets the sql definition for this materialized view
*
* @static
* @returns {string} SQL query string to create the materialized view
* @memberof Model
*/
public static getMaterializedViewDefinition(): string | undefined {
return this.options.materializedViewDefinition;
}
/**
* Refreshes the materialized view in the database
*
* @static
* @returns {Promise<[unknown[], unknown]>}
* @memberof Model
*/
public static refreshMaterializedView(): Promise<[unknown[], unknown]> {
return this.queryInterface.refreshMaterializedView(this.getTableName());
}
}
export default Model;