openprompt-lang 0.3.0 → 0.4.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.
Files changed (90) hide show
  1. package/README.md +483 -32
  2. package/bin/cli.js +232 -41
  3. package/bin/create.js +135 -0
  4. package/bin/lint.js +20 -21
  5. package/docs/COMMANDS.md +200 -127
  6. package/docs/COMMITS/INDEX.md +1 -0
  7. package/docs/PROMPT_AI_CONTEXT.md +99 -0
  8. package/docs/langs/dotnet.md +36 -0
  9. package/docs/langs/java-spring.md +45 -0
  10. package/docs/langs/python-fastapi.md +35 -0
  11. package/docs/langs/unity.md +30 -0
  12. package/docs/langs/vue-nuxt.md +36 -0
  13. package/package.json +31 -3
  14. package/scaffolds/.cursorrules +6 -0
  15. package/scaffolds/AGENTS.md +27 -0
  16. package/scaffolds/Dockerfile +11 -0
  17. package/scaffolds/capacitor.config.ts +17 -0
  18. package/scaffolds/netlify.toml +8 -0
  19. package/scaffolds/prompt-lang.json +15 -0
  20. package/scaffolds/railway.json +12 -0
  21. package/scaffolds/tailwind.config.js +8 -0
  22. package/scaffolds/tauri.conf.json +26 -0
  23. package/schemas/language-module.json +116 -0
  24. package/schemas/prompt-lang.json +38 -3
  25. package/schemas/structures.json +145 -0
  26. package/src/ai/prompt-builder.js +184 -0
  27. package/src/ai/providers.js +247 -0
  28. package/src/annotations/registry.js +39 -0
  29. package/src/annotations/tags.json +24 -0
  30. package/src/commands/ai-gen.js +161 -0
  31. package/src/commands/component.js +242 -212
  32. package/src/commands/context.js +184 -109
  33. package/src/commands/extract.js +242 -0
  34. package/src/commands/figma.js +15 -15
  35. package/src/commands/init.js +197 -93
  36. package/src/commands/integrate.js +406 -0
  37. package/src/commands/lang.js +148 -0
  38. package/src/commands/qa-gen.js +139 -0
  39. package/src/commands/scaffold.js +127 -0
  40. package/src/commands/suggest.js +24 -14
  41. package/src/commands/teach.js +110 -0
  42. package/src/commands/validate.js +143 -83
  43. package/src/commands/wizard.js +456 -0
  44. package/src/generators/figma-prompt.js +20 -12
  45. package/src/language-service/plugin.cjs +94 -0
  46. package/src/language-service/plugin.d.ts +6 -0
  47. package/src/mcp-server.js +605 -0
  48. package/src/templates/langs/react/INDEX.json +262 -0
  49. package/src/templates/langs/react/MODULE.json +166 -0
  50. package/src/templates/langs/react/templates/hooks/useAuth.template.ts +134 -0
  51. package/src/templates/langs/react/templates/hooks/useDebounce.template.ts +45 -0
  52. package/src/templates/langs/react/templates/hooks/useForm.template.ts +146 -0
  53. package/src/templates/langs/react/templates/hooks/usePagination.template.ts +108 -0
  54. package/src/templates/langs/react/templates/services/apiService.template.ts +123 -0
  55. package/src/templates/langs/react/templates/ui/Button.template.tsx +87 -0
  56. package/src/templates/langs/react/templates/ui/Card.template.tsx +85 -0
  57. package/src/templates/langs/react/templates/ui/DataTable.template.tsx +163 -0
  58. package/src/templates/langs/react/templates/ui/Input.template.tsx +96 -0
  59. package/src/templates/langs/react/templates/ui/Modal.template.tsx +133 -0
  60. package/src/templates/langs/react/templates/ui/Select.template.tsx +99 -0
  61. package/src/templates/langs/vue/INDEX.json +246 -0
  62. package/src/templates/langs/vue/MODULE.json +105 -0
  63. package/src/templates/langs/vue/templates/composables/useAuth.template.ts +106 -0
  64. package/src/templates/langs/vue/templates/composables/useDebounce.template.ts +47 -0
  65. package/src/templates/langs/vue/templates/composables/useFetch.template.ts +54 -0
  66. package/src/templates/langs/vue/templates/composables/useForm.template.ts +127 -0
  67. package/src/templates/langs/vue/templates/composables/usePagination.template.ts +98 -0
  68. package/src/templates/langs/vue/templates/services/apiService.template.ts +116 -0
  69. package/src/templates/langs/vue/templates/ui/Button.template.vue +79 -0
  70. package/src/templates/langs/vue/templates/ui/Card.template.vue +73 -0
  71. package/src/templates/langs/vue/templates/ui/DataTable.template.vue +115 -0
  72. package/src/templates/langs/vue/templates/ui/Input.template.vue +70 -0
  73. package/src/templates/langs/vue/templates/ui/Modal.template.vue +112 -0
  74. package/src/templates/langs/vue/templates/ui/Select.template.vue +77 -0
  75. package/src/templates/scripts/log-actividad.sh +32 -0
  76. package/src/templates/scripts/log-commit.sh +35 -0
  77. package/src/templates/scripts/log-error.sh +45 -0
  78. package/src/templates/scripts/validate.sh +23 -0
  79. package/src/ts-transformer/index.cjs +86 -0
  80. package/src/utils/ai.js +35 -53
  81. package/src/utils/annotations.js +260 -214
  82. package/src/utils/config.js +61 -13
  83. package/src/utils/error-learner.js +203 -0
  84. package/src/utils/file-utils.js +119 -0
  85. package/src/utils/language-loader.js +167 -0
  86. package/src/utils/template-utils.js +45 -0
  87. package/src/vite-plugin/index.js +54 -0
  88. package/vscode-extension/package.json +23 -2
  89. package/vscode-extension/snippets/promptlang.json +1 -3
  90. package/vscode-extension/syntaxes/annotations-code.tmGrammar.json +15 -0
@@ -1,7 +1,8 @@
1
- import { writeFileSync, readFileSync, existsSync, mkdirSync } from "fs";
2
- import { join } from "path";
3
- import chalk from "chalk";
4
- import { detectStack } from "../utils/config.js";
1
+ import { writeFileSync, readFileSync, existsSync, mkdirSync } from "fs"
2
+ import { join } from "path"
3
+ import chalk from "chalk"
4
+ import inquirer from "inquirer"
5
+ import { detectStack } from "../utils/config.js"
5
6
 
6
7
  const BASE_STRUCTURE = {
7
8
  "src/components/ui": { desc: "Componentes atómicos reutilizables" },
@@ -19,8 +20,8 @@ const BASE_STRUCTURE = {
19
20
  "docs/BACKLOG": { desc: "Backlog por fases" },
20
21
  "docs/PROMPTS/PLANTILLAS": { desc: "Prompts reutilizables" },
21
22
  "docs/PROMPTS/STACK": { desc: "Contextos por tecnología" },
22
- "scripts": { desc: "Scripts de automatización" },
23
- };
23
+ scripts: { desc: "Scripts de automatización" },
24
+ }
24
25
 
25
26
  const DESCRIPTIVE_SCRIPTS = {
26
27
  "dev:start": "vite",
@@ -34,24 +35,25 @@ const DESCRIPTIVE_SCRIPTS = {
34
35
  "test:unit": "vitest run",
35
36
  "test:watch": "vitest",
36
37
  "test:coverage": "vitest run --coverage",
37
- "validate:all": "npm run lint:check && npm run type:check && npm run quality:doctor && npm run test:unit",
38
- };
38
+ "validate:all":
39
+ "npm run lint:check && npm run type:check && npm run quality:doctor && npm run test:unit",
40
+ }
39
41
 
40
42
  export async function init(options) {
41
43
  if (options.existing) {
42
- return initExisting();
44
+ return initExisting()
43
45
  }
44
46
 
45
- const projectName = options.name || "mi-proyecto";
46
- const baseDir = join(process.cwd(), projectName);
47
+ const projectName = options.name || "mi-proyecto"
48
+ const baseDir = join(process.cwd(), projectName)
47
49
 
48
- console.log(chalk.cyan(`\n🚀 Inicializando proyecto: ${projectName}\n`));
50
+ console.log(chalk.cyan(`\n🚀 Inicializando proyecto: ${projectName}\n`))
49
51
 
50
52
  // Crear directorios
51
53
  for (const [dir, meta] of Object.entries(BASE_STRUCTURE)) {
52
- const fullPath = join(baseDir, dir);
53
- mkdirSync(fullPath, { recursive: true });
54
- console.log(` 📁 ${dir}/`);
54
+ const fullPath = join(baseDir, dir)
55
+ mkdirSync(fullPath, { recursive: true })
56
+ console.log(` 📁 ${dir}/`)
55
57
  }
56
58
 
57
59
  // Crear prompt-lang.json
@@ -79,10 +81,10 @@ export async function init(options) {
79
81
  },
80
82
  docs: { commits: true, logs: true, backlog: true },
81
83
  extractor: { ignore: [".env", "*.local", "dist"], output: "contexto.md" },
82
- };
84
+ }
83
85
 
84
- writeFileSync(join(baseDir, "prompt-lang.json"), JSON.stringify(config, null, 2), "utf-8");
85
- console.log(chalk.green(" ✅ prompt-lang.json"));
86
+ writeFileSync(join(baseDir, "prompt-lang.json"), JSON.stringify(config, null, 2), "utf-8")
87
+ console.log(chalk.green(" ✅ prompt-lang.json"))
86
88
 
87
89
  // Crear AGENTS.md
88
90
  const agentsContent = `# AGENTS.md — Contexto para IA
@@ -116,10 +118,10 @@ ${config.profile}
116
118
  ## Referencias
117
119
  - Framework: docs/FRAMEWORK.md
118
120
  - Prompt library: docs/PROMPTS/INDEX.md
119
- `;
121
+ `
120
122
 
121
- writeFileSync(join(baseDir, "AGENTS.md"), agentsContent, "utf-8");
122
- console.log(chalk.green(" ✅ AGENTS.md"));
123
+ writeFileSync(join(baseDir, "AGENTS.md"), agentsContent, "utf-8")
124
+ console.log(chalk.green(" ✅ AGENTS.md"))
123
125
 
124
126
  // Crear .gitignore
125
127
  const gitignore = `node_modules/
@@ -131,10 +133,10 @@ build/
131
133
  .DS_Store
132
134
  coverage/
133
135
  contexto.md
134
- `;
136
+ `
135
137
 
136
- writeFileSync(join(baseDir, ".gitignore"), gitignore, "utf-8");
137
- console.log(chalk.green(" ✅ .gitignore"));
138
+ writeFileSync(join(baseDir, ".gitignore"), gitignore, "utf-8")
139
+ console.log(chalk.green(" ✅ .gitignore"))
138
140
 
139
141
  // Crear package.json con scripts descriptivos
140
142
  const packageJson = {
@@ -143,10 +145,10 @@ contexto.md
143
145
  private: true,
144
146
  type: "module",
145
147
  scripts: { ...DESCRIPTIVE_SCRIPTS },
146
- };
148
+ }
147
149
 
148
- writeFileSync(join(baseDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
149
- console.log(chalk.green(" ✅ package.json (scripts descriptivos)"));
150
+ writeFileSync(join(baseDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8")
151
+ console.log(chalk.green(" ✅ package.json (scripts descriptivos)"))
150
152
 
151
153
  // Crear scripts de validación
152
154
  const validateScript = `#!/bin/bash
@@ -167,10 +169,10 @@ echo "[4/4] Tests..."
167
169
  npm run test:unit || { echo "❌ Tests fallaron"; exit 1; }
168
170
 
169
171
  echo "=== ✅ Pipeline completo — Código válido ==="
170
- `;
172
+ `
171
173
 
172
- writeFileSync(join(baseDir, "scripts/validate.sh"), validateScript, "utf-8");
173
- console.log(chalk.green(" ✅ scripts/validate.sh"));
174
+ writeFileSync(join(baseDir, "scripts/validate.sh"), validateScript, "utf-8")
175
+ console.log(chalk.green(" ✅ scripts/validate.sh"))
174
176
 
175
177
  // Crear docs/BACKLOG/PHASE-1-core.md
176
178
  const backlogPhase1 = `# PHASE-1 Core — MVP Funcional
@@ -197,53 +199,60 @@ echo "=== ✅ Pipeline completo — Código válido ==="
197
199
  - [ ] Registro de usuarios
198
200
  - [ ] Protección de rutas
199
201
  - [ ] Manejo de sesión con Zustand
200
- `;
202
+ `
201
203
 
202
- writeFileSync(join(baseDir, "docs/BACKLOG/PHASE-1-core.md"), backlogPhase1, "utf-8");
203
- console.log(chalk.green(" ✅ docs/BACKLOG/PHASE-1-core.md"));
204
+ writeFileSync(join(baseDir, "docs/BACKLOG/PHASE-1-core.md"), backlogPhase1, "utf-8")
205
+ console.log(chalk.green(" ✅ docs/BACKLOG/PHASE-1-core.md"))
204
206
 
205
207
  // Crear docs/COMMITS/INDEX.md
206
208
  writeFileSync(
207
209
  join(baseDir, "docs/COMMITS/INDEX.md"),
208
210
  "# Índice de Commits\n\n| Fecha | Versión | Descripción |\n|---|---|---|\n",
209
211
  "utf-8"
210
- );
211
- console.log(chalk.green(" ✅ docs/COMMITS/INDEX.md"));
212
+ )
213
+ console.log(chalk.green(" ✅ docs/COMMITS/INDEX.md"))
212
214
 
213
- console.log(chalk.cyan("\n📦 Estructura inicial creada exitosamente."));
214
- console.log(chalk.cyan(`👉 cd ${projectName}`));
215
- console.log(chalk.cyan(`👉 npx openPrompt-Lang context`));
216
- console.log(chalk.cyan(`👉 npm run dev:start # Iniciar servidor de desarrollo`));
217
- console.log(chalk.cyan(`👉 npm run validate:all # Pipeline completo de validación`));
218
- console.log(chalk.cyan(`👉 Revisa docs/FRAMEWORK.md para las convenciones\n`));
215
+ console.log(chalk.cyan("\n📦 Estructura inicial creada exitosamente."))
216
+ console.log(chalk.cyan(`👉 cd ${projectName}`))
217
+ console.log(chalk.cyan(`👉 npx openPrompt-Lang context`))
218
+ console.log(chalk.cyan(`👉 npm run dev:start # Iniciar servidor de desarrollo`))
219
+ console.log(chalk.cyan(`👉 npm run validate:all # Pipeline completo de validación`))
220
+ console.log(chalk.cyan(`👉 Revisa docs/FRAMEWORK.md para las convenciones\n`))
219
221
 
220
- return baseDir;
222
+ return baseDir
221
223
  }
222
224
 
223
225
  async function initExisting() {
224
- const cwd = process.cwd();
226
+ const cwd = process.cwd()
225
227
  const projectName = existsSync(join(cwd, "package.json"))
226
228
  ? JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8")).name || "mi-proyecto"
227
- : "mi-proyecto";
229
+ : "mi-proyecto"
228
230
 
229
- console.log(chalk.cyan(`\n🔧 Configurando openPrompt-Lang en proyecto existente: ${projectName}\n`));
231
+ console.log(
232
+ chalk.cyan(`\n🔧 Configurando openPrompt-Lang en proyecto existente: ${projectName}\n`)
233
+ )
230
234
 
231
235
  // Detectar stack
232
- const stack = detectStack(cwd);
233
- const detected = Object.entries(stack).filter(([, v]) => v).map(([k]) => k);
234
- console.log(chalk.blue("🔍 Stack detectado:") + (detected.length ? detected.join(", ") : "ninguno detectado"));
235
-
236
- const baseExtensions = [];
237
- if (stack.ionic) baseExtensions.push("ionic");
238
- if (stack.tauri) baseExtensions.push("tauri");
239
- if (stack.supabase) baseExtensions.push("supabase");
236
+ const stack = detectStack(cwd)
237
+ const detected = Object.entries(stack)
238
+ .filter(([, v]) => v)
239
+ .map(([k]) => k)
240
+ console.log(
241
+ chalk.blue("🔍 Stack detectado:") +
242
+ (detected.length ? detected.join(", ") : "ninguno detectado")
243
+ )
244
+
245
+ const baseExtensions = []
246
+ if (stack.ionic) baseExtensions.push("ionic")
247
+ if (stack.tauri) baseExtensions.push("tauri")
248
+ if (stack.supabase) baseExtensions.push("supabase")
240
249
 
241
250
  // Crear prompt-lang.json
242
251
  const config = {
243
252
  name: projectName,
244
253
  version: "0.1.0",
245
254
  stack: {
246
- base: detected.filter(t => ["react", "typescript", "vite", "tailwind"].includes(t)),
255
+ base: detected.filter((t) => ["react", "typescript", "vite", "tailwind"].includes(t)),
247
256
  extensions: baseExtensions,
248
257
  },
249
258
  profile: "senior",
@@ -258,13 +267,13 @@ async function initExisting() {
258
267
  },
259
268
  docs: { commits: false, logs: false, backlog: false },
260
269
  extractor: { ignore: [".env", "*.local", "dist", "node_modules"], output: "contexto.md" },
261
- };
270
+ }
262
271
 
263
272
  if (existsSync(join(cwd, "prompt-lang.json"))) {
264
- console.log(chalk.yellow(" ⚠️ prompt-lang.json ya existe. Saltando."));
273
+ console.log(chalk.yellow(" ⚠️ prompt-lang.json ya existe. Saltando."))
265
274
  } else {
266
- writeFileSync(join(cwd, "prompt-lang.json"), JSON.stringify(config, null, 2), "utf-8");
267
- console.log(chalk.green(" ✅ prompt-lang.json"));
275
+ writeFileSync(join(cwd, "prompt-lang.json"), JSON.stringify(config, null, 2), "utf-8")
276
+ console.log(chalk.green(" ✅ prompt-lang.json"))
268
277
  }
269
278
 
270
279
  // Crear AGENTS.md
@@ -296,78 +305,173 @@ async function initExisting() {
296
305
  "- Framework: openPrompt-Lang",
297
306
  "- Prompt library: docs/PROMPTS/INDEX.md (si aplica)",
298
307
  "",
299
- ];
308
+ ]
300
309
 
301
310
  if (existsSync(join(cwd, "AGENTS.md"))) {
302
- console.log(chalk.yellow(" ⚠️ AGENTS.md ya existe. Saltando."));
311
+ console.log(chalk.yellow(" ⚠️ AGENTS.md ya existe. Saltando."))
303
312
  } else {
304
- writeFileSync(join(cwd, "AGENTS.md"), agentsLines.join("\n"), "utf-8");
305
- console.log(chalk.green(" ✅ AGENTS.md"));
313
+ writeFileSync(join(cwd, "AGENTS.md"), agentsLines.join("\n"), "utf-8")
314
+ console.log(chalk.green(" ✅ AGENTS.md"))
306
315
  }
307
316
 
308
317
  // Preguntar: agregar scripts descriptivos al package.json
309
318
  if (existsSync(join(cwd, "package.json"))) {
310
- const { addScripts } = await import("inquirer").then(m =>
311
- m.default.prompt([{
319
+ const { addScripts } = await inquirer.prompt([
320
+ {
312
321
  type: "confirm",
313
322
  name: "addScripts",
314
- message: "¿Agregar scripts descriptivos (dev:start, lint:check, validate:all...) al package.json?",
323
+ message:
324
+ "¿Agregar scripts descriptivos (dev:start, lint:check, validate:all...) al package.json?",
315
325
  default: false,
316
- }])
317
- );
326
+ },
327
+ ])
318
328
 
319
329
  if (addScripts) {
320
- const pkgPath = join(cwd, "package.json");
321
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
322
- pkg.scripts = pkg.scripts || {};
323
- let added = 0;
330
+ const pkgPath = join(cwd, "package.json")
331
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"))
332
+ pkg.scripts = pkg.scripts || {}
333
+ let added = 0
324
334
  for (const [name, cmd] of Object.entries(DESCRIPTIVE_SCRIPTS)) {
325
335
  if (!pkg.scripts[name]) {
326
- pkg.scripts[name] = cmd;
327
- added++;
336
+ pkg.scripts[name] = cmd
337
+ added++
328
338
  }
329
339
  }
330
340
  if (added > 0) {
331
- writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
332
- console.log(chalk.green(` ✅ ${added} scripts agregados al package.json`));
341
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8")
342
+ console.log(chalk.green(` ✅ ${added} scripts agregados al package.json`))
333
343
  } else {
334
- console.log(chalk.yellow(" ⚠️ Todos los scripts descriptivos ya existen. Sin cambios."));
344
+ console.log(chalk.yellow(" ⚠️ Todos los scripts descriptivos ya existen. Sin cambios."))
335
345
  }
336
346
  }
337
347
  }
338
348
 
339
349
  // Preguntar: crear docs/
340
- const { createDocs } = await import("inquirer").then(m =>
341
- m.default.prompt([{
350
+ const { createDocs } = await inquirer.prompt([
351
+ {
342
352
  type: "confirm",
343
353
  name: "createDocs",
344
354
  message: "¿Crear docs/BACKLOG, docs/COMMITS y docs/LOGS?",
345
355
  default: false,
346
- }])
347
- );
356
+ },
357
+ ])
348
358
 
349
359
  if (createDocs) {
350
- const docDirs = ["docs/BACKLOG", "docs/COMMITS", "docs/LOGS/ERRORES", "docs/LOGS/ACTIVIDAD", "docs/PROMPTS/PLANTILLAS", "docs/PROMPTS/STACK"];
360
+ const docDirs = [
361
+ "docs/BACKLOG",
362
+ "docs/COMMITS",
363
+ "docs/LOGS/ERRORES",
364
+ "docs/LOGS/ACTIVIDAD",
365
+ "docs/PROMPTS/PLANTILLAS",
366
+ "docs/PROMPTS/STACK",
367
+ ]
351
368
  for (const dir of docDirs) {
352
- const fullPath = join(cwd, dir);
353
- mkdirSync(fullPath, { recursive: true });
354
- console.log(` 📁 ${dir}/`);
369
+ const fullPath = join(cwd, dir)
370
+ mkdirSync(fullPath, { recursive: true })
371
+ console.log(` 📁 ${dir}/`)
355
372
  }
356
373
 
357
- const backlogIndex = join(cwd, "docs/BACKLOG/PHASE-1-core.md");
374
+ const backlogIndex = join(cwd, "docs/BACKLOG/PHASE-1-core.md")
358
375
  if (!existsSync(backlogIndex)) {
359
- writeFileSync(backlogIndex, `# PHASE-1 Core — MVP Funcional\n\n> Prioridad: P0 (Crítico) | 50% del proyecto\n\n## Tareas\n\n### TASK-001: Primera tarea\n**Módulo:** \n**Estimación:** \n**Criterios de aceptación:**\n- [ ] \n`, "utf-8");
360
- console.log(chalk.green(" ✅ docs/BACKLOG/PHASE-1-core.md"));
376
+ writeFileSync(
377
+ backlogIndex,
378
+ `# PHASE-1 Core — MVP Funcional\n\n> Prioridad: P0 (Crítico) | 50% del proyecto\n\n## Tareas\n\n### TASK-001: Primera tarea\n**Módulo:** \n**Estimación:** \n**Criterios de aceptación:**\n- [ ] \n`,
379
+ "utf-8"
380
+ )
381
+ console.log(chalk.green(" ✅ docs/BACKLOG/PHASE-1-core.md"))
361
382
  }
362
383
 
363
- const commitsIndex = join(cwd, "docs/COMMITS/INDEX.md");
384
+ const commitsIndex = join(cwd, "docs/COMMITS/INDEX.md")
364
385
  if (!existsSync(commitsIndex)) {
365
- writeFileSync(commitsIndex, "# Índice de Commits\n\n| Fecha | Versión | Descripción |\n|---|---|---|\n", "utf-8");
366
- console.log(chalk.green(" ✅ docs/COMMITS/INDEX.md"));
386
+ writeFileSync(
387
+ commitsIndex,
388
+ "# Índice de Commits\n\n| Fecha | Versión | Descripción |\n|---|---|---|\n",
389
+ "utf-8"
390
+ )
391
+ console.log(chalk.green(" ✅ docs/COMMITS/INDEX.md"))
392
+ }
393
+ }
394
+
395
+ // Preguntar: configurar build plugins
396
+ const { setupBuild } = await inquirer.prompt([
397
+ {
398
+ type: "confirm",
399
+ name: "setupBuild",
400
+ message: "¿Configurar plugins de build para anotaciones como código? (Vite + TS)",
401
+ default: true,
402
+ },
403
+ ])
404
+
405
+ if (setupBuild) {
406
+ // Configurar Vite plugin
407
+ const viteConfig = ["vite.config.ts", "vite.config.js", "vite.config.mjs"].find((f) =>
408
+ existsSync(join(cwd, f))
409
+ )
410
+ if (viteConfig) {
411
+ const { addVite } = await inquirer.prompt([
412
+ {
413
+ type: "confirm",
414
+ name: "addVite",
415
+ message: `¿Agregar openPrompt-Lang plugin a ${viteConfig}? (elimina @tag() en build)`,
416
+ default: true,
417
+ },
418
+ ])
419
+ if (addVite) {
420
+ const vitePath = join(cwd, viteConfig)
421
+ const existing = readFileSync(vitePath, "utf-8")
422
+ const importLine = `import { openPromptAnnotations } from "openprompt-lang/vite-plugin";\n`
423
+ if (!existing.includes("openPromptAnnotations")) {
424
+ // Match plugins: [ with any whitespace/newlines, capture indentation
425
+ const indentMatch = existing.match(/^(\s*)plugins\s*:\s*\[/m)
426
+ const indent = indentMatch ? indentMatch[1] || " " : " "
427
+ const pluginLine = `${indent} openPromptAnnotations(),\n`
428
+ const updated = existing.replace(/plugins\s*:\s*\[/, `plugins: [\n${pluginLine}`)
429
+ // Only add import if not already present
430
+ const finalContent = existing.includes('from "openprompt-lang/vite-plugin"')
431
+ ? updated
432
+ : importLine + updated
433
+ writeFileSync(vitePath, finalContent, "utf-8")
434
+ console.log(chalk.green(` ✅ openPrompt plugin agregado a ${viteConfig}`))
435
+ } else {
436
+ console.log(chalk.yellow(` ⚠️ ${viteConfig} ya tiene openPrompt plugin`))
437
+ }
438
+ }
439
+ }
440
+
441
+ // Configurar TS Language Service plugin
442
+ const tsconfig = ["tsconfig.json", "tsconfig.app.json"].find((f) => existsSync(join(cwd, f)))
443
+ if (tsconfig) {
444
+ const { addTsPlugin } = await inquirer.prompt([
445
+ {
446
+ type: "confirm",
447
+ name: "addTsPlugin",
448
+ message: `¿Agregar openPrompt-Lang TS plugin a ${tsconfig}? (suprime errores @tag)`,
449
+ default: true,
450
+ },
451
+ ])
452
+ if (addTsPlugin) {
453
+ const tsPath = join(cwd, tsconfig)
454
+ const tsConfig = JSON.parse(readFileSync(tsPath, "utf-8"))
455
+ tsConfig.compilerOptions = tsConfig.compilerOptions || {}
456
+ tsConfig.compilerOptions.plugins = tsConfig.compilerOptions.plugins || []
457
+ if (!tsConfig.compilerOptions.plugins.some((p) => p.name?.includes("openprompt"))) {
458
+ tsConfig.compilerOptions.plugins.push({ name: "openprompt-lang/ts-plugin" })
459
+ writeFileSync(tsPath, JSON.stringify(tsConfig, null, 2) + "\n", "utf-8")
460
+ console.log(chalk.green(` ✅ openPrompt TS plugin agregado a ${tsconfig}`))
461
+ } else {
462
+ console.log(chalk.yellow(` ⚠️ ${tsconfig} ya tiene openPrompt TS plugin`))
463
+ }
464
+ }
465
+ }
466
+
467
+ if (!viteConfig && !tsconfig) {
468
+ console.log(
469
+ chalk.yellow(" ⚠️ No se encontró vite.config ni tsconfig. Omite los plugins de build.")
470
+ )
367
471
  }
368
472
  }
369
473
 
370
- console.log(chalk.cyan("\n✅ openPrompt-Lang configurado en proyecto existente."));
371
- console.log(chalk.cyan(`👉 openPrompt-Lang context --output contexto.md`));
372
- console.log(chalk.cyan(`👉 Empieza a anotar tu código con @kind, @contract, @limit...\n`));
474
+ console.log(chalk.cyan("\n✅ openPrompt-Lang configurado en proyecto existente."))
475
+ console.log(chalk.cyan(`👉 openPrompt-Lang context --output contexto.md`))
476
+ console.log(chalk.cyan(`👉 Empieza a anotar tu código con @kind, @contract, @limit...\n`))
373
477
  }