38203-vm/backend/src/db/migrations/1770263369317.js
2026-02-05 03:50:33 +00:00

5572 lines
176 KiB
JavaScript

module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.createTable('users', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('roles', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('permissions', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('sources', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('extensions', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('series', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('chapters', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('chapter_pages', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('library_entries', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('categories', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('category_assignments', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('reading_sessions', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('bookmarks', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('downloads', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('notification_preferences', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('update_subscriptions', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('tracker_accounts', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('tracker_mappings', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('user_preferences', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('backups', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('feedback_reports', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('search_history', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.createTable('reading_progress', {
id: {
type: Sequelize.DataTypes.UUID,
defaultValue: Sequelize.DataTypes.UUIDV4,
primaryKey: true,
},
createdById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
updatedById: {
type: Sequelize.DataTypes.UUID,
references: {
key: 'id',
model: 'users',
},
},
createdAt: { type: Sequelize.DataTypes.DATE },
updatedAt: { type: Sequelize.DataTypes.DATE },
deletedAt: { type: Sequelize.DataTypes.DATE },
importHash: {
type: Sequelize.DataTypes.STRING(255),
allowNull: true,
unique: true,
},
}, { transaction });
await queryInterface.addColumn(
'users',
'firstName',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'lastName',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'phoneNumber',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'email',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'disabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'password',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'emailVerified',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'emailVerificationToken',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'emailVerificationTokenExpiresAt',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'passwordResetToken',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'passwordResetTokenExpiresAt',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'provider',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'users',
'app_roleId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'roles',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'roles',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'roles',
'role_customization',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'permissions',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'base_url',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'source_type',
{
type: Sequelize.DataTypes.ENUM,
values: ['catalog','extension','custom_repo'],
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'enabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'supports_nsfw',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'default_language',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'region',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'rate_limit_per_minute',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'sources',
'last_healthcheck_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'package_name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'version',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'website_url',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'repo_url',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'install_status',
{
type: Sequelize.DataTypes.ENUM,
values: ['installed','available','disabled','error'],
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'nsfw_capable',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'signature_verified',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'installed_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'last_updated_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'extensions',
'sourceId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'sources',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'title',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'alt_titles',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'slug',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'author',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'artist',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'description',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'content_type',
{
type: Sequelize.DataTypes.ENUM,
values: ['manga','manhwa','manhua','comic','webtoon'],
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'publication_status',
{
type: Sequelize.DataTypes.ENUM,
values: ['ongoing','completed','hiatus','cancelled','unknown'],
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'age_rating',
{
type: Sequelize.DataTypes.ENUM,
values: ['general','teen','mature','adult'],
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'is_nsfw',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'language',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'average_rating',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'followers_count',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'last_metadata_refresh_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'series',
'sourceId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'sources',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'title',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'chapter_number_text',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'chapter_number',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'volume_number',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'scanlation_status',
{
type: Sequelize.DataTypes.ENUM,
values: ['available','missing','removed'],
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'page_count',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'is_premium',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'published_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'fetched_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'chapters',
'seriesId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'series',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'page_index',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'image_url',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'width',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'height',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'load_state',
{
type: Sequelize.DataTypes.ENUM,
values: ['remote','cached','error'],
},
{ transaction }
);
await queryInterface.addColumn(
'chapter_pages',
'chapterId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'chapters',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'reading_status',
{
type: Sequelize.DataTypes.ENUM,
values: ['planned','reading','completed','on_hold','dropped','re_reading'],
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'is_favorite',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'last_read_chapter_number',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'added_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'last_read_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'library_entries',
'seriesId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'series',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'categories',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'categories',
'description',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'categories',
'visibility',
{
type: Sequelize.DataTypes.ENUM,
values: ['private','shared','public'],
},
{ transaction }
);
await queryInterface.addColumn(
'categories',
'sort_order',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'categories',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'category_assignments',
'library_entryId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'library_entries',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'category_assignments',
'categoryId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'categories',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'category_assignments',
'assigned_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'started_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'ended_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'reading_mode',
{
type: Sequelize.DataTypes.ENUM,
values: ['vertical_scroll','horizontal_paged','horizontal_scroll','webtoon'],
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'page_fit',
{
type: Sequelize.DataTypes.ENUM,
values: ['fit_width','fit_height','fit_screen','original'],
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'zoom_level',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'direction',
{
type: Sequelize.DataTypes.ENUM,
values: ['ltr','rtl'],
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'crop_borders',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'keep_screen_on',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'show_page_number',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'skip_read_chapters',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'start_page_index',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'end_page_index',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'reading_sessions',
'chapterId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'chapters',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'note',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'page_index',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'bookmarked_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'bookmarks',
'chapterId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'chapters',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'download_type',
{
type: Sequelize.DataTypes.ENUM,
values: ['chapter','series'],
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'status',
{
type: Sequelize.DataTypes.ENUM,
values: ['queued','downloading','paused','completed','failed','cancelled'],
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'progress_percent',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'total_bytes',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'downloaded_bytes',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'storage_path',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'only_on_wifi',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'queued_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'started_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'finished_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'seriesId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'series',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'downloads',
'chapterId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'chapters',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'enabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'notify_new_chapters',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'notify_app_updates',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'notify_downloads',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'delivery_channel',
{
type: Sequelize.DataTypes.ENUM,
values: ['in_app','email','push'],
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'quiet_hours_start',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'quiet_hours_end',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'notification_preferences',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'enabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'update_mode',
{
type: Sequelize.DataTypes.ENUM,
values: ['manual','scheduled','smart'],
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'check_interval_minutes',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'last_checked_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'next_check_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'update_subscriptions',
'seriesId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'series',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'provider',
{
type: Sequelize.DataTypes.ENUM,
values: ['myanimelist','anilist','kitsu','mangaupdates','shikimori'],
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'account_username',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'access_token',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'refresh_token',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'token_expires_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'sync_enabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'last_synced_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_accounts',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'external_item_id',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'external_item_url',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'external_title',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'linked_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'tracker_accountId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'tracker_accounts',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'tracker_mappings',
'seriesId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'series',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'theme_mode',
{
type: Sequelize.DataTypes.ENUM,
values: ['light','dark','system','cover_based'],
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'theme_accent_color',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'reading_mode_default',
{
type: Sequelize.DataTypes.ENUM,
values: ['vertical_scroll','horizontal_paged','horizontal_scroll','webtoon'],
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'direction_default',
{
type: Sequelize.DataTypes.ENUM,
values: ['ltr','rtl'],
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'page_fit_default',
{
type: Sequelize.DataTypes.ENUM,
values: ['fit_width','fit_height','fit_screen','original'],
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'zoom_default',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'show_nsfw_in_search',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'show_nsfw_in_library',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'only_downloaded_mode',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'auto_download_while_reading',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'auto_download_ahead_chapters',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'bulk_download_warnings',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'google_drive_backup_enabled',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'last_backup_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'last_restore_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'user_preferences',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'provider',
{
type: Sequelize.DataTypes.ENUM,
values: ['local','google_drive'],
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'backup_type',
{
type: Sequelize.DataTypes.ENUM,
values: ['automatic','manual'],
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'provider_file_id',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'size_bytes',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'started_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'completed_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'status',
{
type: Sequelize.DataTypes.ENUM,
values: ['queued','running','completed','failed'],
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'error_message',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'backups',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'report_type',
{
type: Sequelize.DataTypes.ENUM,
values: ['bug','feature_request','content_issue','security','other'],
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'severity',
{
type: Sequelize.DataTypes.ENUM,
values: ['low','medium','high','critical'],
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'title',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'details',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'status',
{
type: Sequelize.DataTypes.ENUM,
values: ['open','triaged','in_progress','resolved','closed'],
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'app_version',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'platform',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'submitted_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'resolved_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'feedback_reports',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'search_history',
'query',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'search_history',
'content_filter',
{
type: Sequelize.DataTypes.ENUM,
values: ['all','safe_only','nsfw_allowed'],
},
{ transaction }
);
await queryInterface.addColumn(
'search_history',
'language_filter',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction }
);
await queryInterface.addColumn(
'search_history',
'searched_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'search_history',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'is_completed',
{
type: Sequelize.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'last_page_index',
{
type: Sequelize.DataTypes.INTEGER,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'progress_percent',
{
type: Sequelize.DataTypes.DECIMAL,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'first_read_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'last_read_at',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'userId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'users',
key: 'id',
},
},
{ transaction }
);
await queryInterface.addColumn(
'reading_progress',
'chapterId',
{
type: Sequelize.DataTypes.UUID,
references: {
model: 'chapters',
key: 'id',
},
},
{ transaction }
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn(
'reading_progress',
'chapterId',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'last_read_at',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'first_read_at',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'progress_percent',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'last_page_index',
{ transaction }
);
await queryInterface.removeColumn(
'reading_progress',
'is_completed',
{ transaction }
);
await queryInterface.removeColumn(
'search_history',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'search_history',
'searched_at',
{ transaction }
);
await queryInterface.removeColumn(
'search_history',
'language_filter',
{ transaction }
);
await queryInterface.removeColumn(
'search_history',
'content_filter',
{ transaction }
);
await queryInterface.removeColumn(
'search_history',
'query',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'resolved_at',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'submitted_at',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'platform',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'app_version',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'status',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'details',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'title',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'severity',
{ transaction }
);
await queryInterface.removeColumn(
'feedback_reports',
'report_type',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'error_message',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'status',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'completed_at',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'started_at',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'size_bytes',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'provider_file_id',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'backup_type',
{ transaction }
);
await queryInterface.removeColumn(
'backups',
'provider',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'last_restore_at',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'last_backup_at',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'google_drive_backup_enabled',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'bulk_download_warnings',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'auto_download_ahead_chapters',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'auto_download_while_reading',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'only_downloaded_mode',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'show_nsfw_in_library',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'show_nsfw_in_search',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'zoom_default',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'page_fit_default',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'direction_default',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'reading_mode_default',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'theme_accent_color',
{ transaction }
);
await queryInterface.removeColumn(
'user_preferences',
'theme_mode',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'seriesId',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'tracker_accountId',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'linked_at',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'external_title',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'external_item_url',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_mappings',
'external_item_id',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'last_synced_at',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'sync_enabled',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'token_expires_at',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'refresh_token',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'access_token',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'account_username',
{ transaction }
);
await queryInterface.removeColumn(
'tracker_accounts',
'provider',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'seriesId',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'next_check_at',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'last_checked_at',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'check_interval_minutes',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'update_mode',
{ transaction }
);
await queryInterface.removeColumn(
'update_subscriptions',
'enabled',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'quiet_hours_end',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'quiet_hours_start',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'delivery_channel',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'notify_downloads',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'notify_app_updates',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'notify_new_chapters',
{ transaction }
);
await queryInterface.removeColumn(
'notification_preferences',
'enabled',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'chapterId',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'seriesId',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'finished_at',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'started_at',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'queued_at',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'only_on_wifi',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'storage_path',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'downloaded_bytes',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'total_bytes',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'progress_percent',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'status',
{ transaction }
);
await queryInterface.removeColumn(
'downloads',
'download_type',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'chapterId',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'bookmarked_at',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'page_index',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'note',
{ transaction }
);
await queryInterface.removeColumn(
'bookmarks',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'chapterId',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'end_page_index',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'start_page_index',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'skip_read_chapters',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'show_page_number',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'keep_screen_on',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'crop_borders',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'direction',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'zoom_level',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'page_fit',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'reading_mode',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'ended_at',
{ transaction }
);
await queryInterface.removeColumn(
'reading_sessions',
'started_at',
{ transaction }
);
await queryInterface.removeColumn(
'category_assignments',
'assigned_at',
{ transaction }
);
await queryInterface.removeColumn(
'category_assignments',
'categoryId',
{ transaction }
);
await queryInterface.removeColumn(
'category_assignments',
'library_entryId',
{ transaction }
);
await queryInterface.removeColumn(
'categories',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'categories',
'sort_order',
{ transaction }
);
await queryInterface.removeColumn(
'categories',
'visibility',
{ transaction }
);
await queryInterface.removeColumn(
'categories',
'description',
{ transaction }
);
await queryInterface.removeColumn(
'categories',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'seriesId',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'userId',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'last_read_at',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'added_at',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'last_read_chapter_number',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'is_favorite',
{ transaction }
);
await queryInterface.removeColumn(
'library_entries',
'reading_status',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'chapterId',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'load_state',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'height',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'width',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'image_url',
{ transaction }
);
await queryInterface.removeColumn(
'chapter_pages',
'page_index',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'seriesId',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'fetched_at',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'published_at',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'is_premium',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'page_count',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'scanlation_status',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'volume_number',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'chapter_number',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'chapter_number_text',
{ transaction }
);
await queryInterface.removeColumn(
'chapters',
'title',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'sourceId',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'last_metadata_refresh_at',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'followers_count',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'average_rating',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'language',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'is_nsfw',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'age_rating',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'publication_status',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'content_type',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'description',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'artist',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'author',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'slug',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'alt_titles',
{ transaction }
);
await queryInterface.removeColumn(
'series',
'title',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'sourceId',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'last_updated_at',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'installed_at',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'signature_verified',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'nsfw_capable',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'install_status',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'repo_url',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'website_url',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'version',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'package_name',
{ transaction }
);
await queryInterface.removeColumn(
'extensions',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'last_healthcheck_at',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'rate_limit_per_minute',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'region',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'default_language',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'supports_nsfw',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'enabled',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'source_type',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'base_url',
{ transaction }
);
await queryInterface.removeColumn(
'sources',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'permissions',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'roles',
'role_customization',
{ transaction }
);
await queryInterface.removeColumn(
'roles',
'name',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'app_roleId',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'provider',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'passwordResetTokenExpiresAt',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'passwordResetToken',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'emailVerificationTokenExpiresAt',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'emailVerificationToken',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'emailVerified',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'password',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'disabled',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'email',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'phoneNumber',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'lastName',
{ transaction }
);
await queryInterface.removeColumn(
'users',
'firstName',
{ transaction }
);
await queryInterface.dropTable('reading_progress', { transaction });
await queryInterface.dropTable('search_history', { transaction });
await queryInterface.dropTable('feedback_reports', { transaction });
await queryInterface.dropTable('backups', { transaction });
await queryInterface.dropTable('user_preferences', { transaction });
await queryInterface.dropTable('tracker_mappings', { transaction });
await queryInterface.dropTable('tracker_accounts', { transaction });
await queryInterface.dropTable('update_subscriptions', { transaction });
await queryInterface.dropTable('notification_preferences', { transaction });
await queryInterface.dropTable('downloads', { transaction });
await queryInterface.dropTable('bookmarks', { transaction });
await queryInterface.dropTable('reading_sessions', { transaction });
await queryInterface.dropTable('category_assignments', { transaction });
await queryInterface.dropTable('categories', { transaction });
await queryInterface.dropTable('library_entries', { transaction });
await queryInterface.dropTable('chapter_pages', { transaction });
await queryInterface.dropTable('chapters', { transaction });
await queryInterface.dropTable('series', { transaction });
await queryInterface.dropTable('extensions', { transaction });
await queryInterface.dropTable('sources', { transaction });
await queryInterface.dropTable('permissions', { transaction });
await queryInterface.dropTable('roles', { transaction });
await queryInterface.dropTable('users', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
}
};