Files
dss/dss/export_import/migrations.py
Bruno Sarlo 41fba59bf7 Major refactor: Consolidate DSS into unified package structure
- Create new dss/ Python package at project root
- Move MCP core from tools/dss_mcp/ to dss/mcp/
- Move storage layer from tools/storage/ to dss/storage/
- Move domain logic from dss-mvp1/dss/ to dss/
- Move services from tools/api/services/ to dss/services/
- Move API server to apps/api/
- Move CLI to apps/cli/
- Move Storybook assets to storybook/
- Create unified dss/__init__.py with comprehensive exports
- Merge configuration into dss/settings.py (Pydantic-based)
- Create pyproject.toml for proper package management
- Update startup scripts for new paths
- Remove old tools/ and dss-mvp1/ directories

Architecture changes:
- DSS is now MCP-first with 40+ tools for Claude Code
- Clean imports: from dss import Projects, Components, FigmaToolSuite
- No more sys.path.insert() hacking
- apps/ contains thin application wrappers (API, CLI)
- Single unified Python package for all DSS logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 12:46:43 -03:00

149 lines
4.6 KiB
Python

"""Schema migration system for .dss archive compatibility"""
from typing import Dict, Any, List, Callable
import json
class SchemaMigration:
"""Base class for schema migrations"""
source_version: str = "1.0.0"
target_version: str = "1.0.1"
def up(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Migrate data from source to target version"""
raise NotImplementedError
def down(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Rollback migration"""
raise NotImplementedError
class MigrationV1_0_0_to_V1_0_1(SchemaMigration):
"""Initial migration: add UUID support to all entities"""
source_version = "1.0.0"
target_version = "1.0.1"
def up(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Add UUID fields if missing"""
from uuid import uuid4
# Ensure all entities have UUIDs (backward compat)
if 'project' in data:
if 'uuid' not in data['project']:
data['project']['uuid'] = str(uuid4())
if 'tokens' in data:
for token_name, token in data['tokens'].items():
if isinstance(token, dict) and 'uuid' not in token:
token['uuid'] = str(uuid4())
if 'components' in data:
for comp in data['components']:
if 'uuid' not in comp:
comp['uuid'] = str(uuid4())
if 'variants' in comp:
for variant in comp['variants']:
if 'uuid' not in variant:
variant['uuid'] = str(uuid4())
if 'themes' in data:
for theme in data['themes']:
if 'uuid' not in theme:
theme['uuid'] = str(uuid4())
return data
def down(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Remove UUID fields (rollback)"""
if 'project' in data:
data['project'].pop('uuid', None)
if 'tokens' in data:
for token in data['tokens'].values():
if isinstance(token, dict):
token.pop('uuid', None)
if 'components' in data:
for comp in data['components']:
comp.pop('uuid', None)
if 'variants' in comp:
for variant in comp['variants']:
variant.pop('uuid', None)
if 'themes' in data:
for theme in data['themes']:
theme.pop('uuid', None)
return data
class MigrationManager:
"""Manages schema migrations for .dss archives"""
# Map of version pairs to migration classes
MIGRATIONS: Dict[tuple, type] = {
("1.0.0", "1.0.1"): MigrationV1_0_0_to_V1_0_1,
}
# Ordered list of all schema versions
VERSIONS = ["1.0.0", "1.0.1"]
@classmethod
def migrate(cls, data: Dict[str, Any], from_version: str, to_version: str) -> Dict[str, Any]:
"""
Apply migrations from source version to target version.
Args:
data: Archive data to migrate
from_version: Current schema version in archive
to_version: Target schema version
Returns:
Migrated data
Raises:
ValueError: If migration path doesn't exist or versions are invalid
"""
if from_version == to_version:
return data
# Validate versions
if from_version not in cls.VERSIONS:
raise ValueError(f"Unknown source schema version: {from_version}")
if to_version not in cls.VERSIONS:
raise ValueError(f"Unknown target schema version: {to_version}")
from_idx = cls.VERSIONS.index(from_version)
to_idx = cls.VERSIONS.index(to_version)
if from_idx > to_idx:
raise ValueError(f"Cannot downgrade from {from_version} to {to_version}")
# Apply migrations sequentially
current_version = from_version
while current_version != to_version:
current_idx = cls.VERSIONS.index(current_version)
next_version = cls.VERSIONS[current_idx + 1]
migration_key = (current_version, next_version)
if migration_key not in cls.MIGRATIONS:
raise ValueError(f"No migration found for {current_version} -> {next_version}")
migration_class = cls.MIGRATIONS[migration_key]
migration = migration_class()
data = migration.up(data)
current_version = next_version
return data
@classmethod
def get_latest_version(cls) -> str:
"""Get latest schema version"""
return cls.VERSIONS[-1]
# Export
__all__ = ['MigrationManager', 'SchemaMigration']