@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,418 +0,0 @@
1
- /**
2
- * Sync Source Command - Bidirectional Synchronization
3
- * =====================================================
4
- *
5
- * Detects which is newer (repo or original file) and syncs accordingly.
6
- * Combines pull and push logic with automatic conflict detection.
7
- *
8
- * Usage:
9
- * super sync Sync current project
10
- * super sync <project-name> Sync specific project
11
- * super sync --all Sync all projects
12
- *
13
- * @module commands/sync-source
14
- */
15
-
16
- const fs = require('fs');
17
- const path = require('path');
18
-
19
- const profiles = require('../utils/profiles');
20
- const pbix = require('../utils/pbix');
21
- const git = require('../utils/git');
22
- const rl = require('../utils/readline');
23
- const { getAllProjects, getProject, detectCurrentProject } = require('../utils/projects');
24
-
25
- // Using shared readline utilities
26
- const { createReadline } = rl;
27
-
28
- /**
29
- * Parse command line arguments
30
- * @param {string[]} args - CLI arguments
31
- * @returns {Object} Parsed options
32
- */
33
- function parseArgs(args) {
34
- const options = {
35
- projectName: null,
36
- all: false,
37
- force: false,
38
- help: false,
39
- };
40
-
41
- for (let i = 0; i < args.length; i++) {
42
- const arg = args[i];
43
-
44
- if (arg === '--all' || arg === '-a') {
45
- options.all = true;
46
- } else if (arg === '--force' || arg === '-f') {
47
- options.force = true;
48
- } else if (arg === '--help' || arg === '-h') {
49
- options.help = true;
50
- } else if (!arg.startsWith('-') && !options.projectName) {
51
- options.projectName = arg;
52
- }
53
- }
54
-
55
- return options;
56
- }
57
-
58
- /**
59
- * Show help message
60
- */
61
- function showHelp() {
62
- console.log(`
63
- super sync - Sincronización bidireccional
64
-
65
- Detecta automáticamente qué es más nuevo (repo o archivo original)
66
- y sincroniza en la dirección correcta.
67
-
68
- Usage:
69
- super sync Sync proyecto actual
70
- super sync <proyecto> Sync proyecto específico
71
- super sync --all Sync todos los proyectos
72
-
73
- Options:
74
- --all, -a Sincronizar todos los proyectos
75
- --force, -f Forzar sin confirmación
76
- --help, -h Mostrar esta ayuda
77
-
78
- Ejemplos:
79
- super sync sales-q4
80
- super sync --all
81
- `);
82
- }
83
-
84
- // Note: getAllProjects, getProject, and detectCurrentProject are imported from ../utils/projects
85
-
86
- /**
87
- * Determine sync direction based on timestamps and hashes
88
- * @param {Object} project - Project config
89
- * @returns {Object} Sync info { direction, reason, sourceModified, repoModified }
90
- */
91
- function determineSyncDirection(project) {
92
- const result = {
93
- direction: 'none', // 'pull', 'push', 'conflict', 'none'
94
- reason: '',
95
- sourceModified: null,
96
- repoModified: null,
97
- hasChanges: false,
98
- };
99
-
100
- const sourcePath = project.source?.path;
101
- if (!sourcePath || !fs.existsSync(sourcePath)) {
102
- result.reason = 'Archivo original no encontrado';
103
- return result;
104
- }
105
-
106
- // Get source file modification time
107
- const sourceStats = fs.statSync(sourcePath);
108
- result.sourceModified = sourceStats.mtime;
109
-
110
- // Get repo definition modification time
111
- const definitionPath = path.join(project.projectPath, 'definition');
112
- if (fs.existsSync(definitionPath)) {
113
- const repoFiles = pbix.getAllFiles(definitionPath);
114
- if (repoFiles.length > 0) {
115
- // Find most recent repo file
116
- let latestRepoTime = new Date(0);
117
- for (const file of repoFiles) {
118
- const stats = fs.statSync(file);
119
- if (stats.mtime > latestRepoTime) {
120
- latestRepoTime = stats.mtime;
121
- }
122
- }
123
- result.repoModified = latestRepoTime;
124
- }
125
- }
126
-
127
- // Get last sync time
128
- const lastSync = project.source?.lastSync ? new Date(project.source.lastSync) : null;
129
-
130
- // Determine direction
131
- if (!result.repoModified) {
132
- // No repo content yet, need to pull
133
- result.direction = 'pull';
134
- result.reason = 'Repo vacío - necesita pull inicial';
135
- result.hasChanges = true;
136
- } else if (!lastSync) {
137
- // Never synced, check which is newer
138
- if (result.sourceModified > result.repoModified) {
139
- result.direction = 'pull';
140
- result.reason = 'Archivo original más nuevo (nunca sincronizado)';
141
- result.hasChanges = true;
142
- } else if (result.repoModified > result.sourceModified) {
143
- result.direction = 'push';
144
- result.reason = 'Repo más nuevo (nunca sincronizado)';
145
- result.hasChanges = true;
146
- }
147
- } else {
148
- // Check what changed since last sync
149
- const sourceChangedSinceSync = result.sourceModified > lastSync;
150
- const repoChangedSinceSync = result.repoModified > lastSync;
151
-
152
- if (sourceChangedSinceSync && repoChangedSinceSync) {
153
- result.direction = 'conflict';
154
- result.reason = 'Ambos modificados desde último sync';
155
- result.hasChanges = true;
156
- } else if (sourceChangedSinceSync) {
157
- result.direction = 'pull';
158
- result.reason = 'Archivo original modificado';
159
- result.hasChanges = true;
160
- } else if (repoChangedSinceSync) {
161
- result.direction = 'push';
162
- result.reason = 'Repo modificado';
163
- result.hasChanges = true;
164
- } else {
165
- result.direction = 'none';
166
- result.reason = 'Sin cambios desde último sync';
167
- result.hasChanges = false;
168
- }
169
- }
170
-
171
- return result;
172
- }
173
-
174
- /**
175
- * Execute pull for a project
176
- * @param {Object} project - Project config
177
- * @returns {Object} Result
178
- */
179
- function executePull(project) {
180
- const result = { success: false, message: '', filesChanged: 0 };
181
-
182
- if (project.type === 'power-bi-project') {
183
- const extractResult = pbix.extractPbipToRepo(project.source.path, project.projectPath);
184
-
185
- if (extractResult.success) {
186
- // Update project.json
187
- project.source.lastSync = new Date().toISOString();
188
- project.source.hash = pbix.getFileHash(project.source.path);
189
-
190
- const configPath = path.join(project.projectPath, 'project.json');
191
- fs.writeFileSync(configPath, JSON.stringify(project, null, 2));
192
-
193
- result.success = true;
194
- result.filesChanged = extractResult.files.length;
195
- result.message = `Pulled ${extractResult.files.length} files`;
196
- } else {
197
- result.message = extractResult.error;
198
- }
199
- } else {
200
- result.message = `Pull no soportado para tipo: ${project.type}`;
201
- }
202
-
203
- return result;
204
- }
205
-
206
- /**
207
- * Execute push for a project
208
- * @param {Object} project - Project config
209
- * @returns {Object} Result
210
- */
211
- function executePush(project) {
212
- const result = { success: false, message: '', filesChanged: 0 };
213
-
214
- if (project.type === 'power-bi-project') {
215
- const definitionPath = pbix.getPbipDefinitionPath(project.source.path);
216
- const repoDefinition = path.join(project.projectPath, 'definition');
217
-
218
- if (!definitionPath) {
219
- result.message = 'No se encontró carpeta definition en PBIP';
220
- return result;
221
- }
222
-
223
- if (!fs.existsSync(repoDefinition)) {
224
- result.message = 'No hay definition en el repo';
225
- return result;
226
- }
227
-
228
- try {
229
- const files = pbix.copyDirectoryRecursive(repoDefinition, definitionPath);
230
-
231
- // Update project.json
232
- project.source.lastSync = new Date().toISOString();
233
- const configPath = path.join(project.projectPath, 'project.json');
234
- fs.writeFileSync(configPath, JSON.stringify(project, null, 2));
235
-
236
- result.success = true;
237
- result.filesChanged = files.length;
238
- result.message = `Pushed ${files.length} files`;
239
- } catch (e) {
240
- result.message = e.message;
241
- }
242
- } else {
243
- result.message = `Push no soportado para tipo: ${project.type}`;
244
- }
245
-
246
- return result;
247
- }
248
-
249
- /**
250
- * Sync a single project
251
- * @param {Object} project - Project config
252
- * @param {Object} options - Sync options
253
- * @param {readline.Interface} rl - Readline interface for prompts
254
- * @returns {Promise<Object>} Sync result
255
- */
256
- async function syncProject(project, options, rl) {
257
- const syncInfo = determineSyncDirection(project);
258
-
259
- console.log(`\n ${project.name}`);
260
- console.log(` Tipo: ${project.type}`);
261
- console.log(` Original: ${project.source?.path || 'No configurado'}`);
262
- console.log(` Estado: ${syncInfo.reason}`);
263
-
264
- if (!syncInfo.hasChanges) {
265
- console.log(' → Sin cambios necesarios');
266
- return { synced: false, direction: 'none' };
267
- }
268
-
269
- if (syncInfo.direction === 'conflict') {
270
- console.log(' ⚠ CONFLICTO: Ambos han sido modificados');
271
-
272
- if (!options.force) {
273
- const answer = await new Promise((resolve) => {
274
- rl.question(' ¿Qué hacer? (pull/push/skip): ', resolve);
275
- });
276
-
277
- if (answer === 'pull') {
278
- syncInfo.direction = 'pull';
279
- } else if (answer === 'push') {
280
- syncInfo.direction = 'push';
281
- } else {
282
- console.log(' → Omitido');
283
- return { synced: false, direction: 'skip' };
284
- }
285
- } else {
286
- // Force mode defaults to pull (safer)
287
- syncInfo.direction = 'pull';
288
- console.log(' → Forzando pull (más seguro)');
289
- }
290
- }
291
-
292
- let result;
293
- if (syncInfo.direction === 'pull') {
294
- console.log(' → Ejecutando pull...');
295
- result = executePull(project);
296
- } else if (syncInfo.direction === 'push') {
297
- console.log(' → Ejecutando push...');
298
- result = executePush(project);
299
- }
300
-
301
- if (result.success) {
302
- console.log(` ✓ ${result.message}`);
303
- return { synced: true, direction: syncInfo.direction, filesChanged: result.filesChanged };
304
- } else {
305
- console.log(` ✗ ${result.message}`);
306
- return { synced: false, direction: syncInfo.direction, error: result.message };
307
- }
308
- }
309
-
310
- /**
311
- * Main sync command handler
312
- */
313
- async function syncSourceCommand(args, _config) {
314
- const options = parseArgs(args);
315
-
316
- if (options.help) {
317
- showHelp();
318
- return;
319
- }
320
-
321
- // Check if repo exists
322
- const repoPath = profiles.getRepoPath();
323
- if (!repoPath || !fs.existsSync(repoPath)) {
324
- console.log(`
325
- No se encontró el repositorio de BI.
326
-
327
- Ejecuta primero:
328
- super setup
329
- `);
330
- process.exit(1);
331
- }
332
-
333
- console.log(`
334
- ════════════════════════════════════════════════════════════════
335
- Sync - Sincronización Bidireccional
336
- ════════════════════════════════════════════════════════════════
337
-
338
- Repositorio: ${repoPath}
339
- `);
340
-
341
- // Get projects to sync
342
- let projects = [];
343
-
344
- if (options.all) {
345
- projects = getAllProjects(repoPath);
346
- if (projects.length === 0) {
347
- console.log('No hay proyectos en el repo.\n');
348
- console.log('Añade uno con: super add "ruta/archivo.pbix"');
349
- return;
350
- }
351
- console.log(`Sincronizando ${projects.length} proyecto(s)...`);
352
- } else if (options.projectName) {
353
- const project = getProject(repoPath, options.projectName);
354
- if (!project) {
355
- console.log(`✗ Proyecto no encontrado: ${options.projectName}`);
356
- console.log('\nProyectos disponibles:');
357
- getAllProjects(repoPath).forEach((p) => {
358
- console.log(` - ${p.name}`);
359
- });
360
- process.exit(1);
361
- }
362
- projects = [project];
363
- } else {
364
- const current = detectCurrentProject(repoPath);
365
- if (current) {
366
- projects = [current];
367
- } else {
368
- // Show all projects status
369
- projects = getAllProjects(repoPath);
370
- if (projects.length === 0) {
371
- console.log('No hay proyectos en el repo.\n');
372
- console.log('Añade uno con: super add "ruta/archivo.pbix"');
373
- return;
374
- }
375
- console.log('Estado de todos los proyectos:');
376
- }
377
- }
378
-
379
- // Create readline interface
380
- const rlInterface = createReadline();
381
-
382
- // Sync each project
383
- let syncedCount = 0;
384
- let totalFilesChanged = 0;
385
-
386
- for (const project of projects) {
387
- const result = await syncProject(project, options, rlInterface);
388
- if (result.synced) {
389
- syncedCount++;
390
- totalFilesChanged += result.filesChanged || 0;
391
- }
392
- }
393
-
394
- rlInterface.close();
395
-
396
- // Commit changes if any
397
- if (syncedCount > 0 && git.isGitRepo(repoPath)) {
398
- console.log('\nCommiteando cambios...');
399
- git.stageFiles(repoPath, '.');
400
- const projectNames = projects
401
- .filter((p) => p)
402
- .map((p) => p.name)
403
- .join(', ');
404
- git.commit(repoPath, `Sync: ${projectNames}`);
405
- console.log('✓ Cambios commiteados');
406
- }
407
-
408
- console.log(`
409
- ════════════════════════════════════════════════════════════════
410
- Resumen
411
- ════════════════════════════════════════════════════════════════
412
-
413
- Proyectos sincronizados: ${syncedCount}/${projects.length}
414
- Archivos cambiados: ${totalFilesChanged}
415
- `);
416
- }
417
-
418
- module.exports = syncSourceCommand;
@@ -1,14 +0,0 @@
1
- /**
2
- * Tests for Sync Source Command
3
- * @module commands/sync-source.test
4
- */
5
-
6
- const { test, describe } = require('node:test');
7
- const assert = require('node:assert');
8
-
9
- describe('Sync Source Command', () => {
10
- test('module exports a function', () => {
11
- const syncSourceCommand = require('./sync-source');
12
- assert.strictEqual(typeof syncSourceCommand, 'function');
13
- });
14
- });
@@ -1,111 +0,0 @@
1
- /**
2
- * Tests for the native Claude Code plugin generator.
3
- */
4
-
5
- const { test, describe } = require('node:test');
6
- const assert = require('node:assert');
7
- const fs = require('node:fs');
8
- const os = require('node:os');
9
- const path = require('node:path');
10
-
11
- const claudePlugin = require('./claude-plugin');
12
-
13
- function makeSkill(name, title) {
14
- return {
15
- name,
16
- path: `/virtual/${name}.md`,
17
- content: `# ${title}
18
-
19
- ## Trigger
20
- - "${name}"
21
-
22
- ## Identity
23
- You are the ${title} guide.
24
-
25
- ## MANDATORY RULES
26
- 1. Stay helpful.
27
-
28
- Reference: library/snippets/example.md
29
- `,
30
- };
31
- }
32
-
33
- describe('claude-plugin generator', () => {
34
- test('creates plugin manifest, mcp config, commands, and skills', async () => {
35
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bi-superpowers-plugin-'));
36
-
37
- try {
38
- const skills = [
39
- makeSkill('project-kickoff', 'Project Kickoff'),
40
- makeSkill('pbi-connect', 'PBI Connect'),
41
- ];
42
-
43
- await claudePlugin.generate(tempDir, skills, {
44
- packageDir: '/tmp/bi-superpowers',
45
- version: '9.9.9',
46
- usePluginRootLauncher: true,
47
- libraryPrefix: 'library',
48
- });
49
-
50
- const pluginManifestPath = path.join(tempDir, '.claude-plugin', 'plugin.json');
51
- const pluginMcpPath = path.join(tempDir, '.mcp.json');
52
- const commandPath = path.join(tempDir, 'commands', 'project-kickoff.md');
53
- const skillPath = path.join(tempDir, 'skills', 'pbi-connect', 'SKILL.md');
54
-
55
- assert.ok(fs.existsSync(pluginManifestPath));
56
- assert.ok(fs.existsSync(pluginMcpPath));
57
- assert.ok(fs.existsSync(commandPath));
58
- assert.ok(fs.existsSync(skillPath));
59
-
60
- const pluginManifest = JSON.parse(fs.readFileSync(pluginManifestPath, 'utf8'));
61
- const pluginMcp = JSON.parse(fs.readFileSync(pluginMcpPath, 'utf8'));
62
- const commandContent = fs.readFileSync(commandPath, 'utf8');
63
- const skillContent = fs.readFileSync(skillPath, 'utf8');
64
-
65
- assert.strictEqual(pluginManifest.name, 'bi-superpowers');
66
- assert.strictEqual(pluginManifest.version, '9.9.9');
67
-
68
- // Only 2 MCPs ship: local Power BI Modeling and Microsoft Learn
69
- assert.strictEqual(Object.keys(pluginMcp).length, 2);
70
- assert.ok(pluginMcp['powerbi-modeling-mcp']);
71
- assert.ok(pluginMcp['microsoft-learn']);
72
- assert.strictEqual(pluginMcp['powerbi-modeling-mcp'].command, 'node');
73
- assert.ok(
74
- pluginMcp['powerbi-modeling-mcp'].args[0].includes(
75
- '${CLAUDE_PLUGIN_ROOT}/bin/mcp/powerbi-modeling-launcher.js'
76
- )
77
- );
78
- assert.strictEqual(pluginMcp['microsoft-learn'].type, 'http');
79
- assert.strictEqual(pluginMcp['microsoft-learn'].url, 'https://learn.microsoft.com/api/mcp');
80
-
81
- assert.ok(commandContent.includes('Generated by BI Agent Superpowers'));
82
- assert.ok(skillContent.includes('name: "pbi-connect"'));
83
- assert.ok(skillContent.includes('version: "9.9.9"'));
84
- } finally {
85
- fs.rmSync(tempDir, { recursive: true, force: true });
86
- }
87
- });
88
-
89
- test('rewrites library references for generated project outputs', async () => {
90
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bi-superpowers-plugin-'));
91
-
92
- try {
93
- const skills = [makeSkill('pbi-connect', 'PBI Connect')];
94
-
95
- await claudePlugin.generate(tempDir, skills, {
96
- packageDir: '/tmp/bi-superpowers',
97
- version: '1.0.0',
98
- libraryPrefix: '.bi-superpowers/library',
99
- });
100
-
101
- const skillContent = fs.readFileSync(
102
- path.join(tempDir, 'skills', 'pbi-connect', 'SKILL.md'),
103
- 'utf8'
104
- );
105
-
106
- assert.ok(skillContent.includes('.bi-superpowers/library/snippets/example.md'));
107
- } finally {
108
- fs.rmSync(tempDir, { recursive: true, force: true });
109
- }
110
- });
111
- });