/** * Migration: Add tenant_id to heartbeats table * This migration adds tenant_id field to heartbeats for multi-tenant support */ 'use strict'; module.exports = { async up(queryInterface, Sequelize) { try { // Check if heartbeats table exists first const tables = await queryInterface.showAllTables(); if (!tables.includes('heartbeats')) { console.log('⚠️ Heartbeats table does not exist yet, skipping heartbeat tenant support migration...'); return; } // Check if tenant_id column already exists const tableDescription = await queryInterface.describeTable('heartbeats'); if (!tableDescription.tenant_id) { // Add index for tenant_id for better query performance try { await queryInterface.addIndex('heartbeats', ['tenant_id'], { name: 'heartbeats_tenant_id_idx' }); console.log('✅ Added index on heartbeats.tenant_id'); } catch (error) { if (error.parent?.code === '42P07') { // Index already exists console.log('⚠️ Index heartbeats_tenant_id already exists, skipping...'); } else { throw error; } } // Associate existing heartbeats with default tenant (backward compatibility) const defaultTenant = await queryInterface.sequelize.query( 'SELECT id FROM tenants WHERE slug = :slug', { replacements: { slug: 'default' }, type: Sequelize.QueryTypes.SELECT } ); if (defaultTenant.length > 0) { await queryInterface.sequelize.query( 'UPDATE heartbeats SET tenant_id = :tenantId WHERE tenant_id IS NULL', { replacements: { tenantId: defaultTenant[0].id }, type: Sequelize.QueryTypes.UPDATE } ); console.log('✅ Associated existing heartbeats with default tenant'); } console.log('✅ Added tenant_id field to heartbeats table'); } else { console.log('⚠️ Column tenant_id already exists in heartbeats table, skipping...'); } } catch (error) { console.log('⚠️ Migration skipped - tables may not exist yet:', error.message); // Don't throw error, just skip this migration if tables don't exist } }, async down(queryInterface, Sequelize) { // Remove index try { await queryInterface.removeIndex('heartbeats', 'heartbeats_tenant_id_idx'); } catch (error) { console.log('⚠️ Index heartbeats_tenant_id_idx does not exist, skipping...'); } // Remove column await queryInterface.removeColumn('heartbeats', 'tenant_id'); console.log('✅ Removed tenant_id field from heartbeats table'); } };