Files
dss/server/migrations/20251209000001-add-config-settings.js
Digital Production Factory 276ed71f31 Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
2025-12-09 18:45:48 -03:00

98 lines
2.8 KiB
JavaScript

import { DataTypes, Op } from 'sequelize';
export default {
up: async (queryInterface) => {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.createTable('config_settings', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
scope: {
type: DataTypes.ENUM('SYSTEM', 'PROJECT', 'USER'),
allowNull: false
},
scopeId: {
type: DataTypes.UUID,
allowNull: true,
field: 'scope_id'
},
key: {
type: DataTypes.STRING,
allowNull: false
},
value: {
type: DataTypes.JSONB,
allowNull: false
},
isSecret: {
type: DataTypes.BOOLEAN,
defaultValue: false,
field: 'is_secret'
},
schemaVersion: {
type: DataTypes.INTEGER,
defaultValue: 1,
field: 'schema_version'
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
field: 'created_at'
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
field: 'updated_at'
}
}, { transaction });
// Create a unique index that handles the NULL scope_id for SYSTEM scope correctly
// In Postgres 15+ we could use NULLS NOT DISTINCT, but for compatibility we use a partial index
// for the NULL case and a standard unique index for the non-NULL case.
// 1. Standard unique constraint for non-null scope_id (Project/User)
await queryInterface.addIndex('config_settings', ['scope', 'scope_id', 'key'], {
unique: true,
where: {
scope_id: { [Op.ne]: null }
},
name: 'config_settings_scope_scope_id_key_unique',
transaction
});
// 2. Unique constraint for SYSTEM scope (where scope_id is NULL)
await queryInterface.addIndex('config_settings', ['scope', 'key'], {
unique: true,
where: {
scope_id: null
},
name: 'config_settings_system_scope_key_unique',
transaction
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
down: async (queryInterface) => {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.dropTable('config_settings', { transaction });
await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_config_settings_scope";', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
}
};