@luquimbo/bi-superpowers 3.1.1 → 4.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.
Files changed (186) hide show
  1. package/.claude-plugin/marketplace.json +5 -3
  2. package/.claude-plugin/plugin.json +28 -2
  3. package/.claude-plugin/skill-manifest.json +22 -6
  4. package/.plugin/plugin.json +1 -1
  5. package/AGENTS.md +52 -36
  6. package/CHANGELOG.md +295 -0
  7. package/README.md +75 -26
  8. package/bin/build-plugin.js +17 -10
  9. package/bin/cli.js +278 -322
  10. package/bin/commands/build-desktop.js +35 -16
  11. package/bin/commands/diff.js +31 -13
  12. package/bin/commands/install.js +93 -72
  13. package/bin/commands/lint.js +40 -26
  14. package/bin/commands/mcp-setup.js +3 -10
  15. package/bin/commands/update-check.js +389 -0
  16. package/bin/lib/agents.js +19 -0
  17. package/bin/lib/generators/claude-plugin.js +144 -6
  18. package/bin/lib/generators/shared.js +29 -33
  19. package/bin/lib/mcp-config.js +191 -16
  20. package/bin/lib/skills.js +115 -27
  21. package/bin/postinstall.js +4 -2
  22. package/bin/utils/mcp-detect.js +2 -2
  23. package/commands/bi-start.md +218 -0
  24. package/commands/pbi-connect.md +43 -65
  25. package/commands/project-kickoff.md +393 -673
  26. package/commands/report-design.md +403 -0
  27. package/desktop-extension/manifest.json +5 -12
  28. package/desktop-extension/server.js +34 -25
  29. package/package.json +6 -10
  30. package/skills/bi-start/SKILL.md +220 -0
  31. package/skills/bi-start/scripts/update-check.js +389 -0
  32. package/skills/pbi-connect/SKILL.md +45 -67
  33. package/skills/pbi-connect/scripts/update-check.js +389 -0
  34. package/skills/project-kickoff/SKILL.md +395 -675
  35. package/skills/project-kickoff/scripts/update-check.js +389 -0
  36. package/skills/report-design/SKILL.md +405 -0
  37. package/skills/report-design/references/cli-commands.md +184 -0
  38. package/skills/report-design/references/cli-setup.md +101 -0
  39. package/skills/report-design/references/close-write-open-pattern.md +80 -0
  40. package/skills/report-design/references/layouts/finance.md +65 -0
  41. package/skills/report-design/references/layouts/generic.md +46 -0
  42. package/skills/report-design/references/layouts/hr.md +48 -0
  43. package/skills/report-design/references/layouts/marketing.md +45 -0
  44. package/skills/report-design/references/layouts/operations.md +44 -0
  45. package/skills/report-design/references/layouts/sales.md +50 -0
  46. package/skills/report-design/references/native-visuals.md +341 -0
  47. package/skills/report-design/references/pbi-desktop-installation.md +87 -0
  48. package/skills/report-design/references/pbir-preview-activation.md +40 -0
  49. package/skills/report-design/references/slicer.md +89 -0
  50. package/skills/report-design/references/textbox.md +101 -0
  51. package/skills/report-design/references/themes/BISuperpowers.json +915 -0
  52. package/skills/report-design/references/troubleshooting.md +135 -0
  53. package/skills/report-design/references/visual-types.md +78 -0
  54. package/skills/report-design/scripts/apply-theme.js +243 -0
  55. package/skills/report-design/scripts/create-visual.js +878 -0
  56. package/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  57. package/skills/report-design/scripts/update-check.js +389 -0
  58. package/skills/report-design/scripts/validate-pbir.js +322 -0
  59. package/src/content/base.md +12 -68
  60. package/src/content/mcp-requirements.json +0 -25
  61. package/src/content/routing.md +19 -74
  62. package/src/content/skills/bi-start.md +191 -0
  63. package/src/content/skills/pbi-connect.md +22 -65
  64. package/src/content/skills/project-kickoff.md +372 -673
  65. package/src/content/skills/report-design/SKILL.md +376 -0
  66. package/src/content/skills/report-design/references/cli-commands.md +184 -0
  67. package/src/content/skills/report-design/references/cli-setup.md +101 -0
  68. package/src/content/skills/report-design/references/close-write-open-pattern.md +80 -0
  69. package/src/content/skills/report-design/references/layouts/finance.md +65 -0
  70. package/src/content/skills/report-design/references/layouts/generic.md +46 -0
  71. package/src/content/skills/report-design/references/layouts/hr.md +48 -0
  72. package/src/content/skills/report-design/references/layouts/marketing.md +45 -0
  73. package/src/content/skills/report-design/references/layouts/operations.md +44 -0
  74. package/src/content/skills/report-design/references/layouts/sales.md +50 -0
  75. package/src/content/skills/report-design/references/native-visuals.md +341 -0
  76. package/src/content/skills/report-design/references/pbi-desktop-installation.md +87 -0
  77. package/src/content/skills/report-design/references/pbir-preview-activation.md +40 -0
  78. package/src/content/skills/report-design/references/slicer.md +89 -0
  79. package/src/content/skills/report-design/references/textbox.md +101 -0
  80. package/src/content/skills/report-design/references/themes/BISuperpowers.json +915 -0
  81. package/src/content/skills/report-design/references/troubleshooting.md +135 -0
  82. package/src/content/skills/report-design/references/visual-types.md +78 -0
  83. package/src/content/skills/report-design/scripts/apply-theme.js +243 -0
  84. package/src/content/skills/report-design/scripts/create-visual.js +878 -0
  85. package/src/content/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
  86. package/src/content/skills/report-design/scripts/validate-pbir.js +322 -0
  87. package/bin/commands/add.js +0 -533
  88. package/bin/commands/add.test.js +0 -77
  89. package/bin/commands/changelog.js +0 -443
  90. package/bin/commands/install.test.js +0 -289
  91. package/bin/commands/lint.test.js +0 -103
  92. package/bin/commands/pull.js +0 -287
  93. package/bin/commands/pull.test.js +0 -36
  94. package/bin/commands/push.js +0 -231
  95. package/bin/commands/push.test.js +0 -14
  96. package/bin/commands/search.js +0 -344
  97. package/bin/commands/search.test.js +0 -115
  98. package/bin/commands/setup.js +0 -545
  99. package/bin/commands/setup.test.js +0 -46
  100. package/bin/commands/sync-profile.js +0 -405
  101. package/bin/commands/sync-profile.test.js +0 -14
  102. package/bin/commands/sync-source.js +0 -418
  103. package/bin/commands/sync-source.test.js +0 -14
  104. package/bin/lib/generators/claude-plugin.test.js +0 -111
  105. package/bin/lib/mcp-config.test.js +0 -310
  106. package/bin/lib/microsoft-mcp.test.js +0 -115
  107. package/bin/utils/errors.js +0 -159
  108. package/bin/utils/git.js +0 -298
  109. package/bin/utils/logger.js +0 -142
  110. package/bin/utils/mcp-detect.test.js +0 -81
  111. package/bin/utils/pbix.js +0 -305
  112. package/bin/utils/pbix.test.js +0 -37
  113. package/bin/utils/profiles.js +0 -312
  114. package/bin/utils/projects.js +0 -169
  115. package/bin/utils/readline.js +0 -206
  116. package/bin/utils/readline.test.js +0 -47
  117. package/bin/utils/tui.test.js +0 -127
  118. package/docs/openrouter-free-models.md +0 -92
  119. package/library/examples/README.md +0 -151
  120. package/library/examples/finance-reporting/README.md +0 -351
  121. package/library/examples/finance-reporting/data-model.md +0 -267
  122. package/library/examples/finance-reporting/measures.dax +0 -557
  123. package/library/examples/hr-analytics/README.md +0 -371
  124. package/library/examples/hr-analytics/data-model.md +0 -315
  125. package/library/examples/hr-analytics/measures.dax +0 -460
  126. package/library/examples/marketing-analytics/README.md +0 -37
  127. package/library/examples/marketing-analytics/data-model.md +0 -62
  128. package/library/examples/marketing-analytics/measures.dax +0 -110
  129. package/library/examples/retail-analytics/README.md +0 -439
  130. package/library/examples/retail-analytics/data-model.md +0 -288
  131. package/library/examples/retail-analytics/measures.dax +0 -481
  132. package/library/examples/supply-chain/README.md +0 -37
  133. package/library/examples/supply-chain/data-model.md +0 -69
  134. package/library/examples/supply-chain/measures.dax +0 -77
  135. package/library/examples/udf-library/README.md +0 -228
  136. package/library/examples/udf-library/functions.dax +0 -571
  137. package/library/snippets/dax/README.md +0 -292
  138. package/library/snippets/dax/business-domains.md +0 -576
  139. package/library/snippets/dax/calculate-patterns.md +0 -276
  140. package/library/snippets/dax/calculation-groups.md +0 -489
  141. package/library/snippets/dax/error-handling.md +0 -495
  142. package/library/snippets/dax/iterators-and-aggregations.md +0 -474
  143. package/library/snippets/dax/kpis-and-metrics.md +0 -293
  144. package/library/snippets/dax/rankings-and-topn.md +0 -235
  145. package/library/snippets/dax/security-patterns.md +0 -413
  146. package/library/snippets/dax/text-and-formatting.md +0 -316
  147. package/library/snippets/dax/time-intelligence.md +0 -196
  148. package/library/snippets/dax/user-defined-functions.md +0 -477
  149. package/library/snippets/dax/virtual-tables.md +0 -546
  150. package/library/snippets/excel-formulas/README.md +0 -84
  151. package/library/snippets/excel-formulas/aggregations.md +0 -330
  152. package/library/snippets/excel-formulas/dates-and-times.md +0 -361
  153. package/library/snippets/excel-formulas/dynamic-arrays.md +0 -314
  154. package/library/snippets/excel-formulas/lookups.md +0 -169
  155. package/library/snippets/excel-formulas/text-functions.md +0 -363
  156. package/library/snippets/governance/naming-conventions.md +0 -97
  157. package/library/snippets/governance/review-checklists.md +0 -107
  158. package/library/snippets/power-query/README.md +0 -389
  159. package/library/snippets/power-query/api-integration.md +0 -707
  160. package/library/snippets/power-query/connections.md +0 -434
  161. package/library/snippets/power-query/data-cleaning.md +0 -298
  162. package/library/snippets/power-query/error-handling.md +0 -526
  163. package/library/snippets/power-query/parameters.md +0 -350
  164. package/library/snippets/power-query/performance.md +0 -506
  165. package/library/snippets/power-query/transformations.md +0 -330
  166. package/library/snippets/report-design/accessibility.md +0 -78
  167. package/library/snippets/report-design/chart-selection.md +0 -54
  168. package/library/snippets/report-design/layout-patterns.md +0 -87
  169. package/library/templates/data-models/README.md +0 -93
  170. package/library/templates/data-models/finance-model.md +0 -627
  171. package/library/templates/data-models/retail-star-schema.md +0 -473
  172. package/library/templates/excel/README.md +0 -83
  173. package/library/templates/excel/budget-tracker.md +0 -432
  174. package/library/templates/excel/data-entry-form.md +0 -533
  175. package/library/templates/power-bi/README.md +0 -72
  176. package/library/templates/power-bi/finance-report.md +0 -449
  177. package/library/templates/power-bi/kpi-scorecard.md +0 -461
  178. package/library/templates/power-bi/sales-dashboard.md +0 -281
  179. package/library/themes/excel/README.md +0 -436
  180. package/library/themes/power-bi/README.md +0 -271
  181. package/library/themes/power-bi/accessible.json +0 -307
  182. package/library/themes/power-bi/bi-superpowers-default.json +0 -858
  183. package/library/themes/power-bi/corporate-blue.json +0 -291
  184. package/library/themes/power-bi/dark-mode.json +0 -291
  185. package/library/themes/power-bi/minimal.json +0 -292
  186. package/library/themes/power-bi/print-friendly.json +0 -309
@@ -1,533 +0,0 @@
1
- /**
2
- * Add Command - Add Project to Repository
3
- * =========================================
4
- *
5
- * Adds a Power BI or Excel project to the bi-repo.
6
- * Extracts versionable content (TMDL, queries) and creates project config.
7
- *
8
- * Usage:
9
- * super add "C:/path/to/file.pbix"
10
- * super add "C:/path/to/file.pbix" --profile finance
11
- * super add "C:/path/to/file.xlsx" --name budget-2026
12
- *
13
- * @module commands/add
14
- */
15
-
16
- const fs = require('fs');
17
- const path = require('path');
18
-
19
- const git = require('../utils/git');
20
- const profiles = require('../utils/profiles');
21
- const pbix = require('../utils/pbix');
22
- const rl = require('../utils/readline');
23
-
24
- // Using shared readline utilities
25
- const { createReadline, prompt } = rl;
26
-
27
- /**
28
- * Parse command line arguments
29
- * @param {string[]} args - CLI arguments
30
- * @returns {Object} Parsed options
31
- */
32
- function parseArgs(args) {
33
- const options = {
34
- filePath: null,
35
- name: null,
36
- profile: null,
37
- help: false,
38
- };
39
-
40
- for (let i = 0; i < args.length; i++) {
41
- const arg = args[i];
42
-
43
- if (arg === '--name' || arg === '-n') {
44
- options.name = args[++i];
45
- } else if (arg === '--profile' || arg === '-p') {
46
- options.profile = args[++i];
47
- } else if (arg === '--help' || arg === '-h') {
48
- options.help = true;
49
- } else if (!arg.startsWith('-') && !options.filePath) {
50
- options.filePath = arg;
51
- }
52
- }
53
-
54
- return options;
55
- }
56
-
57
- // Readline functions imported from ../utils/readline.js
58
-
59
- /**
60
- * Show help message
61
- */
62
- function showHelp() {
63
- console.log(`
64
- super add - Añadir un proyecto BI al repositorio
65
-
66
- Uso:
67
- super add <archivo> Añadir un proyecto
68
- super add <archivo> --profile <nombre> Añadir con perfil específico
69
- super add <archivo> --name <nombre> Especificar nombre del proyecto
70
-
71
- Argumentos:
72
- <archivo> Ruta al archivo .pbix, .pbip o .xlsx
73
-
74
- Opciones:
75
- --name, -n <nombre> Nombre personalizado del proyecto (slug)
76
- --profile, -p <nombre> Perfil a usar (default, finance, retail, etc.)
77
- --help, -h Mostrar esta ayuda
78
-
79
- Ejemplos:
80
- super add "C:/Users/Juan/Documents/Sales.pbix"
81
- super add "./Dashboard.pbix" --profile finance
82
- super add "Budget.xlsx" --name budget-2026 --profile finance
83
- `);
84
- }
85
-
86
- /**
87
- * Get or create project name
88
- */
89
- async function getProjectName(rl, fileInfo, customName) {
90
- if (customName) {
91
- return pbix.generateSlug(customName);
92
- }
93
-
94
- const suggested = pbix.generateSlug(fileInfo.name);
95
- console.log(`\nNombre detectado: ${fileInfo.name}`);
96
- const input = await prompt(rl, `Nombre del proyecto [${suggested}]: `);
97
-
98
- return input ? pbix.generateSlug(input) : suggested;
99
- }
100
-
101
- /**
102
- * Select profile for the project
103
- */
104
- async function selectProfile(rl, customProfile) {
105
- if (customProfile) {
106
- // Validate profile exists or create it
107
- if (!profiles.profileExists(customProfile)) {
108
- console.log(`\nPerfil "${customProfile}" no existe. Creándolo...`);
109
- profiles.createProfile(customProfile, { inheritsFrom: 'default' });
110
- }
111
- return customProfile;
112
- }
113
-
114
- const availableProfiles = profiles.listProfiles();
115
-
116
- console.log('\nPerfil a usar:');
117
- availableProfiles.forEach((p, i) => {
118
- console.log(` ${i + 1}. ${p}`);
119
- });
120
-
121
- const choice = await prompt(rl, `\nSelecciona (1-${availableProfiles.length}): `);
122
- const choiceNum = parseInt(choice, 10);
123
-
124
- if (choiceNum >= 1 && choiceNum <= availableProfiles.length) {
125
- return availableProfiles[choiceNum - 1];
126
- }
127
-
128
- return 'default';
129
- }
130
-
131
- /**
132
- * Create project directory in repo
133
- */
134
- function createProjectDirectory(repoPath, projectName) {
135
- const projectDir = path.join(repoPath, 'projects', projectName);
136
-
137
- if (fs.existsSync(projectDir)) {
138
- return { exists: true, path: projectDir };
139
- }
140
-
141
- fs.mkdirSync(projectDir, { recursive: true });
142
- fs.mkdirSync(path.join(projectDir, 'definition'), { recursive: true });
143
- fs.mkdirSync(path.join(projectDir, 'queries'), { recursive: true });
144
-
145
- return { exists: false, path: projectDir };
146
- }
147
-
148
- /**
149
- * Extract content based on file type
150
- */
151
- function extractContent(fileInfo, projectDir) {
152
- const result = {
153
- success: false,
154
- files: [],
155
- message: '',
156
- };
157
-
158
- if (fileInfo.type === 'power-bi-project') {
159
- // PBIP - extract TMDL directly
160
- const extraction = pbix.extractPbipToRepo(fileInfo.path, projectDir);
161
- if (extraction.success) {
162
- result.success = true;
163
- result.files = extraction.files;
164
- result.message = `Extraídos ${extraction.files.length} archivos TMDL`;
165
- } else {
166
- result.message = extraction.error;
167
- }
168
- } else if (fileInfo.type === 'power-bi') {
169
- // PBIX - binary file, cannot extract directly
170
- // We'll create a placeholder and instruct user to save as PBIP
171
- result.success = true;
172
- result.message = `
173
- NOTA: Los archivos .pbix son binarios y no se pueden versionar directamente.
174
-
175
- Para versionar tu modelo, tienes dos opciones:
176
-
177
- 1. RECOMENDADO: Guarda como proyecto PBIP
178
- - En Power BI Desktop: File → Save as → Power BI Project (.pbip)
179
- - Luego ejecuta: super add "ruta/al/proyecto.pbip"
180
-
181
- 2. Usar el formato actual:
182
- - El proyecto se añadirá con referencia al .pbix
183
- - Los cambios se detectarán por fecha de modificación
184
- - No podrás ver diferencias detalladas en Git`;
185
-
186
- // Create a note file
187
- const noteContent = `# ${fileInfo.name}
188
-
189
- Este proyecto está vinculado a un archivo .pbix binario.
190
-
191
- ## Archivo Original
192
- - Ruta: ${fileInfo.path}
193
- - Tipo: Power BI Desktop (.pbix)
194
-
195
- ## Para mejor versionado
196
-
197
- Considera guardar como Power BI Project (.pbip):
198
- 1. Abre el archivo en Power BI Desktop
199
- 2. File → Save as → Power BI Project (.pbip)
200
- 3. Ejecuta: super add "ruta/al/proyecto.pbip"
201
-
202
- Los archivos .pbip contienen TMDL (texto) que Git puede versionar correctamente.
203
- `;
204
-
205
- fs.writeFileSync(path.join(projectDir, 'README.md'), noteContent);
206
- result.files = ['README.md'];
207
- } else if (fileInfo.type === 'excel' || fileInfo.type === 'excel-macro') {
208
- // Excel - create documentation placeholder
209
- result.success = true;
210
-
211
- const workbookDir = path.join(projectDir, 'workbook');
212
- if (!fs.existsSync(workbookDir)) {
213
- fs.mkdirSync(workbookDir, { recursive: true });
214
- }
215
-
216
- const structureContent = `# ${fileInfo.name}
217
-
218
- ## Estructura del Workbook
219
-
220
- Documenta aquí la estructura de tu workbook:
221
-
222
- ### Hojas
223
- -
224
-
225
- ### Tablas
226
- -
227
-
228
- ### Rangos Nombrados
229
- -
230
-
231
- ### Conexiones de Datos
232
- -
233
- `;
234
-
235
- fs.writeFileSync(path.join(workbookDir, 'structure.md'), structureContent);
236
-
237
- const formulasContent = `# Fórmulas Importantes
238
-
239
- Documenta aquí las fórmulas clave de tu workbook:
240
-
241
- ## Cálculos Principales
242
-
243
- \`\`\`excel
244
- =EXAMPLE_FORMULA()
245
- \`\`\`
246
-
247
- ## Lookups
248
-
249
- ## Agregaciones
250
- `;
251
-
252
- fs.writeFileSync(path.join(workbookDir, 'formulas.md'), formulasContent);
253
-
254
- result.files = ['workbook/structure.md', 'workbook/formulas.md'];
255
- result.message = 'Creada estructura para documentar el workbook Excel';
256
- } else {
257
- result.message = 'Tipo de archivo no soportado';
258
- }
259
-
260
- return result;
261
- }
262
-
263
- /**
264
- * Update repo config with new project
265
- */
266
- function updateRepoConfig(repoPath, projectName, projectConfig) {
267
- const configPath = path.join(repoPath, '.bi-superpowers.json');
268
-
269
- let config = { version: '3.0', projects: [] };
270
- if (fs.existsSync(configPath)) {
271
- try {
272
- config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
273
- } catch (e) {
274
- // Use default
275
- }
276
- }
277
-
278
- // Add or update project
279
- const existingIndex = config.projects.findIndex((p) => p.name === projectName);
280
- if (existingIndex >= 0) {
281
- config.projects[existingIndex] = projectConfig;
282
- } else {
283
- config.projects.push(projectConfig);
284
- }
285
-
286
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
287
- }
288
-
289
- /**
290
- * Main add command handler
291
- */
292
- async function addCommand(args, _config) {
293
- const options = parseArgs(args);
294
-
295
- if (options.help) {
296
- showHelp();
297
- return;
298
- }
299
-
300
- // Check if repo exists
301
- const repoPath = profiles.getRepoPath();
302
- if (!repoPath || !fs.existsSync(repoPath)) {
303
- console.log(`
304
- No se encontró el repositorio de BI.
305
-
306
- Ejecuta primero:
307
- super setup
308
-
309
- Para crear tu repositorio de proyectos.
310
- `);
311
- process.exit(1);
312
- }
313
-
314
- // Check if file path provided
315
- if (!options.filePath) {
316
- console.log(`
317
- Uso: super add <archivo>
318
-
319
- Ejemplo:
320
- super add "C:/Users/Juan/Documents/Sales.pbix"
321
- super add ./Dashboard.pbip --profile finance
322
- `);
323
- process.exit(1);
324
- }
325
-
326
- // Resolve and validate file path
327
- const filePath = path.resolve(options.filePath);
328
-
329
- // Security: Validate path to prevent path traversal attacks
330
- // Ensure the resolved path is within expected locations (user's folders, not system paths)
331
- const normalizedPath = path.normalize(filePath);
332
- const systemPaths = [
333
- path.normalize('C:\\Windows'),
334
- path.normalize('C:\\Program Files'),
335
- path.normalize('C:\\Program Files (x86)'),
336
- '/etc',
337
- '/usr',
338
- '/bin',
339
- '/sbin',
340
- '/var',
341
- '/root',
342
- ];
343
-
344
- const isSystemPath = systemPaths.some((sysPath) =>
345
- normalizedPath.toLowerCase().startsWith(sysPath.toLowerCase())
346
- );
347
-
348
- if (isSystemPath) {
349
- console.log('\n✗ Access denied: Cannot add files from system directories');
350
- console.log(' Please use files from your user directories.');
351
- process.exit(1);
352
- }
353
-
354
- const fileInfo = pbix.detectFileType(filePath);
355
-
356
- if (!fileInfo.exists) {
357
- console.log(`\n✗ Archivo no encontrado: ${filePath}`);
358
- process.exit(1);
359
- }
360
-
361
- if (fileInfo.type === 'unknown') {
362
- console.log(`\n✗ Tipo de archivo no soportado: ${fileInfo.extension}`);
363
- console.log(' Formatos soportados: .pbix, .pbip, .xlsx, .xlsm');
364
- process.exit(1);
365
- }
366
-
367
- console.log(`
368
- ════════════════════════════════════════════════════════════════
369
- Añadir Proyecto
370
- ════════════════════════════════════════════════════════════════
371
-
372
- Archivo: ${fileInfo.name}${fileInfo.extension}
373
- Tipo: ${fileInfo.type}
374
- Ruta: ${filePath}
375
- `);
376
-
377
- const rl = createReadline();
378
-
379
- try {
380
- // Get project name
381
- const projectName = await getProjectName(rl, fileInfo, options.name);
382
-
383
- // Select profile
384
- const profile = await selectProfile(rl, options.profile);
385
-
386
- // Create project directory
387
- const projectDir = createProjectDirectory(repoPath, projectName);
388
-
389
- if (projectDir.exists) {
390
- const overwrite = await prompt(
391
- rl,
392
- `\nEl proyecto "${projectName}" ya existe. ¿Sobrescribir? (s/n): `
393
- );
394
- if (overwrite.toLowerCase() !== 's' && overwrite.toLowerCase() !== 'y') {
395
- console.log('\nCancelado.');
396
- return;
397
- }
398
- }
399
-
400
- console.log(`\nCreando proyecto: ${projectName}`);
401
- console.log(` Directorio: ${projectDir.path}`);
402
- console.log(` Perfil: ${profile}`);
403
-
404
- // Extract content
405
- const extraction = extractContent(fileInfo, projectDir.path);
406
-
407
- if (extraction.success) {
408
- console.log(`\n ✓ ${extraction.message}`);
409
-
410
- if (extraction.files.length > 0) {
411
- console.log(' Archivos:');
412
- extraction.files.slice(0, 5).forEach((f) => {
413
- console.log(` - ${f}`);
414
- });
415
- if (extraction.files.length > 5) {
416
- console.log(` ... y ${extraction.files.length - 5} más`);
417
- }
418
- }
419
- } else if (extraction.message) {
420
- console.log(extraction.message);
421
- }
422
-
423
- // Create project.json (legacy, for backward compatibility)
424
- const projectConfig = pbix.createProjectConfig({
425
- name: projectName,
426
- displayName: fileInfo.name,
427
- type: fileInfo.type,
428
- profile: profile,
429
- sourcePath: filePath,
430
- });
431
-
432
- fs.writeFileSync(
433
- path.join(projectDir.path, 'project.json'),
434
- JSON.stringify(projectConfig, null, 2)
435
- );
436
- console.log(' ✓ Creado: project.json');
437
-
438
- // Create bi-project.json (versioned project config - NEW in v2.4)
439
- const biProjectConfig = {
440
- version: '1.0',
441
- name: projectName,
442
- displayName: fileInfo.name,
443
- type: fileInfo.type,
444
- profile: profile,
445
- sourcePath: filePath,
446
- created: new Date().toISOString(),
447
- mcpServers: {
448
- 'powerbi-modeling-mcp': {
449
- enabled: true,
450
- launcher: 'official-microsoft',
451
- },
452
- 'powerbi-remote': {
453
- enabled: false,
454
- semanticModelId: null,
455
- },
456
- 'fabric-mcp-server': {
457
- enabled: true,
458
- mode: 'all',
459
- },
460
- },
461
- changelog: {
462
- enabled: true,
463
- path: 'CHANGELOG.md',
464
- includeInAgentContext: true,
465
- recentChangesCount: 5,
466
- },
467
- agentContext: {
468
- includeRecentChanges: true,
469
- customInstructions: null,
470
- },
471
- };
472
-
473
- fs.writeFileSync(
474
- path.join(projectDir.path, 'bi-project.json'),
475
- JSON.stringify(biProjectConfig, null, 2)
476
- );
477
- console.log(' ✓ Creado: bi-project.json (configuración versionada)');
478
-
479
- // Create initial CHANGELOG.md
480
- const changelogContent = `# Changelog - ${fileInfo.name}
481
-
482
- All notable changes to this project will be documented in this file.
483
-
484
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
485
-
486
- ## [Unreleased]
487
-
488
- ### Added
489
- - Initial project setup with BI Agent Superpowers
490
-
491
- ---
492
- *Generated by [BI Agent Superpowers](https://github.com/luquimbo/bi-superpowers)*
493
- `;
494
-
495
- fs.writeFileSync(path.join(projectDir.path, 'CHANGELOG.md'), changelogContent);
496
- console.log(' ✓ Creado: CHANGELOG.md');
497
-
498
- // Update repo config
499
- updateRepoConfig(repoPath, projectName, {
500
- name: projectName,
501
- type: fileInfo.type,
502
- profile: profile,
503
- });
504
-
505
- // Git commit
506
- if (git.isGitRepo(repoPath)) {
507
- git.stageFiles(repoPath, '.');
508
- git.commit(repoPath, `Add project: ${projectName}`);
509
- console.log(` ✓ Commit: "Add project: ${projectName}"`);
510
- }
511
-
512
- console.log(`
513
- ════════════════════════════════════════════════════════════════
514
- ¡Proyecto añadido!
515
- ════════════════════════════════════════════════════════════════
516
-
517
- Los archivos originales permanecen en:
518
- ${filePath}
519
-
520
- Para traer cambios del original al repo:
521
- super pull ${projectName}
522
-
523
- Para ver el historial:
524
- cd "${repoPath}" && git log --oneline
525
-
526
- ════════════════════════════════════════════════════════════════
527
- `);
528
- } finally {
529
- rl.close();
530
- }
531
- }
532
-
533
- module.exports = addCommand;
@@ -1,77 +0,0 @@
1
- /**
2
- * Tests for Add Command
3
- * @module commands/add.test
4
- */
5
-
6
- const { test, describe } = require('node:test');
7
- const assert = require('node:assert');
8
- const path = require('path');
9
-
10
- describe('Add Command', () => {
11
- test('module exports a function', () => {
12
- const addCommand = require('./add');
13
- assert.strictEqual(typeof addCommand, 'function');
14
- });
15
- });
16
-
17
- describe('Add Command - File Type Detection', () => {
18
- test('detects .pbix files', () => {
19
- const pbix = require('../utils/pbix');
20
- const result = pbix.detectFileType('/path/to/file.pbix');
21
- assert.strictEqual(result.type, 'power-bi');
22
- assert.strictEqual(result.extension, '.pbix');
23
- });
24
-
25
- test('detects .pbip files', () => {
26
- const pbix = require('../utils/pbix');
27
- const result = pbix.detectFileType('/path/to/file.pbip');
28
- assert.strictEqual(result.type, 'power-bi-project');
29
- assert.strictEqual(result.extension, '.pbip');
30
- });
31
-
32
- test('detects .xlsx files', () => {
33
- const pbix = require('../utils/pbix');
34
- const result = pbix.detectFileType('/path/to/file.xlsx');
35
- assert.strictEqual(result.type, 'excel');
36
- assert.strictEqual(result.extension, '.xlsx');
37
- });
38
-
39
- test('detects .xlsm files', () => {
40
- const pbix = require('../utils/pbix');
41
- const result = pbix.detectFileType('/path/to/file.xlsm');
42
- assert.strictEqual(result.type, 'excel-macro');
43
- assert.strictEqual(result.extension, '.xlsm');
44
- });
45
-
46
- test('handles unknown file types', () => {
47
- const pbix = require('../utils/pbix');
48
- const result = pbix.detectFileType('/path/to/file.txt');
49
- assert.strictEqual(result.type, 'unknown');
50
- });
51
- });
52
-
53
- describe('Add Command - Slug Generation', () => {
54
- test('generates slug from name', () => {
55
- const pbix = require('../utils/pbix');
56
-
57
- assert.strictEqual(pbix.generateSlug('Sales Dashboard Q4'), 'sales-dashboard-q4');
58
- assert.strictEqual(pbix.generateSlug('My Report!'), 'my-report');
59
- assert.strictEqual(pbix.generateSlug('Budget 2026'), 'budget-2026');
60
- });
61
-
62
- test('handles special characters', () => {
63
- const pbix = require('../utils/pbix');
64
-
65
- assert.strictEqual(pbix.generateSlug('Report (Final)'), 'report-final');
66
- assert.strictEqual(pbix.generateSlug('Test & Demo'), 'test-demo');
67
- });
68
-
69
- test('limits slug length', () => {
70
- const pbix = require('../utils/pbix');
71
- const longName =
72
- 'This is a very long project name that should be truncated to a reasonable length';
73
- const slug = pbix.generateSlug(longName);
74
-
75
- assert.ok(slug.length <= 50);
76
- });
77
- });