Files
dss/cli/src/commands/extract.ts
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

147 lines
4.3 KiB
TypeScript

/**
* DSS Extract Command
*
* Extract tokens or components from Figma.
*/
import chalk from 'chalk';
import ora from 'ora';
import { writeFileSync, existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { getConfig, getProjectRoot } from '../lib/config.js';
import { getApiClient } from '../lib/api.js';
import { isServerRunning } from '../lib/server.js';
interface ExtractOptions {
format: string;
output?: string;
fileKey?: string;
}
export async function extractCommand(
type: string,
options: ExtractOptions
): Promise<void> {
const validTypes = ['tokens', 'components', 'styles', 'all'];
if (!validTypes.includes(type)) {
console.log(chalk.red(` Invalid type: ${type}`));
console.log(chalk.dim(` Valid types: ${validTypes.join(', ')}`));
process.exit(1);
}
const config = getConfig();
const cwd = getProjectRoot();
// Check if server is running
if (!isServerRunning(cwd)) {
console.log(chalk.yellow(' DSS server is not running'));
console.log(chalk.dim(' Start it with: dss start'));
process.exit(1);
}
const fileKey = options.fileKey || config.figmaFileKey;
if (!fileKey) {
console.log(chalk.red(' No Figma file key configured'));
console.log(chalk.dim(' Set it with: dss config --set figmaFileKey=YOUR_KEY'));
process.exit(1);
}
const outputDir = options.output || join(cwd, '.dss', 'output');
if (!existsSync(outputDir)) {
mkdirSync(outputDir, { recursive: true });
}
const api = getApiClient({ port: config.port });
if (type === 'tokens' || type === 'all') {
await extractTokens(api, fileKey, options.format, outputDir);
}
if (type === 'components' || type === 'all') {
await extractComponents(api, fileKey, outputDir);
}
if (type === 'styles' || type === 'all') {
await extractStyles(api, fileKey, outputDir);
}
}
async function extractTokens(
api: ReturnType<typeof getApiClient>,
fileKey: string,
format: string,
outputDir: string
): Promise<void> {
const spinner = ora('Extracting tokens...').start();
try {
const result = await api.extractTokens(fileKey, format || 'json');
const filename = format === 'css' ? 'tokens.css' :
format === 'scss' ? '_tokens.scss' :
format === 'ts' ? 'tokens.ts' : 'tokens.json';
const outputPath = join(outputDir, filename);
writeFileSync(outputPath, result.formatted_output);
spinner.succeed(`Extracted ${result.tokens_count} tokens`);
console.log(chalk.dim(` Output: ${outputPath}`));
} catch (error) {
spinner.fail('Failed to extract tokens');
console.error(chalk.red(` ${(error as Error).message}`));
}
}
async function extractComponents(
api: ReturnType<typeof getApiClient>,
fileKey: string,
outputDir: string
): Promise<void> {
const spinner = ora('Extracting components...').start();
try {
const result = await api.extractComponents(fileKey);
const outputPath = join(outputDir, 'components.json');
writeFileSync(outputPath, JSON.stringify(result.components, null, 2));
spinner.succeed(`Extracted ${result.components_count} components`);
console.log(chalk.dim(` Output: ${outputPath}`));
// Show component summary
console.log('');
result.components.forEach(comp => {
console.log(chalk.dim(` - ${comp.name}`));
if (comp.variants?.length) {
console.log(chalk.dim(` Variants: ${comp.variants.join(', ')}`));
}
});
} catch (error) {
spinner.fail('Failed to extract components');
console.error(chalk.red(` ${(error as Error).message}`));
}
}
async function extractStyles(
api: ReturnType<typeof getApiClient>,
fileKey: string,
outputDir: string
): Promise<void> {
const spinner = ora('Extracting styles...').start();
try {
// Note: This would need a corresponding API endpoint
// For now, we'll extract tokens which include style information
const result = await api.extractTokens(fileKey, 'json');
const outputPath = join(outputDir, 'styles.json');
writeFileSync(outputPath, JSON.stringify(result.tokens, null, 2));
spinner.succeed(`Extracted styles`);
console.log(chalk.dim(` Output: ${outputPath}`));
} catch (error) {
spinner.fail('Failed to extract styles');
console.error(chalk.red(` ${(error as Error).message}`));
}
}