@luquimbo/bi-superpowers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +8 -0
- package/.mcp.json +25 -0
- package/AGENTS.md +244 -0
- package/CHANGELOG.md +265 -0
- package/LICENSE +21 -0
- package/README.md +211 -0
- package/bin/build-plugin.js +30 -0
- package/bin/cli.js +1064 -0
- package/bin/commands/add.js +533 -0
- package/bin/commands/add.test.js +77 -0
- package/bin/commands/build-desktop.js +166 -0
- package/bin/commands/changelog.js +443 -0
- package/bin/commands/diff.js +325 -0
- package/bin/commands/lint.js +419 -0
- package/bin/commands/lint.test.js +103 -0
- package/bin/commands/mcp-setup.js +246 -0
- package/bin/commands/pull.js +287 -0
- package/bin/commands/pull.test.js +36 -0
- package/bin/commands/push.js +231 -0
- package/bin/commands/push.test.js +14 -0
- package/bin/commands/search.js +344 -0
- package/bin/commands/search.test.js +115 -0
- package/bin/commands/setup.js +545 -0
- package/bin/commands/setup.test.js +46 -0
- package/bin/commands/sync-profile.js +405 -0
- package/bin/commands/sync-profile.test.js +14 -0
- package/bin/commands/sync-source.js +418 -0
- package/bin/commands/sync-source.test.js +14 -0
- package/bin/commands/watch.js +206 -0
- package/bin/lib/generators/claude-plugin.js +266 -0
- package/bin/lib/generators/claude-plugin.test.js +110 -0
- package/bin/lib/generators/index.js +116 -0
- package/bin/lib/generators/shared.js +282 -0
- package/bin/lib/licensing/index.js +35 -0
- package/bin/lib/licensing/storage.js +364 -0
- package/bin/lib/licensing/storage.test.js +55 -0
- package/bin/lib/licensing/validator.js +213 -0
- package/bin/lib/licensing/validator.test.js +137 -0
- package/bin/lib/microsoft-mcp.js +176 -0
- package/bin/lib/microsoft-mcp.test.js +106 -0
- package/bin/lib/skills.js +84 -0
- package/bin/mcp/powerbi-modeling-launcher.js +38 -0
- package/bin/postinstall.js +44 -0
- package/bin/utils/errors.js +159 -0
- package/bin/utils/git.js +298 -0
- package/bin/utils/logger.js +142 -0
- package/bin/utils/mcp-detect.js +274 -0
- package/bin/utils/mcp-detect.test.js +105 -0
- package/bin/utils/pbix.js +305 -0
- package/bin/utils/pbix.test.js +37 -0
- package/bin/utils/profiles.js +312 -0
- package/bin/utils/projects.js +168 -0
- package/bin/utils/readline.js +206 -0
- package/bin/utils/readline.test.js +47 -0
- package/bin/utils/tui.js +314 -0
- package/bin/utils/tui.test.js +127 -0
- package/commands/contributions.md +265 -0
- package/commands/data-model-design.md +468 -0
- package/commands/dax-doctor.md +248 -0
- package/commands/fabric-scripts.md +452 -0
- package/commands/migration-assistant.md +290 -0
- package/commands/model-documenter.md +242 -0
- package/commands/pbi-connect.md +239 -0
- package/commands/project-kickoff.md +905 -0
- package/commands/report-layout.md +296 -0
- package/commands/rls-design.md +533 -0
- package/commands/theme-tweaker.md +624 -0
- package/config.example.json +23 -0
- package/config.json +23 -0
- package/desktop-extension/manifest.json +37 -0
- package/desktop-extension/package.json +10 -0
- package/desktop-extension/server.js +95 -0
- package/docs/openrouter-free-models.md +92 -0
- package/library/examples/README.md +151 -0
- package/library/examples/finance-reporting/README.md +351 -0
- package/library/examples/finance-reporting/data-model.md +267 -0
- package/library/examples/finance-reporting/measures.dax +557 -0
- package/library/examples/hr-analytics/README.md +371 -0
- package/library/examples/hr-analytics/data-model.md +315 -0
- package/library/examples/hr-analytics/measures.dax +460 -0
- package/library/examples/marketing-analytics/README.md +37 -0
- package/library/examples/marketing-analytics/data-model.md +62 -0
- package/library/examples/marketing-analytics/measures.dax +110 -0
- package/library/examples/retail-analytics/README.md +439 -0
- package/library/examples/retail-analytics/data-model.md +288 -0
- package/library/examples/retail-analytics/measures.dax +481 -0
- package/library/examples/supply-chain/README.md +37 -0
- package/library/examples/supply-chain/data-model.md +69 -0
- package/library/examples/supply-chain/measures.dax +77 -0
- package/library/examples/udf-library/README.md +228 -0
- package/library/examples/udf-library/functions.dax +571 -0
- package/library/snippets/dax/README.md +292 -0
- package/library/snippets/dax/business-domains.md +576 -0
- package/library/snippets/dax/calculate-patterns.md +276 -0
- package/library/snippets/dax/calculation-groups.md +489 -0
- package/library/snippets/dax/error-handling.md +495 -0
- package/library/snippets/dax/iterators-and-aggregations.md +474 -0
- package/library/snippets/dax/kpis-and-metrics.md +293 -0
- package/library/snippets/dax/rankings-and-topn.md +235 -0
- package/library/snippets/dax/security-patterns.md +413 -0
- package/library/snippets/dax/text-and-formatting.md +316 -0
- package/library/snippets/dax/time-intelligence.md +196 -0
- package/library/snippets/dax/user-defined-functions.md +477 -0
- package/library/snippets/dax/virtual-tables.md +546 -0
- package/library/snippets/excel-formulas/README.md +84 -0
- package/library/snippets/excel-formulas/aggregations.md +330 -0
- package/library/snippets/excel-formulas/dates-and-times.md +361 -0
- package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
- package/library/snippets/excel-formulas/lookups.md +169 -0
- package/library/snippets/excel-formulas/text-functions.md +363 -0
- package/library/snippets/governance/naming-conventions.md +97 -0
- package/library/snippets/governance/review-checklists.md +107 -0
- package/library/snippets/power-query/README.md +389 -0
- package/library/snippets/power-query/api-integration.md +707 -0
- package/library/snippets/power-query/connections.md +434 -0
- package/library/snippets/power-query/data-cleaning.md +298 -0
- package/library/snippets/power-query/error-handling.md +526 -0
- package/library/snippets/power-query/parameters.md +350 -0
- package/library/snippets/power-query/performance.md +506 -0
- package/library/snippets/power-query/transformations.md +330 -0
- package/library/snippets/report-design/accessibility.md +78 -0
- package/library/snippets/report-design/chart-selection.md +54 -0
- package/library/snippets/report-design/layout-patterns.md +87 -0
- package/library/templates/data-models/README.md +93 -0
- package/library/templates/data-models/finance-model.md +627 -0
- package/library/templates/data-models/retail-star-schema.md +473 -0
- package/library/templates/excel/README.md +83 -0
- package/library/templates/excel/budget-tracker.md +432 -0
- package/library/templates/excel/data-entry-form.md +533 -0
- package/library/templates/power-bi/README.md +72 -0
- package/library/templates/power-bi/finance-report.md +449 -0
- package/library/templates/power-bi/kpi-scorecard.md +461 -0
- package/library/templates/power-bi/sales-dashboard.md +281 -0
- package/library/themes/excel/README.md +436 -0
- package/library/themes/power-bi/README.md +271 -0
- package/library/themes/power-bi/accessible.json +307 -0
- package/library/themes/power-bi/bi-superpowers-default.json +858 -0
- package/library/themes/power-bi/corporate-blue.json +291 -0
- package/library/themes/power-bi/dark-mode.json +291 -0
- package/library/themes/power-bi/minimal.json +292 -0
- package/library/themes/power-bi/print-friendly.json +309 -0
- package/package.json +93 -0
- package/skills/contributions/SKILL.md +267 -0
- package/skills/data-model-design/SKILL.md +470 -0
- package/skills/data-modeling/SKILL.md +254 -0
- package/skills/data-quality/SKILL.md +664 -0
- package/skills/dax/SKILL.md +708 -0
- package/skills/dax-doctor/SKILL.md +250 -0
- package/skills/dax-udf/SKILL.md +489 -0
- package/skills/deployment/SKILL.md +320 -0
- package/skills/excel-formulas/SKILL.md +463 -0
- package/skills/fabric-scripts/SKILL.md +454 -0
- package/skills/fast-standard/SKILL.md +509 -0
- package/skills/governance/SKILL.md +205 -0
- package/skills/migration-assistant/SKILL.md +292 -0
- package/skills/model-documenter/SKILL.md +244 -0
- package/skills/pbi-connect/SKILL.md +241 -0
- package/skills/power-query/SKILL.md +406 -0
- package/skills/project-kickoff/SKILL.md +907 -0
- package/skills/query-performance/SKILL.md +480 -0
- package/skills/report-design/SKILL.md +207 -0
- package/skills/report-layout/SKILL.md +298 -0
- package/skills/rls-design/SKILL.md +535 -0
- package/skills/semantic-model/SKILL.md +237 -0
- package/skills/testing-validation/SKILL.md +643 -0
- package/skills/theme-tweaker/SKILL.md +626 -0
- package/src/content/base.md +237 -0
- package/src/content/mcp-requirements.json +69 -0
- package/src/content/routing.md +203 -0
- package/src/content/skills/contributions.md +259 -0
- package/src/content/skills/data-model-design.md +462 -0
- package/src/content/skills/data-modeling.md +246 -0
- package/src/content/skills/data-quality.md +656 -0
- package/src/content/skills/dax-doctor.md +242 -0
- package/src/content/skills/dax-udf.md +481 -0
- package/src/content/skills/dax.md +700 -0
- package/src/content/skills/deployment.md +312 -0
- package/src/content/skills/excel-formulas.md +455 -0
- package/src/content/skills/fabric-scripts.md +446 -0
- package/src/content/skills/fast-standard.md +501 -0
- package/src/content/skills/governance.md +197 -0
- package/src/content/skills/migration-assistant.md +284 -0
- package/src/content/skills/model-documenter.md +236 -0
- package/src/content/skills/pbi-connect.md +233 -0
- package/src/content/skills/power-query.md +398 -0
- package/src/content/skills/project-kickoff.md +899 -0
- package/src/content/skills/query-performance.md +472 -0
- package/src/content/skills/report-design.md +199 -0
- package/src/content/skills/report-layout.md +290 -0
- package/src/content/skills/rls-design.md +527 -0
- package/src/content/skills/semantic-model.md +229 -0
- package/src/content/skills/testing-validation.md +635 -0
- package/src/content/skills/theme-tweaker.md +618 -0
|
@@ -0,0 +1,545 @@
|
|
|
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;
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
});
|