Skip to content

Commit

Permalink
feat(types): migrate model-manager to TypeScript (#16070)
Browse files Browse the repository at this point in the history
Co-authored-by: Luke Hart <50547373+lohart13@users.noreply.github.com>
Co-authored-by: Rik Smale <13023439+WikiRik@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 9, 2023
1 parent 40ed9e1 commit 605150e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 46 deletions.
24 changes: 0 additions & 24 deletions packages/core/src/model-manager.d.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
'use strict';

import defaults from 'lodash/defaults';

const Toposort = require('toposort-class');
// @ts-expect-error -- toposort-class definition will be added to sequelize/toposort later
import Toposort from 'toposort-class';
import type { ModelStatic } from './model';
import type { Sequelize } from './sequelize';

export class ModelManager {
constructor(sequelize) {
#sequelize: Sequelize;
declare models: ModelStatic[];

constructor(sequelize: Sequelize) {
this.models = [];
this.sequelize = sequelize;
this.#sequelize = sequelize;
}

addModel(model) {
addModel<T extends ModelStatic>(model: T): T {
this.models.push(model);
this.sequelize.models[model.name] = model;
this.#sequelize.models[model.name] = model;

return model;
}

removeModel(modelToRemove) {
this.models = this.models.filter(model => model.name !== modelToRemove.name);
removeModel(modelToRemove: ModelStatic): void {
this.models = this.models.filter(
model => model.name !== modelToRemove.name,
);

delete this.sequelize.models[modelToRemove.name];
delete this.#sequelize.models[modelToRemove.name];
}

getModel(modelName) {
getModel(modelName: string): ModelStatic | undefined {
return this.models.find(model => model.name === modelName);
}

findModel(callback) {
findModel(
callback: (model: ModelStatic) => boolean,
): ModelStatic | undefined {
return this.models.find(callback);
}

hasModel(targetModel) {
hasModel(targetModel: ModelStatic): boolean {
return this.models.includes(targetModel);
}

get all() {
get all(): ModelStatic[] {
return this.models;
}

Expand All @@ -46,11 +55,11 @@ export class ModelManager {
*
* If there is a cyclic dependency, this returns null.
*/
getModelsTopoSortedByForeignKey() {
getModelsTopoSortedByForeignKey(): ModelStatic[] | null {
const models = new Map();
const sorter = new Toposort();

const queryGenerator = this.sequelize.queryInterface.queryGenerator;
const queryGenerator = this.#sequelize.queryInterface.queryGenerator;

for (const model of this.models) {
let deps = [];
Expand All @@ -62,7 +71,7 @@ export class ModelManager {
for (const attrName of attributes.keys()) {
const attribute = attributes.get(attrName);

if (!attribute.references) {
if (!attribute?.references) {
continue;
}

Expand All @@ -78,16 +87,19 @@ export class ModelManager {
let sorted;
try {
sorted = sorter.sort();
} catch (error) {
if (!error.message.startsWith('Cyclic dependency found.')) {
} catch (error: unknown) {
if (
error instanceof Error
&& !error.message.startsWith('Cyclic dependency found.')
) {
throw error;
}

return null;
}

return sorted
.map(modelName => {
.map((modelName: string) => {
return models.get(modelName);
})
.filter(Boolean);
Expand All @@ -97,13 +109,17 @@ export class ModelManager {
* Iterate over Models in an order suitable for e.g. creating tables.
* Will take foreign key constraints into account so that dependencies are visited before dependents.
*
* @param {Function} iterator method to execute on each model
* @param {object} options
* @param iterator method to execute on each model
* @param options
* @param options.reverse
* @private
*
* @deprecated
*/
forEachModel(iterator, options) {
forEachModel(
iterator: (model: ModelStatic) => void,
options?: { reverse?: boolean },
) {
const sortedModels = this.getModelsTopoSortedByForeignKey();
if (sortedModels == null) {
throw new Error('Cyclic dependency found.');
Expand Down

0 comments on commit 605150e

Please sign in to comment.