rook-cli 1.2.2 → 1.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rook-cli",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "description": "CLI para instalar componentes Shopify",
5
5
  "repository": {
6
6
  "type": "git",
package/src/mcp/server.js CHANGED
@@ -93,6 +93,10 @@ const InstallComponentSchema = z.object({
93
93
  type: z
94
94
  .enum(['component', 'kit'])
95
95
  .describe('Tipo do pacote: "component" para componente individual, "kit" para kit completo.'),
96
+ projectPath: z
97
+ .string()
98
+ .optional()
99
+ .describe('Obrigatório no Cursor/Claude Desktop: Caminho absoluto para a raiz do projeto (ex: /Users/nome/projeto).'),
96
100
  });
97
101
 
98
102
  const GenerateScaffoldSchema = z.object({
@@ -103,6 +107,10 @@ const GenerateScaffoldSchema = z.object({
103
107
  elementType: z
104
108
  .enum(['section', 'block', 'snippet', 'controller'])
105
109
  .describe('Tipo de recurso Shopify a ser gerado.'),
110
+ projectPath: z
111
+ .string()
112
+ .optional()
113
+ .describe('Obrigatório no Cursor/Claude Desktop: Caminho absoluto para a raiz do projeto (ex: /Users/nome/projeto).'),
106
114
  });
107
115
 
108
116
  // ═══════════════════════════════════════════════════════════════
@@ -156,8 +164,8 @@ async function handleListComponents(args) {
156
164
  * Instala um componente individual ou kit completo no tema do usuário.
157
165
  */
158
166
  async function handleInstallComponent(args) {
159
- const { name, type } = InstallComponentSchema.parse(args);
160
- const diretorioAtual = process.cwd();
167
+ const { name, type, projectPath } = InstallComponentSchema.parse(args);
168
+ const diretorioAtual = projectPath || process.cwd();
161
169
 
162
170
  if (type === 'kit') {
163
171
  // --- Instalação de Kit ---
@@ -218,7 +226,7 @@ async function handleInstallComponent(args) {
218
226
  * Gera boilerplate de um componente Liquid (section, block, snippet, controller).
219
227
  */
220
228
  async function handleGenerateScaffold(args) {
221
- const { name, elementType } = GenerateScaffoldSchema.parse(args);
229
+ const { name, elementType, projectPath } = GenerateScaffoldSchema.parse(args);
222
230
 
223
231
  // Normaliza nomes (kebab, Pascal, snake)
224
232
  const names = generateNames(name);
@@ -227,13 +235,20 @@ async function handleGenerateScaffold(args) {
227
235
  const arquivo = await scaffoldService.generate(elementType, names);
228
236
 
229
237
  // Grava no disco
230
- const diretorioAtual = process.cwd();
231
- const destDir = path.join(diretorioAtual, arquivo.outputDir);
232
- const destPath = path.join(destDir, arquivo.fileName);
238
+ const diretorioAtual = projectPath || process.cwd();
239
+
240
+ // Garantimos que o caminho seja relativo à pasta onde o comando foi chamado
241
+ // Evita erro de permissão ao tentar criar pastas na raiz do sistema (/)
242
+ const destDir = path.resolve(diretorioAtual, './' + arquivo.outputDir);
243
+ const destPath = path.resolve(destDir, './' + arquivo.fileName);
233
244
  const caminhoRelativo = path.join(arquivo.outputDir, arquivo.fileName);
234
245
 
235
- await fs.ensureDir(destDir);
236
- await fs.writeFile(destPath, arquivo.content, 'utf-8');
246
+ try {
247
+ await fs.ensureDir(destDir);
248
+ await fs.writeFile(destPath, arquivo.content, 'utf-8');
249
+ } catch (fsErro) {
250
+ throw new Error(`Falha ao gravar arquivo em "${destDir}": ${fsErro.message}. Verifique as permissões de escrita.`);
251
+ }
237
252
 
238
253
  return {
239
254
  content: [{
@@ -331,8 +346,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
331
346
  enum: ['component', 'kit'],
332
347
  description: 'Tipo do pacote: "component" ou "kit".',
333
348
  },
349
+ projectPath: {
350
+ type: 'string',
351
+ description: 'Obrigatório no Cursor/Claude Desktop: Caminho absoluto para a raiz do repositório Shopify que o pacote deve ser instalado.',
352
+ },
334
353
  },
335
- required: ['name', 'type'],
354
+ required: ['name', 'type', 'projectPath'],
336
355
  },
337
356
  },
338
357
  {
@@ -352,8 +371,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
352
371
  enum: ['section', 'block', 'snippet', 'controller'],
353
372
  description: 'Tipo de recurso Shopify: section, block, snippet ou controller (JS asset).',
354
373
  },
374
+ projectPath: {
375
+ type: 'string',
376
+ description: 'Obrigatório no Cursor/Claude Desktop: Caminho absoluto para a raiz do repositório Shopify que a entidade será gerada.',
377
+ },
355
378
  },
356
- required: ['name', 'elementType'],
379
+ required: ['name', 'elementType', 'projectPath'],
357
380
  },
358
381
  },
359
382
  ],
@@ -49,7 +49,7 @@ export class Logger {
49
49
  banner() {
50
50
  console.log('');
51
51
  console.log(pc.bold(pc.white(' ╔══════════════════════════════╗')));
52
- console.log(pc.bold(pc.white(' ║ ♟️ ROOK CLI v1.2.1 ║')));
52
+ console.log(pc.bold(pc.white(' ║ ♟️ ROOK CLI v1.3.1 ║')));
53
53
  console.log(pc.bold(pc.white(' ║ Shopify Component Tool ║')));
54
54
  console.log(pc.bold(pc.white(' ╚══════════════════════════════╝')));
55
55
  console.log('');