@luquimbo/bi-superpowers 3.1.0 → 3.2.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/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skill-manifest.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/README.md +2 -2
- package/bin/build-plugin.js +6 -6
- package/bin/cli.js +169 -310
- package/bin/commands/install.js +87 -70
- package/bin/commands/install.test.js +2 -2
- package/bin/lib/agents.js +21 -2
- package/bin/lib/mcp-config.js +27 -5
- package/bin/lib/mcp-config.test.js +1 -1
- package/desktop-extension/manifest.json +4 -11
- package/desktop-extension/server.js +34 -25
- package/package.json +3 -9
- package/skills/pbi-connect/SKILL.md +1 -1
- package/skills/project-kickoff/SKILL.md +1 -1
- package/bin/commands/add.js +0 -533
- package/bin/commands/add.test.js +0 -77
- package/bin/commands/changelog.js +0 -443
- package/bin/commands/pull.js +0 -287
- package/bin/commands/pull.test.js +0 -36
- package/bin/commands/push.js +0 -231
- package/bin/commands/push.test.js +0 -14
- package/bin/commands/search.js +0 -344
- package/bin/commands/search.test.js +0 -115
- package/bin/commands/setup.js +0 -545
- package/bin/commands/setup.test.js +0 -46
- package/bin/commands/sync-profile.js +0 -405
- package/bin/commands/sync-profile.test.js +0 -14
- package/bin/commands/sync-source.js +0 -418
- package/bin/commands/sync-source.test.js +0 -14
- package/bin/utils/errors.js +0 -159
- package/bin/utils/git.js +0 -298
- package/bin/utils/logger.js +0 -142
- package/bin/utils/pbix.js +0 -305
- package/bin/utils/pbix.test.js +0 -37
- package/bin/utils/profiles.js +0 -312
- package/bin/utils/projects.js +0 -169
- package/bin/utils/readline.js +0 -206
- package/bin/utils/readline.test.js +0 -47
- package/docs/openrouter-free-models.md +0 -92
- package/library/examples/README.md +0 -151
- package/library/examples/finance-reporting/README.md +0 -351
- package/library/examples/finance-reporting/data-model.md +0 -267
- package/library/examples/finance-reporting/measures.dax +0 -557
- package/library/examples/hr-analytics/README.md +0 -371
- package/library/examples/hr-analytics/data-model.md +0 -315
- package/library/examples/hr-analytics/measures.dax +0 -460
- package/library/examples/marketing-analytics/README.md +0 -37
- package/library/examples/marketing-analytics/data-model.md +0 -62
- package/library/examples/marketing-analytics/measures.dax +0 -110
- package/library/examples/retail-analytics/README.md +0 -439
- package/library/examples/retail-analytics/data-model.md +0 -288
- package/library/examples/retail-analytics/measures.dax +0 -481
- package/library/examples/supply-chain/README.md +0 -37
- package/library/examples/supply-chain/data-model.md +0 -69
- package/library/examples/supply-chain/measures.dax +0 -77
- package/library/examples/udf-library/README.md +0 -228
- package/library/examples/udf-library/functions.dax +0 -571
- package/library/snippets/dax/README.md +0 -292
- package/library/snippets/dax/business-domains.md +0 -576
- package/library/snippets/dax/calculate-patterns.md +0 -276
- package/library/snippets/dax/calculation-groups.md +0 -489
- package/library/snippets/dax/error-handling.md +0 -495
- package/library/snippets/dax/iterators-and-aggregations.md +0 -474
- package/library/snippets/dax/kpis-and-metrics.md +0 -293
- package/library/snippets/dax/rankings-and-topn.md +0 -235
- package/library/snippets/dax/security-patterns.md +0 -413
- package/library/snippets/dax/text-and-formatting.md +0 -316
- package/library/snippets/dax/time-intelligence.md +0 -196
- package/library/snippets/dax/user-defined-functions.md +0 -477
- package/library/snippets/dax/virtual-tables.md +0 -546
- package/library/snippets/excel-formulas/README.md +0 -84
- package/library/snippets/excel-formulas/aggregations.md +0 -330
- package/library/snippets/excel-formulas/dates-and-times.md +0 -361
- package/library/snippets/excel-formulas/dynamic-arrays.md +0 -314
- package/library/snippets/excel-formulas/lookups.md +0 -169
- package/library/snippets/excel-formulas/text-functions.md +0 -363
- package/library/snippets/governance/naming-conventions.md +0 -97
- package/library/snippets/governance/review-checklists.md +0 -107
- package/library/snippets/power-query/README.md +0 -389
- package/library/snippets/power-query/api-integration.md +0 -707
- package/library/snippets/power-query/connections.md +0 -434
- package/library/snippets/power-query/data-cleaning.md +0 -298
- package/library/snippets/power-query/error-handling.md +0 -526
- package/library/snippets/power-query/parameters.md +0 -350
- package/library/snippets/power-query/performance.md +0 -506
- package/library/snippets/power-query/transformations.md +0 -330
- package/library/snippets/report-design/accessibility.md +0 -78
- package/library/snippets/report-design/chart-selection.md +0 -54
- package/library/snippets/report-design/layout-patterns.md +0 -87
- package/library/templates/data-models/README.md +0 -93
- package/library/templates/data-models/finance-model.md +0 -627
- package/library/templates/data-models/retail-star-schema.md +0 -473
- package/library/templates/excel/README.md +0 -83
- package/library/templates/excel/budget-tracker.md +0 -432
- package/library/templates/excel/data-entry-form.md +0 -533
- package/library/templates/power-bi/README.md +0 -72
- package/library/templates/power-bi/finance-report.md +0 -449
- package/library/templates/power-bi/kpi-scorecard.md +0 -461
- package/library/templates/power-bi/sales-dashboard.md +0 -281
- package/library/themes/excel/README.md +0 -436
- package/library/themes/power-bi/README.md +0 -271
- package/library/themes/power-bi/accessible.json +0 -307
- package/library/themes/power-bi/bi-superpowers-default.json +0 -858
- package/library/themes/power-bi/corporate-blue.json +0 -291
- package/library/themes/power-bi/dark-mode.json +0 -291
- package/library/themes/power-bi/minimal.json +0 -292
- package/library/themes/power-bi/print-friendly.json +0 -309
package/bin/commands/add.test.js
DELETED
|
@@ -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
|
-
});
|
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Changelog Command - Generate changelog from Git history
|
|
3
|
-
* ========================================================
|
|
4
|
-
*
|
|
5
|
-
* Generates or updates CHANGELOG.md from Git commit history.
|
|
6
|
-
* Also updates the agent context file with recent changes.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* super changelog Generate changelog for current project
|
|
10
|
-
* super changelog --all Generate for all projects in bi-repo
|
|
11
|
-
* super changelog --since v1.0.0 Generate since specific tag/commit
|
|
12
|
-
*
|
|
13
|
-
* @module commands/changelog
|
|
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
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Parse command line arguments
|
|
24
|
-
* @param {string[]} args - CLI arguments
|
|
25
|
-
* @returns {Object} Parsed options
|
|
26
|
-
*/
|
|
27
|
-
function parseArgs(args) {
|
|
28
|
-
const options = {
|
|
29
|
-
all: false,
|
|
30
|
-
since: null,
|
|
31
|
-
project: null,
|
|
32
|
-
help: false,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < args.length; i++) {
|
|
36
|
-
const arg = args[i];
|
|
37
|
-
|
|
38
|
-
if (arg === '--all' || arg === '-a') {
|
|
39
|
-
options.all = true;
|
|
40
|
-
} else if (arg === '--since' || arg === '-s') {
|
|
41
|
-
options.since = args[++i];
|
|
42
|
-
} else if (arg === '--project' || arg === '-p') {
|
|
43
|
-
options.project = args[++i];
|
|
44
|
-
} else if (arg === '--help' || arg === '-h') {
|
|
45
|
-
options.help = true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return options;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Show help message
|
|
54
|
-
*/
|
|
55
|
-
function showHelp() {
|
|
56
|
-
console.log(`
|
|
57
|
-
super changelog - Generar changelog desde historial Git
|
|
58
|
-
|
|
59
|
-
Uso:
|
|
60
|
-
super changelog Generar changelog del proyecto actual
|
|
61
|
-
super changelog --all Generar para todos los proyectos
|
|
62
|
-
super changelog --since <ref> Generar desde tag/commit específico
|
|
63
|
-
super changelog --project <name> Generar para proyecto específico
|
|
64
|
-
|
|
65
|
-
Opciones:
|
|
66
|
-
--all, -a Procesar todos los proyectos del bi-repo
|
|
67
|
-
--since, -s <ref> Commit o tag desde donde generar (ej: v1.0.0, HEAD~10)
|
|
68
|
-
--project, -p <name> Nombre del proyecto específico
|
|
69
|
-
--help, -h Mostrar esta ayuda
|
|
70
|
-
|
|
71
|
-
Ejemplos:
|
|
72
|
-
super changelog
|
|
73
|
-
super changelog --since HEAD~20
|
|
74
|
-
super changelog --all
|
|
75
|
-
super changelog --project sales-dashboard
|
|
76
|
-
`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Validate git ref format to prevent command injection
|
|
81
|
-
* @param {string} ref - Git reference (tag, branch, commit hash)
|
|
82
|
-
* @returns {boolean} Whether the ref is valid
|
|
83
|
-
*/
|
|
84
|
-
function isValidGitRef(ref) {
|
|
85
|
-
// Allow alphanumeric, dots, dashes, underscores, slashes (for branches like feature/foo)
|
|
86
|
-
// Also allow ~ and ^ for relative refs like HEAD~10 or HEAD^2
|
|
87
|
-
const validRefPattern = /^[a-zA-Z0-9._\-/~^]+$/;
|
|
88
|
-
return validRefPattern.test(ref) && ref.length <= 256;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get commits from Git log
|
|
93
|
-
* @param {string} repoPath - Path to the repository
|
|
94
|
-
* @param {string} projectPath - Path to project subdirectory (optional)
|
|
95
|
-
* @param {string} since - Starting point for log (optional)
|
|
96
|
-
* @returns {Array} Array of commit objects
|
|
97
|
-
*/
|
|
98
|
-
function getCommits(repoPath, projectPath = null, since = null) {
|
|
99
|
-
const commits = [];
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
const logArgs = ['log', '--pretty=format:%H|%h|%ai|%s|%an', '-n', '100'];
|
|
103
|
-
|
|
104
|
-
if (since) {
|
|
105
|
-
if (!isValidGitRef(since)) {
|
|
106
|
-
console.error(`Error: Invalid git ref format: "${since}"`);
|
|
107
|
-
console.error(
|
|
108
|
-
'Git refs must contain only alphanumeric characters, dots, dashes, underscores, slashes, ~ or ^'
|
|
109
|
-
);
|
|
110
|
-
process.exit(1);
|
|
111
|
-
}
|
|
112
|
-
logArgs.push(`${since}..HEAD`);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (projectPath) {
|
|
116
|
-
logArgs.push('--', projectPath);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const result = git.execGitCommand(repoPath, logArgs);
|
|
120
|
-
|
|
121
|
-
if (result && result.trim()) {
|
|
122
|
-
const lines = result.trim().split('\n');
|
|
123
|
-
for (const line of lines) {
|
|
124
|
-
const [hash, shortHash, date, subject, author] = line.split('|');
|
|
125
|
-
commits.push({
|
|
126
|
-
hash,
|
|
127
|
-
shortHash,
|
|
128
|
-
date: new Date(date),
|
|
129
|
-
subject,
|
|
130
|
-
author,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
} catch (e) {
|
|
135
|
-
// Return empty array if git log fails
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return commits;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Categorize commit by conventional commit type
|
|
143
|
-
* @param {string} subject - Commit subject line
|
|
144
|
-
* @returns {string} Category name
|
|
145
|
-
*/
|
|
146
|
-
function categorizeCommit(subject) {
|
|
147
|
-
const lowerSubject = subject.toLowerCase();
|
|
148
|
-
|
|
149
|
-
if (lowerSubject.startsWith('feat') || lowerSubject.startsWith('add')) {
|
|
150
|
-
return 'Added';
|
|
151
|
-
} else if (lowerSubject.startsWith('fix')) {
|
|
152
|
-
return 'Fixed';
|
|
153
|
-
} else if (lowerSubject.startsWith('change') || lowerSubject.startsWith('update')) {
|
|
154
|
-
return 'Changed';
|
|
155
|
-
} else if (lowerSubject.startsWith('remove') || lowerSubject.startsWith('delete')) {
|
|
156
|
-
return 'Removed';
|
|
157
|
-
} else if (lowerSubject.startsWith('deprecate')) {
|
|
158
|
-
return 'Deprecated';
|
|
159
|
-
} else if (lowerSubject.startsWith('security')) {
|
|
160
|
-
return 'Security';
|
|
161
|
-
} else if (lowerSubject.startsWith('refactor')) {
|
|
162
|
-
return 'Changed';
|
|
163
|
-
} else if (lowerSubject.startsWith('docs')) {
|
|
164
|
-
return 'Documentation';
|
|
165
|
-
} else if (lowerSubject.startsWith('style') || lowerSubject.startsWith('format')) {
|
|
166
|
-
return 'Style';
|
|
167
|
-
} else if (lowerSubject.startsWith('test')) {
|
|
168
|
-
return 'Testing';
|
|
169
|
-
} else if (lowerSubject.startsWith('perf')) {
|
|
170
|
-
return 'Performance';
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return 'Changed';
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Generate changelog content from commits
|
|
178
|
-
* @param {Array} commits - Array of commit objects
|
|
179
|
-
* @param {string} projectName - Project name for header
|
|
180
|
-
* @returns {string} Markdown changelog content
|
|
181
|
-
*/
|
|
182
|
-
function generateChangelogContent(commits, projectName) {
|
|
183
|
-
const categories = {};
|
|
184
|
-
|
|
185
|
-
// Group commits by category
|
|
186
|
-
for (const commit of commits) {
|
|
187
|
-
const category = categorizeCommit(commit.subject);
|
|
188
|
-
if (!categories[category]) {
|
|
189
|
-
categories[category] = [];
|
|
190
|
-
}
|
|
191
|
-
categories[category].push(commit);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Build markdown content
|
|
195
|
-
let content = `# Changelog - ${projectName}
|
|
196
|
-
|
|
197
|
-
All notable changes to this project will be documented in this file.
|
|
198
|
-
|
|
199
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
200
|
-
|
|
201
|
-
## [Unreleased]
|
|
202
|
-
|
|
203
|
-
`;
|
|
204
|
-
|
|
205
|
-
// Add categories in preferred order
|
|
206
|
-
const categoryOrder = [
|
|
207
|
-
'Added',
|
|
208
|
-
'Changed',
|
|
209
|
-
'Fixed',
|
|
210
|
-
'Removed',
|
|
211
|
-
'Deprecated',
|
|
212
|
-
'Security',
|
|
213
|
-
'Performance',
|
|
214
|
-
'Documentation',
|
|
215
|
-
'Style',
|
|
216
|
-
'Testing',
|
|
217
|
-
];
|
|
218
|
-
|
|
219
|
-
for (const category of categoryOrder) {
|
|
220
|
-
if (categories[category] && categories[category].length > 0) {
|
|
221
|
-
content += `### ${category}\n`;
|
|
222
|
-
for (const commit of categories[category]) {
|
|
223
|
-
// Clean up commit subject (remove conventional commit prefix)
|
|
224
|
-
let subject = commit.subject
|
|
225
|
-
.replace(
|
|
226
|
-
/^(feat|fix|add|change|update|remove|delete|refactor|docs|style|test|perf|security)[\s:()[\]]*\s*/i,
|
|
227
|
-
''
|
|
228
|
-
)
|
|
229
|
-
.trim();
|
|
230
|
-
// Capitalize first letter
|
|
231
|
-
subject = subject.charAt(0).toUpperCase() + subject.slice(1);
|
|
232
|
-
content += `- ${subject} (${commit.shortHash})\n`;
|
|
233
|
-
}
|
|
234
|
-
content += '\n';
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
content += `---
|
|
239
|
-
*Generated by [BI Agent Superpowers](https://github.com/luquimbo/bi-superpowers) on ${new Date().toISOString().split('T')[0]}*
|
|
240
|
-
`;
|
|
241
|
-
|
|
242
|
-
return content;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Generate recent changes summary for agent context
|
|
247
|
-
* @param {Array} commits - Array of commit objects
|
|
248
|
-
* @param {number} count - Number of recent changes to include
|
|
249
|
-
* @returns {string} Markdown summary
|
|
250
|
-
*/
|
|
251
|
-
function generateRecentChangesSummary(commits, count = 5) {
|
|
252
|
-
const recentCommits = commits.slice(0, count);
|
|
253
|
-
|
|
254
|
-
if (recentCommits.length === 0) {
|
|
255
|
-
return '## Recent Changes\n\nNo recent changes recorded.\n';
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
let summary = '## Recent Changes\n\n';
|
|
259
|
-
|
|
260
|
-
for (const commit of recentCommits) {
|
|
261
|
-
const dateStr = commit.date.toISOString().split('T')[0];
|
|
262
|
-
summary += `- **${dateStr}**: ${commit.subject} (${commit.shortHash})\n`;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
summary += '\n';
|
|
266
|
-
return summary;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Update agent context file with recent changes
|
|
271
|
-
* @param {string} projectPath - Path to project directory
|
|
272
|
-
* @param {string} recentChanges - Recent changes markdown
|
|
273
|
-
*/
|
|
274
|
-
function updateAgentContext(projectPath, recentChanges) {
|
|
275
|
-
// Check for Claude Code CLAUDE.md
|
|
276
|
-
const claudeDir = path.join(projectPath, '.claude');
|
|
277
|
-
const claudeMdPath = path.join(claudeDir, 'CLAUDE.md');
|
|
278
|
-
|
|
279
|
-
if (fs.existsSync(claudeMdPath)) {
|
|
280
|
-
let content = fs.readFileSync(claudeMdPath, 'utf8');
|
|
281
|
-
|
|
282
|
-
// Replace or append recent changes section
|
|
283
|
-
const recentChangesRegex = /## Recent Changes[\s\S]*?(?=##|$)/;
|
|
284
|
-
|
|
285
|
-
if (recentChangesRegex.test(content)) {
|
|
286
|
-
content = content.replace(recentChangesRegex, recentChanges);
|
|
287
|
-
} else {
|
|
288
|
-
// Append at the end
|
|
289
|
-
content += '\n' + recentChanges;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
fs.writeFileSync(claudeMdPath, content);
|
|
293
|
-
console.log(' ✓ Actualizado: .claude/CLAUDE.md');
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Process a single project
|
|
299
|
-
* @param {string} repoPath - Path to bi-repo
|
|
300
|
-
* @param {string} projectName - Project name
|
|
301
|
-
* @param {Object} options - Command options
|
|
302
|
-
*/
|
|
303
|
-
function processProject(repoPath, projectName, options) {
|
|
304
|
-
const projectPath = path.join(repoPath, 'projects', projectName);
|
|
305
|
-
|
|
306
|
-
if (!fs.existsSync(projectPath)) {
|
|
307
|
-
console.log(` ⚠ Proyecto no encontrado: ${projectName}`);
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
console.log(`\nProcesando: ${projectName}`);
|
|
312
|
-
|
|
313
|
-
// Get commits for this project
|
|
314
|
-
const commits = getCommits(repoPath, path.join('projects', projectName), options.since);
|
|
315
|
-
|
|
316
|
-
if (commits.length === 0) {
|
|
317
|
-
console.log(' ℹ No se encontraron commits para este proyecto');
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
console.log(` ✓ Encontrados ${commits.length} commits`);
|
|
322
|
-
|
|
323
|
-
// Load bi-project.json to get display name and settings
|
|
324
|
-
const biProjectPath = path.join(projectPath, 'bi-project.json');
|
|
325
|
-
let displayName = projectName;
|
|
326
|
-
let changelogSettings = { enabled: true, recentChangesCount: 5 };
|
|
327
|
-
|
|
328
|
-
if (fs.existsSync(biProjectPath)) {
|
|
329
|
-
try {
|
|
330
|
-
const biProject = JSON.parse(fs.readFileSync(biProjectPath, 'utf8'));
|
|
331
|
-
displayName = biProject.displayName || projectName;
|
|
332
|
-
if (biProject.changelog) {
|
|
333
|
-
changelogSettings = { ...changelogSettings, ...biProject.changelog };
|
|
334
|
-
}
|
|
335
|
-
} catch (e) {
|
|
336
|
-
// Use defaults
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (!changelogSettings.enabled) {
|
|
341
|
-
console.log(' ℹ Changelog deshabilitado para este proyecto');
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Generate and write changelog
|
|
346
|
-
const changelogContent = generateChangelogContent(commits, displayName);
|
|
347
|
-
const changelogPath = path.join(projectPath, 'CHANGELOG.md');
|
|
348
|
-
fs.writeFileSync(changelogPath, changelogContent);
|
|
349
|
-
console.log(' ✓ Generado: CHANGELOG.md');
|
|
350
|
-
|
|
351
|
-
// Generate recent changes summary
|
|
352
|
-
const recentChanges = generateRecentChangesSummary(commits, changelogSettings.recentChangesCount);
|
|
353
|
-
|
|
354
|
-
// Update agent context if enabled
|
|
355
|
-
if (changelogSettings.includeInAgentContext !== false) {
|
|
356
|
-
updateAgentContext(projectPath, recentChanges);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Main changelog command handler
|
|
362
|
-
* @param {string[]} args - Command arguments
|
|
363
|
-
* @param {Object} _config - CLI configuration (unused)
|
|
364
|
-
*/
|
|
365
|
-
async function changelogCommand(args, _config) {
|
|
366
|
-
const options = parseArgs(args);
|
|
367
|
-
|
|
368
|
-
if (options.help) {
|
|
369
|
-
showHelp();
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Check if in bi-repo
|
|
374
|
-
const repoPath = profiles.getRepoPath();
|
|
375
|
-
if (!repoPath || !fs.existsSync(repoPath)) {
|
|
376
|
-
console.log(`
|
|
377
|
-
No se encontró el repositorio de BI.
|
|
378
|
-
|
|
379
|
-
Ejecuta primero:
|
|
380
|
-
super setup
|
|
381
|
-
|
|
382
|
-
Para crear tu repositorio de proyectos.
|
|
383
|
-
`);
|
|
384
|
-
process.exit(1);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
console.log(`
|
|
388
|
-
════════════════════════════════════════════════════════════════
|
|
389
|
-
BI Agent Superpowers - Changelog Generator
|
|
390
|
-
════════════════════════════════════════════════════════════════
|
|
391
|
-
`);
|
|
392
|
-
|
|
393
|
-
// Get list of projects
|
|
394
|
-
const projectsDir = path.join(repoPath, 'projects');
|
|
395
|
-
|
|
396
|
-
if (!fs.existsSync(projectsDir)) {
|
|
397
|
-
console.log('No hay proyectos en el repositorio.');
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const allProjects = fs
|
|
402
|
-
.readdirSync(projectsDir)
|
|
403
|
-
.filter((f) => fs.statSync(path.join(projectsDir, f)).isDirectory());
|
|
404
|
-
|
|
405
|
-
if (allProjects.length === 0) {
|
|
406
|
-
console.log('No hay proyectos en el repositorio.');
|
|
407
|
-
console.log('Usa "bi-superpowers add <archivo>" para añadir un proyecto.');
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Determine which projects to process
|
|
412
|
-
let projectsToProcess = [];
|
|
413
|
-
|
|
414
|
-
if (options.project) {
|
|
415
|
-
if (allProjects.includes(options.project)) {
|
|
416
|
-
projectsToProcess = [options.project];
|
|
417
|
-
} else {
|
|
418
|
-
console.log(`Proyecto "${options.project}" no encontrado.`);
|
|
419
|
-
console.log(`Proyectos disponibles: ${allProjects.join(', ')}`);
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
} else if (options.all) {
|
|
423
|
-
projectsToProcess = allProjects;
|
|
424
|
-
} else {
|
|
425
|
-
// Default to first project or prompt
|
|
426
|
-
projectsToProcess = allProjects.slice(0, 1);
|
|
427
|
-
console.log(`Procesando proyecto: ${projectsToProcess[0]}`);
|
|
428
|
-
console.log('(Usa --all para procesar todos los proyectos)');
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Process each project
|
|
432
|
-
for (const projectName of projectsToProcess) {
|
|
433
|
-
processProject(repoPath, projectName, options);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
console.log(`
|
|
437
|
-
════════════════════════════════════════════════════════════════
|
|
438
|
-
¡Changelog generado!
|
|
439
|
-
════════════════════════════════════════════════════════════════
|
|
440
|
-
`);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
module.exports = changelogCommand;
|