@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,115 +0,0 @@
1
- /**
2
- * Unit tests for the search command (xray)
3
- *
4
- * Run with: npm test
5
- */
6
-
7
- const { test, describe } = require('node:test');
8
- const assert = require('node:assert');
9
-
10
- // Mock content for testing search functionality
11
- const mockContent = `# Time Intelligence Patterns
12
-
13
- ## Overview
14
- DAX time intelligence functions for YTD, MTD, QTD calculations.
15
-
16
- ## YTD Pattern
17
-
18
- \`\`\`dax
19
- Sales YTD = TOTALYTD([Total Sales], 'Date'[Date])
20
- \`\`\`
21
-
22
- ## Rolling Average
23
-
24
- \`\`\`dax
25
- Rolling 12M Average =
26
- AVERAGEX(
27
- DATESINPERIOD('Date'[Date], MAX('Date'[Date]), -12, MONTH),
28
- [Total Sales]
29
- )
30
- \`\`\`
31
- `;
32
-
33
- describe('Search Index Building', () => {
34
- test('should extract title from H1 heading', () => {
35
- const h1Match = mockContent.match(/^#\s+(.+)/m);
36
- assert.ok(h1Match, 'Should find H1 heading');
37
- assert.strictEqual(h1Match[1], 'Time Intelligence Patterns');
38
- });
39
-
40
- test('should extract tags from backtick code', () => {
41
- const tagMatches = mockContent.match(/`([^`]+)`/g);
42
- assert.ok(tagMatches, 'Should find backtick tags');
43
- assert.ok(tagMatches.length > 0, 'Should have at least one tag');
44
- });
45
-
46
- test('should find DAX code blocks', () => {
47
- const daxBlocks = mockContent.match(/```dax[\s\S]*?```/g);
48
- assert.ok(daxBlocks, 'Should find DAX code blocks');
49
- assert.strictEqual(daxBlocks.length, 2, 'Should have 2 DAX code blocks');
50
- });
51
- });
52
-
53
- describe('Search Filtering', () => {
54
- test('category filter should be case-insensitive', () => {
55
- const category = 'dax';
56
- const testCategories = ['DAX', 'dax', 'Dax'];
57
-
58
- testCategories.forEach((testCat) => {
59
- const matches = testCat.toLowerCase().includes(category.toLowerCase());
60
- assert.strictEqual(matches, true, `${testCat} should match ${category}`);
61
- });
62
- });
63
-
64
- test('tag filter should find partial matches', () => {
65
- const tags = ['ytd', 'rolling', 'average', 'time-intelligence'];
66
- const searchTag = 'roll';
67
-
68
- const found = tags.some((t) => t.toLowerCase().includes(searchTag.toLowerCase()));
69
- assert.strictEqual(found, true, 'Should find partial tag match');
70
- });
71
- });
72
-
73
- describe('Search Result Scoring', () => {
74
- test('perfect match should score higher than partial', () => {
75
- // Simulating Fuse.js scoring (lower is better, 0 is perfect)
76
- const perfectScore = 0;
77
- const partialScore = 0.3;
78
-
79
- assert.ok(perfectScore < partialScore, 'Perfect match should have lower score');
80
- });
81
-
82
- test('title match should have higher weight', () => {
83
- const titleWeight = 0.4;
84
- const contentWeight = 0.3;
85
- const categoryWeight = 0.2;
86
- const tagsWeight = 0.1;
87
-
88
- const totalWeight = titleWeight + contentWeight + categoryWeight + tagsWeight;
89
- // Use tolerance for floating point comparison
90
- assert.ok(Math.abs(totalWeight - 1.0) < 0.0001, 'Weights should sum to 1.0');
91
- assert.ok(titleWeight > contentWeight, 'Title should have highest weight');
92
- });
93
- });
94
-
95
- describe('Argument Parsing', () => {
96
- test('should parse query argument', () => {
97
- const args = ['YTD'];
98
- const query = args.find((arg) => !arg.startsWith('-'));
99
- assert.strictEqual(query, 'YTD');
100
- });
101
-
102
- test('should parse category flag', () => {
103
- const args = ['--category', 'dax', 'YTD'];
104
- const categoryIndex = args.indexOf('--category');
105
- const category = categoryIndex !== -1 ? args[categoryIndex + 1] : null;
106
- assert.strictEqual(category, 'dax');
107
- });
108
-
109
- test('should parse short category flag', () => {
110
- const args = ['-c', 'power-query', 'transform'];
111
- const categoryIndex = args.indexOf('-c');
112
- const category = categoryIndex !== -1 ? args[categoryIndex + 1] : null;
113
- assert.strictEqual(category, 'power-query');
114
- });
115
- });
@@ -1,545 +0,0 @@
1
- /**
2
- * Setup Command - Onboarding Wizard
3
- * ==================================
4
- *
5
- * Creates the bi-repo structure for multi-project BI version control.
6
- * This is the first command users run after installing BI Superpowers.
7
- *
8
- * Usage:
9
- * super setup Interactive wizard
10
- * super setup --path ~/bi-repo Specify location
11
- * super setup --skip-vscode Don't open VS Code
12
- *
13
- * @module commands/setup
14
- */
15
-
16
- const fs = require('fs');
17
- const path = require('path');
18
- const os = require('os');
19
- const { spawn } = require('child_process');
20
-
21
- const git = require('../utils/git');
22
- const profiles = require('../utils/profiles');
23
- const rl = require('../utils/readline');
24
- const { createMcpConfigForFormat } = require('../lib/microsoft-mcp');
25
-
26
- /**
27
- * Default repo name
28
- */
29
- const DEFAULT_REPO_NAME = 'bi-repo';
30
-
31
- /**
32
- * Parse command line arguments
33
- * @param {string[]} args - CLI arguments
34
- * @returns {Object} Parsed options
35
- */
36
- function parseArgs(args) {
37
- const options = {
38
- path: null,
39
- skipVscode: false,
40
- help: false,
41
- };
42
-
43
- for (let i = 0; i < args.length; i++) {
44
- const arg = args[i];
45
-
46
- if (arg === '--path' || arg === '-p') {
47
- options.path = args[++i];
48
- } else if (arg === '--skip-vscode') {
49
- options.skipVscode = true;
50
- } else if (arg === '--help' || arg === '-h') {
51
- options.help = true;
52
- }
53
- }
54
-
55
- return options;
56
- }
57
-
58
- // Using shared readline utilities from ../utils/readline.js
59
- const { createReadline, prompt } = rl;
60
-
61
- /**
62
- * Show the welcome banner
63
- */
64
- function showWelcome() {
65
- console.log(`
66
- ╔══════════════════════════════════════════════════════════════╗
67
- ║ BI Agent Superpowers - Setup Wizard ║
68
- ╠══════════════════════════════════════════════════════════════╣
69
- ║ ║
70
- ║ Vamos a crear tu repositorio de proyectos BI. ║
71
- ║ ║
72
- ║ Este repo te permite: ║
73
- ║ • Versionar todos tus proyectos con Git ║
74
- ║ • Revertir cambios si algo sale mal ║
75
- ║ • Mantener tus archivos originales seguros ║
76
- ║ • Organizar múltiples proyectos en un solo lugar ║
77
- ║ • Configurar MCPs compartidos para todo el equipo ║
78
- ║ ║
79
- ╚══════════════════════════════════════════════════════════════╝
80
- `);
81
- }
82
-
83
- /**
84
- * Ask user about MCP configuration for the workspace
85
- */
86
- async function configureMCPs(rl) {
87
- console.log('\n─────────────────────────────────────────────────────────────');
88
- console.log(' Configuración de MCPs (Model Context Protocol)');
89
- console.log('─────────────────────────────────────────────────────────────\n');
90
-
91
- console.log('Este repo se crea en modo plugin-first para Claude Code.');
92
- console.log('Se configurarán por defecto los MCPs oficiales de Microsoft:\n');
93
- console.log(' • powerbi-remote (HTTP)');
94
- console.log(' • fabric-mcp-server (npx @microsoft/fabric-mcp@latest)');
95
- console.log(' • powerbi-modeling-mcp (launcher local para Windows)\n');
96
- console.log('Nota: el Modeling MCP local sólo funciona en Windows.');
97
- console.log('En macOS/Linux podrás seguir usando powerbi-remote y Fabric MCP.\n');
98
-
99
- const answer = await prompt(rl, '¿Continuar con esta configuración recomendada? (S/n): ');
100
- const accepted = !answer || answer.toLowerCase() === 's' || answer.toLowerCase() === 'y';
101
-
102
- return {
103
- pluginFirst: accepted,
104
- servers: accepted ? ['powerbi-remote', 'fabric-mcp-server', 'powerbi-modeling-mcp'] : [],
105
- };
106
- }
107
-
108
- /**
109
- * Generate MCP configuration files for AI tools
110
- */
111
- function generateMcpConfigs(repoPath, _mcpConfig) {
112
- if (_mcpConfig && _mcpConfig.pluginFirst === false) {
113
- console.log(' • Omitido: archivos MCP (puedes ejecutar "bi-superpowers mcp-setup" más tarde)');
114
- return;
115
- }
116
-
117
- const packageDir = path.resolve(__dirname, '..', '..');
118
- const pluginMcp = createMcpConfigForFormat('plugin', {
119
- packageDir,
120
- });
121
- fs.writeFileSync(path.join(repoPath, '.mcp.json'), JSON.stringify(pluginMcp, null, 2));
122
- console.log(' ✓ Creado: .mcp.json (MCPs oficiales de Microsoft)');
123
-
124
- // Create .cursor directory and mcp.json
125
- const cursorDir = path.join(repoPath, '.cursor');
126
- if (!fs.existsSync(cursorDir)) {
127
- fs.mkdirSync(cursorDir, { recursive: true });
128
- }
129
-
130
- const cursorMcp = createMcpConfigForFormat('cursor', {
131
- packageDir,
132
- });
133
- fs.writeFileSync(path.join(cursorDir, 'mcp.json'), JSON.stringify(cursorMcp, null, 2));
134
- console.log(' ✓ Creado: .cursor/mcp.json (MCPs legacy)');
135
-
136
- // Create .vscode directory and settings.json
137
- const vscodeDir = path.join(repoPath, '.vscode');
138
- if (!fs.existsSync(vscodeDir)) {
139
- fs.mkdirSync(vscodeDir, { recursive: true });
140
- }
141
-
142
- const vscodeSettings = createMcpConfigForFormat('vscode', {
143
- packageDir,
144
- });
145
- fs.writeFileSync(
146
- path.join(vscodeDir, 'mcp-settings.json'),
147
- JSON.stringify(vscodeSettings, null, 2)
148
- );
149
- console.log(' ✓ Creado: .vscode/mcp-settings.json (MCPs legacy)');
150
- }
151
-
152
- /**
153
- * Show help message
154
- */
155
- function showHelp() {
156
- console.log(`
157
- super setup - Create your BI projects repository
158
-
159
- Usage:
160
- super setup Interactive wizard
161
- super setup --path ~/bi-repo Specify location
162
- super setup --skip-vscode Don't prompt to open VS Code
163
-
164
- Options:
165
- --path, -p <path> Path where to create the repo
166
- --skip-vscode Skip VS Code setup prompt
167
- --help, -h Show this help message
168
-
169
- Examples:
170
- super setup
171
- super setup --path "C:/Users/Juan/bi-repo"
172
- super setup --path ~/Documents/bi-repo --skip-vscode
173
- `);
174
- }
175
-
176
- /**
177
- * Get suggested repo locations
178
- */
179
- function getSuggestedLocations() {
180
- const home = os.homedir();
181
- const locations = [
182
- path.join(home, DEFAULT_REPO_NAME),
183
- path.join(home, 'Documents', DEFAULT_REPO_NAME),
184
- ];
185
-
186
- // Add Desktop on Windows
187
- if (process.platform === 'win32') {
188
- locations.push(path.join(home, 'Desktop', DEFAULT_REPO_NAME));
189
- }
190
-
191
- return locations;
192
- }
193
-
194
- /**
195
- * Ask user to select repo location
196
- */
197
- async function selectRepoLocation(rl) {
198
- const suggestions = getSuggestedLocations();
199
-
200
- console.log('\n¿Dónde quieres crear tu carpeta de repositorio?\n');
201
-
202
- suggestions.forEach((loc, i) => {
203
- console.log(` ${i + 1}. ${loc}`);
204
- });
205
- console.log(` ${suggestions.length + 1}. Otra ubicación (especificar)\n`);
206
-
207
- const choice = await prompt(rl, `Selecciona (1-${suggestions.length + 1}): `);
208
- const choiceNum = parseInt(choice, 10);
209
-
210
- if (choiceNum >= 1 && choiceNum <= suggestions.length) {
211
- return suggestions[choiceNum - 1];
212
- } else if (choiceNum === suggestions.length + 1) {
213
- const customPath = await prompt(rl, '\nEscribe la ruta completa: ');
214
- return customPath || suggestions[0];
215
- } else {
216
- console.log('\nOpción no válida. Usando ubicación recomendada.');
217
- return suggestions[0];
218
- }
219
- }
220
-
221
- /**
222
- * Create the repo directory structure
223
- */
224
- function createRepoStructure(repoPath, mcpConfig = {}) {
225
- console.log('\nCreando estructura...\n');
226
-
227
- // Create main directories
228
- const dirs = [
229
- repoPath,
230
- path.join(repoPath, 'projects'),
231
- path.join(repoPath, 'standards'),
232
- path.join(repoPath, 'snippets'),
233
- ];
234
-
235
- for (const dir of dirs) {
236
- if (!fs.existsSync(dir)) {
237
- fs.mkdirSync(dir, { recursive: true });
238
- console.log(` ✓ Creado: ${path.relative(repoPath, dir) || path.basename(repoPath)}/`);
239
- }
240
- }
241
-
242
- // Create .gitignore
243
- const gitignore = `# BI Agent Superpowers - Generated gitignore
244
-
245
- # Power BI temporary files
246
- *.pbix.tmp
247
- *.pbix.lock
248
-
249
- # Excel temporary files
250
- ~$*.xlsx
251
- ~$*.xlsm
252
-
253
- # OS files
254
- .DS_Store
255
- Thumbs.db
256
-
257
- # IDE
258
- .vscode/settings.json
259
- .idea/
260
-
261
- # Local user config (not versioned)
262
- .bi-superpowers.json
263
- `;
264
-
265
- fs.writeFileSync(path.join(repoPath, '.gitignore'), gitignore);
266
- console.log(' ✓ Creado: .gitignore');
267
-
268
- // Create bi-workspace.json (versioned workspace config)
269
- let workspaceMcpServers = {};
270
- if (mcpConfig.pluginFirst !== false) {
271
- workspaceMcpServers = {
272
- 'powerbi-modeling-mcp': {
273
- enabled: true,
274
- description: 'Microsoft Power BI Modeling MCP',
275
- },
276
- 'powerbi-remote': {
277
- enabled: true,
278
- description: 'Microsoft Power BI Remote MCP',
279
- },
280
- 'fabric-mcp-server': {
281
- enabled: true,
282
- mode: 'all',
283
- description: 'Microsoft Fabric MCP Server',
284
- },
285
- };
286
- }
287
-
288
- const workspaceConfig = {
289
- version: '3.1',
290
- created: new Date().toISOString(),
291
- projects: [],
292
- mcpServers: workspaceMcpServers,
293
- plugin: {
294
- name: 'bi-superpowers',
295
- pluginFirst: mcpConfig.pluginFirst !== false,
296
- },
297
- changelog: {
298
- enabled: true,
299
- autoGenerate: true,
300
- includeInAgentContext: true,
301
- recentChangesCount: 5,
302
- },
303
- };
304
-
305
- fs.writeFileSync(
306
- path.join(repoPath, 'bi-workspace.json'),
307
- JSON.stringify(workspaceConfig, null, 2)
308
- );
309
- console.log(' ✓ Creado: bi-workspace.json');
310
-
311
- // Create README.md
312
- const readme = `# BI Projects Repository
313
-
314
- Este repositorio contiene tus proyectos de Business Intelligence versionados con Git.
315
-
316
- ## Estructura
317
-
318
- \`\`\`
319
- bi-repo/
320
- ├── projects/ # Tus proyectos de BI
321
- │ └── {proyecto}/
322
- │ ├── project.json # Configuración y ruta al archivo original
323
- │ ├── definition/ # TMDL (modelo semántico)
324
- │ └── queries/ # Power Query (.pq)
325
- ├── standards/ # Tus standards personalizados
326
- └── snippets/ # Tus snippets personalizados
327
- \`\`\`
328
-
329
- ## Comandos Útiles
330
-
331
- \`\`\`bash
332
- # Añadir un proyecto
333
- super add "ruta/al/archivo.pbix"
334
-
335
- # Traer cambios del archivo original
336
- super pull
337
-
338
- # Ver historial de cambios
339
- git log --oneline
340
-
341
- # Revertir a una versión anterior
342
- git checkout HEAD~1
343
- super push
344
- \`\`\`
345
-
346
- ## Notas
347
-
348
- - Los archivos originales (.pbix, .xlsx) permanecen en su ubicación original
349
- - Solo los archivos de texto (TMDL, queries) se versionan aquí
350
- - Haz commits frecuentes para tener puntos de restauración
351
-
352
- ---
353
- Creado con [BI Agent Superpowers](https://github.com/luquimbo/bi-superpowers)
354
- `;
355
-
356
- fs.writeFileSync(path.join(repoPath, 'README.md'), readme);
357
- console.log(' ✓ Creado: README.md');
358
-
359
- return true;
360
- }
361
-
362
- /**
363
- * Initialize Git repository
364
- */
365
- function initializeGit(repoPath) {
366
- if (!git.isGitInstalled()) {
367
- console.log('\n⚠ Git no está instalado. Puedes instalarlo después.');
368
- console.log(' Descarga: https://git-scm.com/downloads');
369
- return false;
370
- }
371
-
372
- if (git.isGitRepo(repoPath)) {
373
- console.log(' ✓ Git ya inicializado');
374
- return true;
375
- }
376
-
377
- const success = git.initRepo(repoPath);
378
- if (success) {
379
- console.log(' ✓ Git inicializado');
380
-
381
- // Create initial commit
382
- git.stageFiles(repoPath, '.');
383
- git.commit(repoPath, 'Initial commit - BI Agent Superpowers repo');
384
- console.log(' ✓ Commit inicial creado');
385
-
386
- return true;
387
- } else {
388
- console.log(' ⚠ No se pudo inicializar Git');
389
- return false;
390
- }
391
- }
392
-
393
- /**
394
- * Prompt to open VS Code
395
- */
396
- async function promptVSCode(rl, repoPath, skipVscode) {
397
- if (skipVscode) {
398
- return;
399
- }
400
-
401
- console.log(`
402
- Ahora vamos a configurar VS Code:
403
-
404
- 1. Abre VS Code
405
- 2. File → Add Folder to Workspace
406
- 3. Selecciona: ${repoPath}
407
- `);
408
-
409
- const openNow = await prompt(rl, '¿Quieres que abra VS Code automáticamente? (s/n): ');
410
-
411
- if (openNow.toLowerCase() === 's' || openNow.toLowerCase() === 'y') {
412
- try {
413
- const platform = process.platform;
414
-
415
- if (platform === 'darwin') {
416
- spawn('open', ['-a', 'Visual Studio Code', repoPath], { detached: true, stdio: 'ignore' });
417
- } else if (platform === 'win32') {
418
- spawn('code', [repoPath], { detached: true, stdio: 'ignore' });
419
- } else {
420
- spawn('code', [repoPath], { detached: true, stdio: 'ignore' });
421
- }
422
-
423
- console.log('\n ✓ VS Code abierto');
424
- } catch (e) {
425
- console.log('\n ⚠ No se pudo abrir VS Code automáticamente.');
426
- console.log(' Abre VS Code manualmente y añade la carpeta.');
427
- }
428
- }
429
- }
430
-
431
- /**
432
- * Show completion message
433
- */
434
- function showCompletion(repoPath) {
435
- console.log(`
436
- ════════════════════════════════════════════════════════════════
437
- ¡Tu repositorio está listo!
438
- ════════════════════════════════════════════════════════════════
439
-
440
- Ubicación: ${repoPath}
441
-
442
- Próximos pasos:
443
-
444
- 1. Añade tu primer proyecto:
445
- super add "ruta/a/tu/archivo.pbix"
446
-
447
- 2. Trabaja en tu proyecto normalmente
448
-
449
- 3. Trae los cambios al repo:
450
- super pull
451
-
452
- 4. Git guarda el historial automáticamente
453
-
454
- Comandos útiles:
455
- super add <archivo> Añadir un proyecto
456
- super pull Traer cambios del original
457
- super powers Ver skills disponibles
458
-
459
- ════════════════════════════════════════════════════════════════
460
- `);
461
- }
462
-
463
- /**
464
- * Main setup command handler
465
- */
466
- async function setupCommand(args, _config) {
467
- const options = parseArgs(args);
468
-
469
- if (options.help) {
470
- showHelp();
471
- return;
472
- }
473
-
474
- showWelcome();
475
-
476
- // Check if repo already exists
477
- const existingRepo = profiles.getRepoPath();
478
- if (existingRepo && fs.existsSync(existingRepo)) {
479
- console.log('Ya tienes un repositorio configurado en:');
480
- console.log(` ${existingRepo}\n`);
481
-
482
- const rl = createReadline();
483
- const proceed = await prompt(rl, '¿Quieres crear uno nuevo? (s/n): ');
484
-
485
- if (proceed.toLowerCase() !== 's' && proceed.toLowerCase() !== 'y') {
486
- console.log('\nUsando repositorio existente.');
487
- rl.close();
488
- return;
489
- }
490
- rl.close();
491
- }
492
-
493
- const rl = createReadline();
494
-
495
- try {
496
- // Step 1: Select location
497
- let repoPath;
498
- if (options.path) {
499
- repoPath = path.resolve(options.path);
500
- console.log(`\nUsando ubicación: ${repoPath}`);
501
- } else {
502
- repoPath = await selectRepoLocation(rl);
503
- }
504
-
505
- // Check if path already exists
506
- if (fs.existsSync(repoPath)) {
507
- const contents = fs.readdirSync(repoPath);
508
- if (contents.length > 0) {
509
- console.log(`\n⚠ La carpeta ya existe y no está vacía: ${repoPath}`);
510
- const overwrite = await prompt(rl, '¿Quieres continuar de todos modos? (s/n): ');
511
-
512
- if (overwrite.toLowerCase() !== 's' && overwrite.toLowerCase() !== 'y') {
513
- console.log('\nCancelado.');
514
- return;
515
- }
516
- }
517
- }
518
-
519
- // Step 2: Configure MCPs for the workspace
520
- const mcpConfig = await configureMCPs(rl);
521
-
522
- // Step 3: Create structure with MCP config
523
- createRepoStructure(repoPath, mcpConfig);
524
-
525
- // Step 4: Generate MCP config files for AI tools
526
- generateMcpConfigs(repoPath, mcpConfig);
527
-
528
- // Step 5: Initialize Git
529
- initializeGit(repoPath);
530
-
531
- // Step 4: Save repo path to global config
532
- profiles.setRepoPath(repoPath);
533
- console.log(' ✓ Configuración guardada');
534
-
535
- // Step 5: VS Code setup
536
- await promptVSCode(rl, repoPath, options.skipVscode);
537
-
538
- // Done!
539
- showCompletion(repoPath);
540
- } finally {
541
- rl.close();
542
- }
543
- }
544
-
545
- module.exports = setupCommand;
@@ -1,46 +0,0 @@
1
- /**
2
- * Tests for Setup Command
3
- * @module commands/setup.test
4
- */
5
-
6
- const { test, describe, beforeEach, afterEach, mock } = require('node:test');
7
- const assert = require('node:assert');
8
- const fs = require('fs');
9
- const path = require('path');
10
- const os = require('os');
11
-
12
- // We'll test the parseArgs function and basic structure validation
13
- // Full integration tests would require mocking readline and git
14
-
15
- describe('Setup Command', () => {
16
- test('module exports a function', () => {
17
- const setupCommand = require('./setup');
18
- assert.strictEqual(typeof setupCommand, 'function');
19
- });
20
-
21
- test('parseArgs handles --path option', () => {
22
- // Import the module to access internal functions through the export
23
- // Since parseArgs is not exported, we test through the main command
24
- // This is a placeholder for when we refactor to export parseArgs
25
- assert.ok(true, 'Placeholder test - parseArgs is internal');
26
- });
27
-
28
- test('parseArgs handles --skip-vscode flag', () => {
29
- assert.ok(true, 'Placeholder test - parseArgs is internal');
30
- });
31
-
32
- test('parseArgs handles --help flag', () => {
33
- assert.ok(true, 'Placeholder test - parseArgs is internal');
34
- });
35
- });
36
-
37
- describe('Setup Command - Directory Structure', () => {
38
- test('expected directories are defined', () => {
39
- // Verify the expected structure would be created
40
- const expectedDirs = ['projects', 'standards', 'snippets'];
41
- const expectedFiles = ['.gitignore', '.bi-superpowers.json', 'README.md'];
42
-
43
- assert.ok(expectedDirs.length === 3);
44
- assert.ok(expectedFiles.length === 3);
45
- });
46
- });