feat: Add DSS infrastructure, remove legacy admin-ui code
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
Some checks failed
DSS Project Analysis / dss-context-update (push) Has been cancelled
- Remove legacy admin-ui/js/ vanilla JS components - Add .dss/ directory with core tokens, skins, themes - Add Storybook configuration and generated stories - Add DSS management scripts (dss-services, dss-init, dss-setup, dss-reset) - Add MCP command definitions for DSS plugin - Add Figma sync architecture and scripts - Update pre-commit hooks with documentation validation - Fix JSON trailing commas in skin files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -66,13 +66,19 @@ except ImportError:
|
||||
try:
|
||||
import dss
|
||||
from dss import (
|
||||
# Analyze - Context generation & project graph
|
||||
ProjectScanner, ReactAnalyzer, StyleAnalyzer, DependencyGraph, QuickWinFinder,
|
||||
# Ingest - Token sources
|
||||
CSSTokenSource, SCSSTokenSource, TailwindTokenSource, JSONTokenSource,
|
||||
TokenMerger, MergeStrategy, TokenCollection,
|
||||
StyleDictionaryWrapper, ShadcnWrapper, FigmaWrapper,
|
||||
# Models
|
||||
Theme, Project, ProjectMetadata,
|
||||
# Storybook
|
||||
StorybookScanner, StoryGenerator, ThemeGenerator,
|
||||
DSSSettings, DSSManager, settings, manager
|
||||
# Settings
|
||||
DSSSettings, DSSManager, settings, manager,
|
||||
# Figma
|
||||
FigmaToolSuite,
|
||||
)
|
||||
DSS_AVAILABLE = True
|
||||
except ImportError as e:
|
||||
@@ -962,7 +968,10 @@ async def list_tools() -> List[Tool]:
|
||||
async def call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]:
|
||||
"""Handle tool calls"""
|
||||
|
||||
if not DSS_AVAILABLE and name.startswith("dss_"):
|
||||
# Tools that work without DSS module imports (use scripts directly)
|
||||
DSS_INDEPENDENT_TOOLS = {"dss_sync_figma", "dss_get_status", "dss_list_themes"}
|
||||
|
||||
if not DSS_AVAILABLE and name.startswith("dss_") and name not in DSS_INDEPENDENT_TOOLS:
|
||||
return [TextContent(
|
||||
type="text",
|
||||
text=json.dumps({
|
||||
@@ -1430,19 +1439,90 @@ async def setup_storybook(path: str, action: str) -> Dict[str, Any]:
|
||||
|
||||
|
||||
async def sync_figma(file_key: str) -> Dict[str, Any]:
|
||||
"""Sync tokens from Figma"""
|
||||
"""Sync tokens from Figma using intelligent sync v2.0
|
||||
|
||||
Features:
|
||||
- Rate limiting with exponential backoff
|
||||
- Caching with lastModified checks
|
||||
- Figma Variables extraction
|
||||
- W3C token format output
|
||||
- Component variant classification
|
||||
"""
|
||||
if not file_key:
|
||||
return {"success": False, "error": "file_key is required"}
|
||||
figma_token = os.environ.get("FIGMA_TOKEN") or settings.FIGMA_TOKEN
|
||||
|
||||
# Get token from env or config
|
||||
figma_token = os.environ.get("FIGMA_TOKEN")
|
||||
if not figma_token:
|
||||
return {"success": False, "error": "FIGMA_TOKEN not configured."}
|
||||
config_path = Path(__file__).parent.parent.parent / ".dss/config/figma.json"
|
||||
if config_path.exists():
|
||||
try:
|
||||
with open(config_path) as f:
|
||||
config = json.load(f)
|
||||
figma_token = config.get("token")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not figma_token:
|
||||
return {"success": False, "error": "FIGMA_TOKEN not configured. Set env var or add to .dss/config/figma.json"}
|
||||
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
figma = FigmaWrapper(token=figma_token)
|
||||
result = await loop.run_in_executor(None, lambda: figma.extract_tokens(file_key))
|
||||
return {"success": True, "file_key": file_key, "tokens": safe_serialize(result)}
|
||||
# Import intelligent sync from scripts
|
||||
scripts_dir = Path(__file__).parent.parent.parent / "scripts"
|
||||
sys.path.insert(0, str(scripts_dir))
|
||||
|
||||
from importlib import import_module
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("figma_sync", scripts_dir / "figma-sync.py")
|
||||
figma_sync_module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(figma_sync_module)
|
||||
|
||||
# Run intelligent sync
|
||||
success = await figma_sync_module.intelligent_sync(
|
||||
file_key=file_key,
|
||||
token=figma_token,
|
||||
force=True,
|
||||
verbose=False
|
||||
)
|
||||
|
||||
if success:
|
||||
# Load results
|
||||
tokens_path = Path(__file__).parent.parent.parent / ".dss/data/_system/tokens/figma-tokens.json"
|
||||
components_path = Path(__file__).parent.parent.parent / ".dss/components/figma-registry.json"
|
||||
|
||||
tokens = {}
|
||||
components = {}
|
||||
|
||||
if tokens_path.exists():
|
||||
with open(tokens_path) as f:
|
||||
tokens = json.load(f)
|
||||
|
||||
if components_path.exists():
|
||||
with open(components_path) as f:
|
||||
components = json.load(f)
|
||||
|
||||
token_count = sum(
|
||||
len(v) for k, v in tokens.items()
|
||||
if not k.startswith("$") and not k.startswith("_") and isinstance(v, dict)
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"file_key": file_key,
|
||||
"tokens_extracted": token_count,
|
||||
"components_extracted": components.get("component_count", 0),
|
||||
"output_files": {
|
||||
"tokens": str(tokens_path),
|
||||
"components": str(components_path)
|
||||
}
|
||||
}
|
||||
else:
|
||||
return {"success": False, "error": "Sync failed - check logs"}
|
||||
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
import traceback
|
||||
return {"success": False, "error": str(e), "traceback": traceback.format_exc()}
|
||||
|
||||
|
||||
async def find_quick_wins(path: str) -> Dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user