SequelizeStorage.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _Storage = _interopRequireDefault(require("./Storage"));
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. /**
  9. * @class SequelizeStorage
  10. */
  11. class SequelizeStorage extends _Storage.default {
  12. /**
  13. * Constructs Sequelize based storage.
  14. *
  15. * Stores migration in a database table using Sequelize. One of "sequelize" or
  16. * "model" storage option is required.
  17. *
  18. * If "sequelize" option is supplied will create a model named "SequelizeMeta"
  19. * with timestamps and an attribute "name" for storing migrations. The model
  20. * name, table name, and column name are customizable with options.
  21. *
  22. * If "model" option is supplied will use existing model for storing
  23. * migrations. The model must have an attribute "name", which can be
  24. * customized.
  25. *
  26. * If the table does not exist it will be created automatically.
  27. *
  28. * @param {Object} [options]
  29. * @param {Object} [options.]
  30. * @param {Object} [options.sequelize] - configured instance of Sequelize.
  31. * @param {Object} [options.model] - Sequelize model - must have column name
  32. * matching "columnName" option.
  33. * @param {String} [options.modelName='SequelizeMeta'] - name of the model
  34. * to create if "model" option is not supplied.
  35. * @param {String} [options.tableName=modelName] - name of the table to create
  36. * if "model" option is not supplied.
  37. * @param {String} [options.schema=schema] - name of the schema to create
  38. * the table under, defaults to undefined.
  39. * @param {String} [options.columnName='name'] - name of the table column
  40. * holding migration name.
  41. * @param {String} [options.columnType=Sequelize.STRING] - type of the column.
  42. * For utf8mb4 charsets under InnoDB, you may need to set this <= 190.
  43. * @param {Boolean} [options.timestamps=false] - option to add timestamps to the model table
  44. */
  45. constructor({
  46. sequelize,
  47. model,
  48. modelName = 'SequelizeMeta',
  49. tableName,
  50. schema,
  51. columnName = 'name',
  52. columnType,
  53. timestamps = false
  54. } = {}) {
  55. super();
  56. if (!model && !sequelize) {
  57. throw new Error('One of "sequelize" or "model" storage option is required');
  58. }
  59. this.sequelize = sequelize || model.sequelize;
  60. const Sequelize = this.sequelize.constructor;
  61. this.columnType = columnType || Sequelize.STRING;
  62. this.columnName = columnName;
  63. this.timestamps = timestamps;
  64. this.modelName = modelName;
  65. this.tableName = tableName;
  66. this.schema = schema;
  67. this.model = model || this.getModel();
  68. }
  69. getModel() {
  70. if (this.sequelize.isDefined(this.modelName)) {
  71. return this.sequelize.model(this.modelName);
  72. }
  73. return this.sequelize.define(this.modelName, {
  74. [this.columnName]: {
  75. type: this.columnType,
  76. allowNull: false,
  77. unique: true,
  78. primaryKey: true,
  79. autoIncrement: false
  80. }
  81. }, {
  82. tableName: this.tableName,
  83. schema: this.schema,
  84. timestamps: this.timestamps,
  85. charset: 'utf8',
  86. collate: 'utf8_unicode_ci'
  87. });
  88. }
  89. /**
  90. * Logs migration to be considered as executed.
  91. *
  92. * @param {String} migrationName - Name of the migration to be logged.
  93. * @returns {Promise}
  94. */
  95. logMigration(migrationName) {
  96. const self = this;
  97. return this._model().sync().then(Model => {
  98. const migration = {};
  99. migration[self.columnName] = migrationName;
  100. return Model.create(migration);
  101. });
  102. }
  103. /**
  104. * Unlogs migration to be considered as pending.
  105. *
  106. * @param {String} migrationName - Name of the migration to be unlogged.
  107. * @returns {Promise}
  108. */
  109. unlogMigration(migrationName) {
  110. const self = this;
  111. const sequelize = this.sequelize;
  112. const sequelizeVersion = sequelize.modelManager ? 2 : 1;
  113. return this._model().sync().then(Model => {
  114. let where = {};
  115. where[self.columnName] = migrationName;
  116. if (sequelizeVersion > 1) {
  117. // This is an ugly hack to find out which function signature we have to use.
  118. where = {
  119. where: where
  120. };
  121. }
  122. return Model.destroy(where);
  123. });
  124. }
  125. /**
  126. * Gets list of executed migrations.
  127. *
  128. * @returns {Promise.<String[]>}
  129. */
  130. executed() {
  131. const self = this;
  132. return this._model().sync().then(Model => Model.findAll({
  133. order: [[self.columnName, 'ASC']]
  134. })).then(migrations => migrations.map(migration => migration[self.columnName]));
  135. }
  136. /**
  137. * Gets Sequelize model used as a storage.
  138. *
  139. * @returns {Sequelize.Model}
  140. * @private
  141. */
  142. _model() {
  143. return this.model;
  144. }
  145. }
  146. exports.default = SequelizeStorage;