@promptui-lib/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/promptui.js +8 -0
- package/dist/commands/generate.cmd.d.ts +19 -0
- package/dist/commands/generate.cmd.d.ts.map +1 -0
- package/dist/commands/generate.cmd.js +261 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.cmd.d.ts +6 -0
- package/dist/commands/init.cmd.d.ts.map +1 -0
- package/dist/commands/init.cmd.js +45 -0
- package/dist/commands/mcp.cmd.d.ts +22 -0
- package/dist/commands/mcp.cmd.d.ts.map +1 -0
- package/dist/commands/mcp.cmd.js +120 -0
- package/dist/commands/sync.cmd.d.ts +9 -0
- package/dist/commands/sync.cmd.d.ts.map +1 -0
- package/dist/commands/sync.cmd.js +214 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +169 -0
- package/package.json +63 -0
package/bin/promptui.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Command
|
|
3
|
+
* Gera componente a partir de um node do Figma ou arquivo JSON local
|
|
4
|
+
*/
|
|
5
|
+
import type { ComponentLayer, FrameworkType } from '@promptui-lib/core';
|
|
6
|
+
export interface IGenerateOptions {
|
|
7
|
+
force?: boolean;
|
|
8
|
+
output?: string;
|
|
9
|
+
layer?: ComponentLayer;
|
|
10
|
+
framework?: FrameworkType;
|
|
11
|
+
preview?: boolean;
|
|
12
|
+
noMeta?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function generateCommand(input: string, options: IGenerateOptions): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Gera todos os componentes marcados com # no arquivo Figma
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateAllCommand(options: IGenerateOptions): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=generate.cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.cmd.d.ts","sourceRoot":"","sources":["../../src/commands/generate.cmd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAc,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAapF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA0ED,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAqJf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFjF"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Command
|
|
3
|
+
* Gera componente a partir de um node do Figma ou arquivo JSON local
|
|
4
|
+
*/
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { createFigmaClient } from '@promptui-lib/figma-parser';
|
|
8
|
+
import { parseNode } from '@promptui-lib/figma-parser';
|
|
9
|
+
import { writeComponent, generateCode, generateMuiComponent, generateTailwindComponent, generateBootstrapComponent, FRAMEWORKS, } from '@promptui-lib/codegen';
|
|
10
|
+
import { loadConfig, resolveConfig, validateConfig } from '@promptui-lib/mcp-agent';
|
|
11
|
+
/**
|
|
12
|
+
* Detecta se o input é um arquivo JSON local ou nodeId do Figma
|
|
13
|
+
*/
|
|
14
|
+
function isLocalFile(input) {
|
|
15
|
+
return input.endsWith('.json') || input.startsWith('./') || input.startsWith('/');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Carrega node de arquivo JSON local
|
|
19
|
+
*/
|
|
20
|
+
async function loadNodeFromFile(filePath) {
|
|
21
|
+
const content = await readFile(filePath, 'utf-8');
|
|
22
|
+
const node = JSON.parse(content);
|
|
23
|
+
if (!node.id || !node.name || !node.type) {
|
|
24
|
+
throw new Error('Invalid Figma node JSON: missing id, name or type');
|
|
25
|
+
}
|
|
26
|
+
return node;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Gera metadados do componente
|
|
30
|
+
*/
|
|
31
|
+
function generateMeta(node, ast, source, files) {
|
|
32
|
+
const content = JSON.stringify({ node, ast, source, files });
|
|
33
|
+
const checksum = createHash('sha256').update(content).digest('hex');
|
|
34
|
+
return {
|
|
35
|
+
generator: 'promptui-figma-codegen',
|
|
36
|
+
version: '1.0.0',
|
|
37
|
+
generatedAt: new Date().toISOString(),
|
|
38
|
+
source: {
|
|
39
|
+
nodeId: node.id,
|
|
40
|
+
nodeName: node.name,
|
|
41
|
+
fileId: source.fileId,
|
|
42
|
+
fromFile: source.fromFile,
|
|
43
|
+
},
|
|
44
|
+
output: {
|
|
45
|
+
componentName: ast.name,
|
|
46
|
+
fileName: ast.fileName,
|
|
47
|
+
layer: ast.layer,
|
|
48
|
+
files,
|
|
49
|
+
},
|
|
50
|
+
checksum: `sha256:${checksum}`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function generateCommand(input, options) {
|
|
54
|
+
const isFile = isLocalFile(input);
|
|
55
|
+
console.log(`[PromptUI] Generating component from ${isFile ? 'file' : 'Figma node'}: ${input}`);
|
|
56
|
+
// Carrega config
|
|
57
|
+
const config = await loadConfig();
|
|
58
|
+
const resolved = resolveConfig(config);
|
|
59
|
+
let node;
|
|
60
|
+
let sourceInfo = {};
|
|
61
|
+
try {
|
|
62
|
+
if (isFile) {
|
|
63
|
+
// Carrega de arquivo JSON local
|
|
64
|
+
node = await loadNodeFromFile(input);
|
|
65
|
+
sourceInfo.fromFile = input;
|
|
66
|
+
console.log(`[PromptUI] Loaded from file: ${node.name} (${node.type})`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Valida config para API
|
|
70
|
+
const errors = validateConfig(resolved);
|
|
71
|
+
if (errors.length > 0) {
|
|
72
|
+
console.error('[PromptUI] Configuration errors:');
|
|
73
|
+
for (const error of errors) {
|
|
74
|
+
console.error(` - ${error}`);
|
|
75
|
+
}
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
// Busca node do Figma
|
|
79
|
+
const client = createFigmaClient({ token: resolved.figmaToken });
|
|
80
|
+
const fetchedNode = await client.getNode(resolved.figmaFileId, input);
|
|
81
|
+
if (!fetchedNode) {
|
|
82
|
+
console.error(`[PromptUI] Node not found: ${input}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
node = fetchedNode;
|
|
86
|
+
sourceInfo.fileId = resolved.figmaFileId;
|
|
87
|
+
console.log(`[PromptUI] Fetched from Figma: ${node.name} (${node.type})`);
|
|
88
|
+
}
|
|
89
|
+
// Parseia
|
|
90
|
+
const ast = parseNode(node, { forceLayer: options.layer });
|
|
91
|
+
const framework = options.framework ?? 'react';
|
|
92
|
+
const frameworkInfo = FRAMEWORKS[framework];
|
|
93
|
+
console.log(`[PromptUI] Parsed: ${ast.name} (${ast.layer})`);
|
|
94
|
+
console.log(`[PromptUI] Framework: ${frameworkInfo?.displayName ?? framework}`);
|
|
95
|
+
// Gera código baseado no framework
|
|
96
|
+
const generateForFramework = () => {
|
|
97
|
+
switch (framework) {
|
|
98
|
+
case 'mui':
|
|
99
|
+
return {
|
|
100
|
+
tsx: generateMuiComponent(ast),
|
|
101
|
+
scss: '', // MUI usa sx props inline
|
|
102
|
+
index: `export { ${ast.name} } from './${ast.fileName}';\nexport type { I${ast.name}Props } from './${ast.fileName}';\n`,
|
|
103
|
+
};
|
|
104
|
+
case 'tailwind':
|
|
105
|
+
return {
|
|
106
|
+
tsx: generateTailwindComponent(ast),
|
|
107
|
+
scss: '', // Tailwind usa classes inline
|
|
108
|
+
index: `export { ${ast.name} } from './${ast.fileName}';\nexport type { I${ast.name}Props } from './${ast.fileName}';\n`,
|
|
109
|
+
};
|
|
110
|
+
case 'bootstrap':
|
|
111
|
+
return {
|
|
112
|
+
tsx: generateBootstrapComponent(ast),
|
|
113
|
+
scss: '', // Bootstrap usa classes inline
|
|
114
|
+
index: `export { ${ast.name} } from './${ast.fileName}';\nexport type { I${ast.name}Props } from './${ast.fileName}';\n`,
|
|
115
|
+
};
|
|
116
|
+
case 'react':
|
|
117
|
+
default:
|
|
118
|
+
return generateCode(ast);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
// Preview mode
|
|
122
|
+
if (options.preview) {
|
|
123
|
+
const code = generateForFramework();
|
|
124
|
+
console.log('\n--- TSX ---');
|
|
125
|
+
console.log(code.tsx);
|
|
126
|
+
if (code.scss) {
|
|
127
|
+
console.log('\n--- SCSS ---');
|
|
128
|
+
console.log(code.scss);
|
|
129
|
+
}
|
|
130
|
+
console.log('\n--- index.ts ---');
|
|
131
|
+
console.log(code.index);
|
|
132
|
+
if (!options.noMeta) {
|
|
133
|
+
const meta = generateMeta(node, ast, sourceInfo, [
|
|
134
|
+
`${ast.fileName}.tsx`,
|
|
135
|
+
`${ast.fileName}.scss`,
|
|
136
|
+
'index.ts',
|
|
137
|
+
'meta.json',
|
|
138
|
+
]);
|
|
139
|
+
console.log('\n--- meta.json ---');
|
|
140
|
+
console.log(JSON.stringify(meta, null, 2));
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Escreve arquivos
|
|
145
|
+
const basePath = options.output ?? resolved.outputBasePath;
|
|
146
|
+
const result = await writeComponent(ast, {
|
|
147
|
+
basePath,
|
|
148
|
+
forceOverwrite: options.force,
|
|
149
|
+
});
|
|
150
|
+
if (!result.success) {
|
|
151
|
+
console.error('[PromptUI] Failed to write files:');
|
|
152
|
+
for (const error of result.errors ?? []) {
|
|
153
|
+
console.error(` - ${error}`);
|
|
154
|
+
}
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
// Gera meta.json
|
|
158
|
+
if (!options.noMeta) {
|
|
159
|
+
const { writeFile } = await import('node:fs/promises');
|
|
160
|
+
const { join, dirname } = await import('node:path');
|
|
161
|
+
const metaPath = join(dirname(result.files.tsx), 'meta.json');
|
|
162
|
+
const meta = generateMeta(node, ast, sourceInfo, [
|
|
163
|
+
`${ast.fileName}.tsx`,
|
|
164
|
+
`${ast.fileName}.scss`,
|
|
165
|
+
'index.ts',
|
|
166
|
+
'meta.json',
|
|
167
|
+
]);
|
|
168
|
+
await writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
|
|
169
|
+
console.log('[PromptUI] Generated files:');
|
|
170
|
+
console.log(` - ${result.files.tsx}`);
|
|
171
|
+
console.log(` - ${result.files.scss}`);
|
|
172
|
+
console.log(` - ${result.files.index}`);
|
|
173
|
+
console.log(` - ${metaPath}`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.log('[PromptUI] Generated files:');
|
|
177
|
+
console.log(` - ${result.files.tsx}`);
|
|
178
|
+
console.log(` - ${result.files.scss}`);
|
|
179
|
+
console.log(` - ${result.files.index}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
184
|
+
console.error(`[PromptUI] Error: ${message}`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Gera todos os componentes marcados com # no arquivo Figma
|
|
190
|
+
*/
|
|
191
|
+
export async function generateAllCommand(options) {
|
|
192
|
+
console.log('[PromptUI] Generating all exportable components...');
|
|
193
|
+
// Carrega config
|
|
194
|
+
const config = await loadConfig();
|
|
195
|
+
const resolved = resolveConfig(config);
|
|
196
|
+
// Valida
|
|
197
|
+
const errors = validateConfig(resolved);
|
|
198
|
+
if (errors.length > 0) {
|
|
199
|
+
console.error('[PromptUI] Configuration errors:');
|
|
200
|
+
for (const error of errors) {
|
|
201
|
+
console.error(` - ${error}`);
|
|
202
|
+
}
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const client = createFigmaClient({ token: resolved.figmaToken });
|
|
207
|
+
const file = await client.getFile(resolved.figmaFileId);
|
|
208
|
+
// Encontra todos os nodes exportáveis (começam com #)
|
|
209
|
+
const exportableNodes = [];
|
|
210
|
+
function findExportable(node) {
|
|
211
|
+
if (node.name.startsWith('#')) {
|
|
212
|
+
exportableNodes.push(node);
|
|
213
|
+
}
|
|
214
|
+
if (node.children) {
|
|
215
|
+
for (const child of node.children) {
|
|
216
|
+
findExportable(child);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (file.document) {
|
|
221
|
+
findExportable(file.document);
|
|
222
|
+
}
|
|
223
|
+
console.log(`[PromptUI] Found ${exportableNodes.length} exportable components`);
|
|
224
|
+
if (exportableNodes.length === 0) {
|
|
225
|
+
console.log('[PromptUI] No components found. Mark frames with # prefix to export.');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
let successCount = 0;
|
|
229
|
+
let errorCount = 0;
|
|
230
|
+
for (const node of exportableNodes) {
|
|
231
|
+
try {
|
|
232
|
+
const ast = parseNode(node, { forceLayer: options.layer });
|
|
233
|
+
const basePath = options.output ?? resolved.outputBasePath;
|
|
234
|
+
const result = await writeComponent(ast, {
|
|
235
|
+
basePath,
|
|
236
|
+
forceOverwrite: options.force,
|
|
237
|
+
});
|
|
238
|
+
if (result.success) {
|
|
239
|
+
console.log(` ✅ ${ast.name} (${ast.layer})`);
|
|
240
|
+
successCount++;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
console.log(` ❌ ${node.name}: ${result.errors?.join(', ')}`);
|
|
244
|
+
errorCount++;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
249
|
+
console.log(` ❌ ${node.name}: ${message}`);
|
|
250
|
+
errorCount++;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
console.log('');
|
|
254
|
+
console.log(`[PromptUI] Done: ${successCount} success, ${errorCount} errors`);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
258
|
+
console.error(`[PromptUI] Error: ${message}`);
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { generateCommand, generateAllCommand } from './generate.cmd.js';
|
|
2
|
+
export type { IGenerateOptions } from './generate.cmd.js';
|
|
3
|
+
export { initCommand } from './init.cmd.js';
|
|
4
|
+
export { syncTokensCommand } from './sync.cmd.js';
|
|
5
|
+
export type { ISyncOptions } from './sync.cmd.js';
|
|
6
|
+
export { mcpCommand, studioCommand, listAgents } from './mcp.cmd.js';
|
|
7
|
+
export type { IMcpOptions } from './mcp.cmd.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.cmd.d.ts","sourceRoot":"","sources":["../../src/commands/init.cmd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA8BjD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init Command
|
|
3
|
+
* Cria arquivo de configuração inicial
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile, access } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
figma: {
|
|
9
|
+
token: 'YOUR_FIGMA_TOKEN',
|
|
10
|
+
fileId: 'YOUR_FILE_ID',
|
|
11
|
+
},
|
|
12
|
+
output: {
|
|
13
|
+
basePath: 'src/components',
|
|
14
|
+
styleFormat: 'scss',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export async function initCommand() {
|
|
18
|
+
const configPath = join(process.cwd(), 'promptui.config.json');
|
|
19
|
+
// Verifica se já existe
|
|
20
|
+
try {
|
|
21
|
+
await access(configPath);
|
|
22
|
+
console.log('[PromptUI] Config file already exists: promptui.config.json');
|
|
23
|
+
console.log('[PromptUI] Delete it first if you want to reinitialize.');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Arquivo não existe, podemos criar
|
|
28
|
+
}
|
|
29
|
+
// Escreve config
|
|
30
|
+
const content = JSON.stringify(DEFAULT_CONFIG, null, 2);
|
|
31
|
+
await writeFile(configPath, content, 'utf-8');
|
|
32
|
+
console.log('[PromptUI] Created: promptui.config.json');
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log('Next steps:');
|
|
35
|
+
console.log(' 1. Get your Figma Personal Access Token:');
|
|
36
|
+
console.log(' https://www.figma.com/developers/api#access-tokens');
|
|
37
|
+
console.log('');
|
|
38
|
+
console.log(' 2. Get your Figma File ID from the URL:');
|
|
39
|
+
console.log(' https://www.figma.com/file/<FILE_ID>/...');
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(' 3. Update promptui.config.json with your values');
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log(' 4. Start the agent:');
|
|
44
|
+
console.log(' npx promptui agent');
|
|
45
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Command
|
|
3
|
+
* Executa agentes MCP do PromptUI
|
|
4
|
+
*/
|
|
5
|
+
export interface IMcpOptions {
|
|
6
|
+
input?: string;
|
|
7
|
+
output?: string;
|
|
8
|
+
preview?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Lista agentes disponíveis
|
|
12
|
+
*/
|
|
13
|
+
export declare function listAgents(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Executa um agente MCP
|
|
16
|
+
*/
|
|
17
|
+
export declare function mcpCommand(agentKey: string, input: string, options: IMcpOptions): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Inicia o PromptUI Studio (interface interativa)
|
|
20
|
+
*/
|
|
21
|
+
export declare function studioCommand(): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=mcp.cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.cmd.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.cmd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAUD;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CASjC;AAyBD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAoDf;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBnD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Command
|
|
3
|
+
* Executa agentes MCP do PromptUI
|
|
4
|
+
*/
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
const AVAILABLE_AGENTS = {
|
|
8
|
+
'figma-codegen': {
|
|
9
|
+
name: 'promptui-figma-codegen',
|
|
10
|
+
description: 'Gera componentes React a partir de JSON do Figma (100% determinístico)',
|
|
11
|
+
promptFile: '.claude/agents/promptui-figma-codegen.md',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Lista agentes disponíveis
|
|
16
|
+
*/
|
|
17
|
+
export function listAgents() {
|
|
18
|
+
console.log('[PromptUI] Available MCP Agents:\n');
|
|
19
|
+
for (const [key, agent] of Object.entries(AVAILABLE_AGENTS)) {
|
|
20
|
+
console.log(` ${key}`);
|
|
21
|
+
console.log(` ${agent.description}`);
|
|
22
|
+
console.log(` Usage: npx promptui mcp ${key} <input>`);
|
|
23
|
+
console.log('');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Carrega o prompt de um agente
|
|
28
|
+
*/
|
|
29
|
+
async function loadAgentPrompt(agentKey) {
|
|
30
|
+
const agent = AVAILABLE_AGENTS[agentKey];
|
|
31
|
+
if (!agent) {
|
|
32
|
+
throw new Error(`Unknown agent: ${agentKey}. Use 'npx promptui mcp' to list available agents.`);
|
|
33
|
+
}
|
|
34
|
+
const promptPath = join(process.cwd(), agent.promptFile);
|
|
35
|
+
try {
|
|
36
|
+
return await readFile(promptPath, 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Se não encontrar no projeto, tenta no pacote
|
|
40
|
+
throw new Error(`Agent prompt not found: ${promptPath}\n` +
|
|
41
|
+
`Make sure the PromptUI agents are configured in your project.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Executa um agente MCP
|
|
46
|
+
*/
|
|
47
|
+
export async function mcpCommand(agentKey, input, options) {
|
|
48
|
+
if (!agentKey) {
|
|
49
|
+
listAgents();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
console.log(`[PromptUI] Running MCP agent: ${agentKey}`);
|
|
53
|
+
try {
|
|
54
|
+
// Carrega o prompt do agente
|
|
55
|
+
const prompt = await loadAgentPrompt(agentKey);
|
|
56
|
+
console.log(`[PromptUI] Agent loaded: ${AVAILABLE_AGENTS[agentKey]?.name}`);
|
|
57
|
+
// Para o agente figma-codegen, precisamos do input
|
|
58
|
+
if (agentKey === 'figma-codegen') {
|
|
59
|
+
if (!input) {
|
|
60
|
+
console.error('[PromptUI] Error: Missing input (nodeId or JSON file path)');
|
|
61
|
+
console.log('Usage: npx promptui mcp figma-codegen <nodeId | file.json>');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// Aqui seria a integração com o MCP SDK
|
|
65
|
+
// Por enquanto, mostra as instruções
|
|
66
|
+
console.log('');
|
|
67
|
+
console.log('[PromptUI] MCP Agent Instructions:');
|
|
68
|
+
console.log('');
|
|
69
|
+
console.log('To use this agent with Claude:');
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log('1. Start the MCP server:');
|
|
72
|
+
console.log(' npx promptui agent');
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log('2. Connect via MCP client or use the HTTP API:');
|
|
75
|
+
console.log(' curl -X POST http://localhost:17890/generate \\');
|
|
76
|
+
console.log(' -H "Content-Type: application/json" \\');
|
|
77
|
+
console.log(` -d '{"nodeId": "${input}"}'`);
|
|
78
|
+
console.log('');
|
|
79
|
+
console.log('3. Or use the generate command directly:');
|
|
80
|
+
console.log(` npx promptui generate ${input}`);
|
|
81
|
+
console.log('');
|
|
82
|
+
if (options.preview) {
|
|
83
|
+
console.log('--- Agent Prompt Preview ---');
|
|
84
|
+
console.log(prompt.substring(0, 2000) + '...');
|
|
85
|
+
console.log('--- End Preview ---');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
91
|
+
console.error(`[PromptUI] Error: ${message}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Inicia o PromptUI Studio (interface interativa)
|
|
97
|
+
*/
|
|
98
|
+
export async function studioCommand() {
|
|
99
|
+
console.log('[PromptUI] Starting PromptUI Studio...');
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log('╔════════════════════════════════════════════════════════╗');
|
|
102
|
+
console.log('║ PromptUI Studio (Preview) ║');
|
|
103
|
+
console.log('╠════════════════════════════════════════════════════════╣');
|
|
104
|
+
console.log('║ ║');
|
|
105
|
+
console.log('║ This feature is coming soon! ║');
|
|
106
|
+
console.log('║ ║');
|
|
107
|
+
console.log('║ PromptUI Studio will provide: ║');
|
|
108
|
+
console.log('║ - Interactive component generation ║');
|
|
109
|
+
console.log('║ - Visual preview of generated components ║');
|
|
110
|
+
console.log('║ - Token management and sync ║');
|
|
111
|
+
console.log('║ - Claude AI integration for suggestions ║');
|
|
112
|
+
console.log('║ ║');
|
|
113
|
+
console.log('║ For now, use the CLI commands: ║');
|
|
114
|
+
console.log('║ - npx promptui generate <nodeId> ║');
|
|
115
|
+
console.log('║ - npx promptui generate all ║');
|
|
116
|
+
console.log('║ - npx promptui sync tokens ║');
|
|
117
|
+
console.log('║ ║');
|
|
118
|
+
console.log('╚════════════════════════════════════════════════════════╝');
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.cmd.d.ts","sourceRoot":"","sources":["../../src/commands/sync.cmd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+JD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAmH5E"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Command
|
|
3
|
+
* Sincroniza tokens do Figma para o projeto local
|
|
4
|
+
*/
|
|
5
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { createFigmaClient } from '@promptui-lib/figma-parser';
|
|
8
|
+
import { loadConfig, resolveConfig, validateConfig } from '@promptui-lib/mcp-agent';
|
|
9
|
+
/**
|
|
10
|
+
* Converte cor RGB (0-1) para hex
|
|
11
|
+
*/
|
|
12
|
+
function rgbToHex(color) {
|
|
13
|
+
const r = Math.round(color.r * 255).toString(16).padStart(2, '0');
|
|
14
|
+
const g = Math.round(color.g * 255).toString(16).padStart(2, '0');
|
|
15
|
+
const b = Math.round(color.b * 255).toString(16).padStart(2, '0');
|
|
16
|
+
return `#${r}${g}${b}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Converte nome do estilo para nome de variável SCSS
|
|
20
|
+
*/
|
|
21
|
+
function styleNameToVariable(name) {
|
|
22
|
+
return name
|
|
23
|
+
.toLowerCase()
|
|
24
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
25
|
+
.replace(/^-|-$/g, '');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Gera arquivo SCSS de cores
|
|
29
|
+
*/
|
|
30
|
+
function generateColorsScss(colors) {
|
|
31
|
+
const lines = [
|
|
32
|
+
'// PromptUI - Color Tokens',
|
|
33
|
+
'// Auto-generated from Figma styles',
|
|
34
|
+
'// Do not edit manually',
|
|
35
|
+
'',
|
|
36
|
+
];
|
|
37
|
+
for (const color of colors) {
|
|
38
|
+
const varName = `$color-${styleNameToVariable(color.name)}`;
|
|
39
|
+
lines.push(`${varName}: ${color.value};`);
|
|
40
|
+
}
|
|
41
|
+
return lines.join('\n');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Gera arquivo SCSS de tipografia
|
|
45
|
+
*/
|
|
46
|
+
function generateTypographyScss(textStyles) {
|
|
47
|
+
const lines = [
|
|
48
|
+
'// PromptUI - Typography Tokens',
|
|
49
|
+
'// Auto-generated from Figma styles',
|
|
50
|
+
'// Do not edit manually',
|
|
51
|
+
'',
|
|
52
|
+
];
|
|
53
|
+
// Agrupa por categoria
|
|
54
|
+
const fontFamilies = new Set();
|
|
55
|
+
const fontSizes = new Map();
|
|
56
|
+
const fontWeights = new Set();
|
|
57
|
+
for (const style of textStyles) {
|
|
58
|
+
fontFamilies.add(style.fontFamily);
|
|
59
|
+
fontSizes.set(style.fontSize, style.name);
|
|
60
|
+
fontWeights.add(style.fontWeight);
|
|
61
|
+
}
|
|
62
|
+
// Font families
|
|
63
|
+
lines.push('// Font Families');
|
|
64
|
+
let familyIndex = 1;
|
|
65
|
+
for (const family of fontFamilies) {
|
|
66
|
+
lines.push(`$font-family-${familyIndex}: "${family}", sans-serif;`);
|
|
67
|
+
familyIndex++;
|
|
68
|
+
}
|
|
69
|
+
lines.push('');
|
|
70
|
+
// Font sizes
|
|
71
|
+
lines.push('// Font Sizes');
|
|
72
|
+
const sortedSizes = Array.from(fontSizes.entries()).sort((a, b) => a[0] - b[0]);
|
|
73
|
+
for (const [size, name] of sortedSizes) {
|
|
74
|
+
const varName = `$font-size-${styleNameToVariable(name)}`;
|
|
75
|
+
lines.push(`${varName}: ${size}px;`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('');
|
|
78
|
+
// Font weights
|
|
79
|
+
lines.push('// Font Weights');
|
|
80
|
+
const weightNames = {
|
|
81
|
+
100: 'thin',
|
|
82
|
+
200: 'extralight',
|
|
83
|
+
300: 'light',
|
|
84
|
+
400: 'regular',
|
|
85
|
+
500: 'medium',
|
|
86
|
+
600: 'semibold',
|
|
87
|
+
700: 'bold',
|
|
88
|
+
800: 'extrabold',
|
|
89
|
+
900: 'black',
|
|
90
|
+
};
|
|
91
|
+
const sortedWeights = Array.from(fontWeights).sort((a, b) => a - b);
|
|
92
|
+
for (const weight of sortedWeights) {
|
|
93
|
+
const name = weightNames[weight] ?? `w${weight}`;
|
|
94
|
+
lines.push(`$font-weight-${name}: ${weight};`);
|
|
95
|
+
}
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Gera arquivo SCSS de efeitos (shadows)
|
|
100
|
+
*/
|
|
101
|
+
function generateEffectsScss(effects) {
|
|
102
|
+
const lines = [
|
|
103
|
+
'// PromptUI - Effect Tokens',
|
|
104
|
+
'// Auto-generated from Figma styles',
|
|
105
|
+
'// Do not edit manually',
|
|
106
|
+
'',
|
|
107
|
+
'// Shadows',
|
|
108
|
+
];
|
|
109
|
+
for (const effect of effects) {
|
|
110
|
+
if (effect.type === 'DROP_SHADOW' && effect.color) {
|
|
111
|
+
const varName = `$shadow-${styleNameToVariable(effect.name)}`;
|
|
112
|
+
const x = effect.offset?.x ?? 0;
|
|
113
|
+
const y = effect.offset?.y ?? 0;
|
|
114
|
+
const blur = effect.radius ?? 0;
|
|
115
|
+
const color = `rgba(${Math.round(effect.color.r * 255)}, ${Math.round(effect.color.g * 255)}, ${Math.round(effect.color.b * 255)}, ${effect.color.a.toFixed(2)})`;
|
|
116
|
+
lines.push(`${varName}: ${x}px ${y}px ${blur}px ${color};`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return lines.join('\n');
|
|
120
|
+
}
|
|
121
|
+
export async function syncTokensCommand(options) {
|
|
122
|
+
console.log('[PromptUI] Syncing tokens from Figma...');
|
|
123
|
+
// Carrega config
|
|
124
|
+
const config = await loadConfig();
|
|
125
|
+
const resolved = resolveConfig(config);
|
|
126
|
+
// Valida
|
|
127
|
+
const errors = validateConfig(resolved);
|
|
128
|
+
if (errors.length > 0) {
|
|
129
|
+
console.error('[PromptUI] Configuration errors:');
|
|
130
|
+
for (const error of errors) {
|
|
131
|
+
console.error(` - ${error}`);
|
|
132
|
+
}
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const client = createFigmaClient({ token: resolved.figmaToken });
|
|
137
|
+
console.log('[PromptUI] Fetching styles from Figma...');
|
|
138
|
+
const stylesRecord = await client.getStyles(resolved.figmaFileId);
|
|
139
|
+
if (!stylesRecord || Object.keys(stylesRecord).length === 0) {
|
|
140
|
+
console.log('[PromptUI] No styles found in the Figma file.');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const stylesArray = Object.values(stylesRecord);
|
|
144
|
+
console.log(`[PromptUI] Found ${stylesArray.length} styles`);
|
|
145
|
+
// Separa por tipo
|
|
146
|
+
const colorStyles = [];
|
|
147
|
+
const textStyles = [];
|
|
148
|
+
const effectStyles = [];
|
|
149
|
+
for (const style of stylesArray) {
|
|
150
|
+
// Aqui precisaríamos buscar os detalhes de cada style
|
|
151
|
+
// Por enquanto, apenas categoriza
|
|
152
|
+
if (style.styleType === 'FILL') {
|
|
153
|
+
// Placeholder - precisaria buscar o node para ter a cor
|
|
154
|
+
colorStyles.push({
|
|
155
|
+
name: style.name,
|
|
156
|
+
value: '#000000', // Placeholder
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
else if (style.styleType === 'TEXT') {
|
|
160
|
+
textStyles.push({
|
|
161
|
+
name: style.name,
|
|
162
|
+
fontFamily: 'Inter',
|
|
163
|
+
fontSize: 16,
|
|
164
|
+
fontWeight: 400,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
else if (style.styleType === 'EFFECT') {
|
|
168
|
+
effectStyles.push({
|
|
169
|
+
name: style.name,
|
|
170
|
+
type: 'DROP_SHADOW',
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Cria diretório de output
|
|
175
|
+
const outputDir = options.output ?? join(process.cwd(), 'src/styles/tokens');
|
|
176
|
+
await mkdir(outputDir, { recursive: true });
|
|
177
|
+
// Gera arquivos
|
|
178
|
+
if (colorStyles.length > 0) {
|
|
179
|
+
const colorsPath = join(outputDir, '_colors.scss');
|
|
180
|
+
await writeFile(colorsPath, generateColorsScss(colorStyles), 'utf-8');
|
|
181
|
+
console.log(` ✅ Colors: ${colorsPath}`);
|
|
182
|
+
}
|
|
183
|
+
if (textStyles.length > 0) {
|
|
184
|
+
const typographyPath = join(outputDir, '_typography.scss');
|
|
185
|
+
await writeFile(typographyPath, generateTypographyScss(textStyles), 'utf-8');
|
|
186
|
+
console.log(` ✅ Typography: ${typographyPath}`);
|
|
187
|
+
}
|
|
188
|
+
if (effectStyles.length > 0) {
|
|
189
|
+
const effectsPath = join(outputDir, '_effects.scss');
|
|
190
|
+
await writeFile(effectsPath, generateEffectsScss(effectStyles), 'utf-8');
|
|
191
|
+
console.log(` ✅ Effects: ${effectsPath}`);
|
|
192
|
+
}
|
|
193
|
+
// Gera index
|
|
194
|
+
const indexPath = join(outputDir, '_index.scss');
|
|
195
|
+
const indexContent = [
|
|
196
|
+
'// PromptUI - Design Tokens',
|
|
197
|
+
'// Auto-generated from Figma',
|
|
198
|
+
'',
|
|
199
|
+
"@forward 'colors';",
|
|
200
|
+
"@forward 'typography';",
|
|
201
|
+
"@forward 'effects';",
|
|
202
|
+
'',
|
|
203
|
+
].join('\n');
|
|
204
|
+
await writeFile(indexPath, indexContent, 'utf-8');
|
|
205
|
+
console.log(` ✅ Index: ${indexPath}`);
|
|
206
|
+
console.log('');
|
|
207
|
+
console.log('[PromptUI] Tokens synced successfully!');
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
211
|
+
console.error(`[PromptUI] Error: ${message}`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgEH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAkH/E"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @promptui-lib/cli
|
|
3
|
+
* CLI for PromptUI - Figma to React code generator
|
|
4
|
+
*/
|
|
5
|
+
import { parseArgs } from 'node:util';
|
|
6
|
+
import { startAgent } from '@promptui-lib/mcp-agent';
|
|
7
|
+
import { generateCommand, generateAllCommand } from './commands/generate.cmd.js';
|
|
8
|
+
import { initCommand } from './commands/init.cmd.js';
|
|
9
|
+
import { syncTokensCommand } from './commands/sync.cmd.js';
|
|
10
|
+
import { mcpCommand, studioCommand, listAgents } from './commands/mcp.cmd.js';
|
|
11
|
+
const HELP_TEXT = `
|
|
12
|
+
PromptUI - Figma to React Code Generator
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
promptui <command> [options]
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
init Initialize configuration file
|
|
19
|
+
agent Start the MCP agent server
|
|
20
|
+
generate Generate all #marked components (React + SCSS)
|
|
21
|
+
generate mui Generate all #marked components (Material UI)
|
|
22
|
+
generate tailwind Generate all #marked components (Tailwind CSS)
|
|
23
|
+
generate bootstrap Generate all #marked components (Bootstrap)
|
|
24
|
+
generate <nodeId> Generate specific node by ID
|
|
25
|
+
generate <file.json> Generate from local JSON file
|
|
26
|
+
sync tokens Sync design tokens from Figma
|
|
27
|
+
mcp <agent> [input] Run MCP agent (use 'mcp' alone to list agents)
|
|
28
|
+
studio Start PromptUI Studio (interactive mode)
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--help, -h Show this help message
|
|
32
|
+
--version, -v Show version
|
|
33
|
+
--force, -f Force overwrite existing files
|
|
34
|
+
--output, -o Output directory
|
|
35
|
+
--layer, -l Force layer (atoms|molecules|organisms)
|
|
36
|
+
--preview, -p Preview output without writing files
|
|
37
|
+
--no-meta Skip generating meta.json
|
|
38
|
+
|
|
39
|
+
Frameworks:
|
|
40
|
+
react React + SCSS with BEM methodology (default)
|
|
41
|
+
mui Material UI with sx props and MUI components
|
|
42
|
+
tailwind Tailwind CSS utility classes
|
|
43
|
+
bootstrap Bootstrap CSS classes
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
promptui init # Create promptui.config.json
|
|
47
|
+
promptui agent # Start agent on port 17890
|
|
48
|
+
promptui generate # Generate all (React + SCSS)
|
|
49
|
+
promptui generate mui # Generate all (Material UI)
|
|
50
|
+
promptui generate tailwind # Generate all (Tailwind CSS)
|
|
51
|
+
promptui generate bootstrap # Generate all (Bootstrap)
|
|
52
|
+
promptui generate 123:456 # Generate specific node
|
|
53
|
+
promptui generate ./button.json # Generate from local JSON
|
|
54
|
+
promptui generate ./button.json -p # Preview without writing
|
|
55
|
+
promptui sync tokens # Sync tokens from Figma
|
|
56
|
+
|
|
57
|
+
Environment Variables:
|
|
58
|
+
FIGMA_TOKEN Figma personal access token
|
|
59
|
+
FIGMA_FILE_ID Default Figma file ID
|
|
60
|
+
PROMPTUI_PORT Agent port (default: 17890)
|
|
61
|
+
PROMPTUI_OUTPUT_PATH Output path (default: src/components)
|
|
62
|
+
`;
|
|
63
|
+
const VERSION = '0.1.0';
|
|
64
|
+
export async function run(args = process.argv.slice(2)) {
|
|
65
|
+
const { values, positionals } = parseArgs({
|
|
66
|
+
args,
|
|
67
|
+
options: {
|
|
68
|
+
help: { type: 'boolean', short: 'h' },
|
|
69
|
+
version: { type: 'boolean', short: 'v' },
|
|
70
|
+
force: { type: 'boolean', short: 'f' },
|
|
71
|
+
output: { type: 'string', short: 'o' },
|
|
72
|
+
layer: { type: 'string', short: 'l' },
|
|
73
|
+
framework: { type: 'string', short: 'F' },
|
|
74
|
+
preview: { type: 'boolean', short: 'p' },
|
|
75
|
+
'no-meta': { type: 'boolean' },
|
|
76
|
+
},
|
|
77
|
+
allowPositionals: true,
|
|
78
|
+
});
|
|
79
|
+
// Version (check first, before help)
|
|
80
|
+
if (values.version) {
|
|
81
|
+
console.log(`promptui v${VERSION}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Help
|
|
85
|
+
if (values.help || positionals.length === 0) {
|
|
86
|
+
console.log(HELP_TEXT);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const command = positionals[0];
|
|
90
|
+
switch (command) {
|
|
91
|
+
// promptui init
|
|
92
|
+
case 'init':
|
|
93
|
+
await initCommand();
|
|
94
|
+
break;
|
|
95
|
+
// promptui agent
|
|
96
|
+
case 'agent':
|
|
97
|
+
await startAgent();
|
|
98
|
+
break;
|
|
99
|
+
// promptui generate [framework|nodeId|file.json]
|
|
100
|
+
case 'generate': {
|
|
101
|
+
const input = positionals[1];
|
|
102
|
+
const FRAMEWORKS = ['react', 'mui', 'tailwind', 'bootstrap'];
|
|
103
|
+
// Detecta se o input é um framework
|
|
104
|
+
const isFramework = input && FRAMEWORKS.includes(input);
|
|
105
|
+
// Se não tem input ou é um framework, gera todos os componentes
|
|
106
|
+
const generateAll = !input || isFramework;
|
|
107
|
+
// Define o framework (do input ou do flag)
|
|
108
|
+
const framework = isFramework
|
|
109
|
+
? input
|
|
110
|
+
: values.framework;
|
|
111
|
+
const generateOptions = {
|
|
112
|
+
force: values.force,
|
|
113
|
+
output: values.output,
|
|
114
|
+
layer: values.layer,
|
|
115
|
+
framework,
|
|
116
|
+
preview: values.preview,
|
|
117
|
+
noMeta: values['no-meta'],
|
|
118
|
+
};
|
|
119
|
+
if (generateAll) {
|
|
120
|
+
await generateAllCommand(generateOptions);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
await generateCommand(input, generateOptions);
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
// promptui sync <subcommand>
|
|
128
|
+
case 'sync': {
|
|
129
|
+
const subcommand = positionals[1];
|
|
130
|
+
if (subcommand === 'tokens') {
|
|
131
|
+
await syncTokensCommand({ output: values.output });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.error(`Unknown sync subcommand: ${subcommand}`);
|
|
135
|
+
console.log('Available: sync tokens');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
// promptui mcp [agent] [input]
|
|
141
|
+
case 'mcp': {
|
|
142
|
+
const agentKey = positionals[1];
|
|
143
|
+
const input = positionals[2];
|
|
144
|
+
if (!agentKey) {
|
|
145
|
+
listAgents();
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
await mcpCommand(agentKey, input, {
|
|
149
|
+
output: values.output,
|
|
150
|
+
preview: values.preview,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
// promptui studio
|
|
156
|
+
case 'studio':
|
|
157
|
+
await studioCommand();
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
console.error(`Unknown command: ${command}`);
|
|
161
|
+
console.log(HELP_TEXT);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Execute CLI when run directly
|
|
166
|
+
run().catch((error) => {
|
|
167
|
+
console.error('[PromptUI] Fatal error:', error.message);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@promptui-lib/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "CLI for PromptUI - Figma to React code generator",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Desiree Menezes",
|
|
9
|
+
"url": "https://github.com/desireemenezes"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/desireemenezes/promptUI.git",
|
|
14
|
+
"directory": "packages/cli"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/desireemenezes/promptUI#readme",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"figma",
|
|
19
|
+
"react",
|
|
20
|
+
"codegen",
|
|
21
|
+
"design-to-code",
|
|
22
|
+
"component-generator",
|
|
23
|
+
"scss",
|
|
24
|
+
"mui",
|
|
25
|
+
"tailwind",
|
|
26
|
+
"bootstrap"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"bin": {
|
|
32
|
+
"promptui": "./bin/promptui.js"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"bin"
|
|
46
|
+
],
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@promptui-lib/core": "0.1.0",
|
|
49
|
+
"@promptui-lib/figma-parser": "0.1.0",
|
|
50
|
+
"@promptui-lib/codegen": "0.1.0",
|
|
51
|
+
"@promptui-lib/mcp-agent": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"typescript": "^5.3.0",
|
|
56
|
+
"rimraf": "^5.0.0"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"dev": "tsc --watch",
|
|
61
|
+
"clean": "rimraf dist"
|
|
62
|
+
}
|
|
63
|
+
}
|