@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.
Files changed (110) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.claude-plugin/skill-manifest.json +1 -1
  4. package/.plugin/plugin.json +1 -1
  5. package/README.md +2 -2
  6. package/bin/build-plugin.js +6 -6
  7. package/bin/cli.js +169 -310
  8. package/bin/commands/install.js +87 -70
  9. package/bin/commands/install.test.js +2 -2
  10. package/bin/lib/agents.js +21 -2
  11. package/bin/lib/mcp-config.js +27 -5
  12. package/bin/lib/mcp-config.test.js +1 -1
  13. package/desktop-extension/manifest.json +4 -11
  14. package/desktop-extension/server.js +34 -25
  15. package/package.json +3 -9
  16. package/skills/pbi-connect/SKILL.md +1 -1
  17. package/skills/project-kickoff/SKILL.md +1 -1
  18. package/bin/commands/add.js +0 -533
  19. package/bin/commands/add.test.js +0 -77
  20. package/bin/commands/changelog.js +0 -443
  21. package/bin/commands/pull.js +0 -287
  22. package/bin/commands/pull.test.js +0 -36
  23. package/bin/commands/push.js +0 -231
  24. package/bin/commands/push.test.js +0 -14
  25. package/bin/commands/search.js +0 -344
  26. package/bin/commands/search.test.js +0 -115
  27. package/bin/commands/setup.js +0 -545
  28. package/bin/commands/setup.test.js +0 -46
  29. package/bin/commands/sync-profile.js +0 -405
  30. package/bin/commands/sync-profile.test.js +0 -14
  31. package/bin/commands/sync-source.js +0 -418
  32. package/bin/commands/sync-source.test.js +0 -14
  33. package/bin/utils/errors.js +0 -159
  34. package/bin/utils/git.js +0 -298
  35. package/bin/utils/logger.js +0 -142
  36. package/bin/utils/pbix.js +0 -305
  37. package/bin/utils/pbix.test.js +0 -37
  38. package/bin/utils/profiles.js +0 -312
  39. package/bin/utils/projects.js +0 -169
  40. package/bin/utils/readline.js +0 -206
  41. package/bin/utils/readline.test.js +0 -47
  42. package/docs/openrouter-free-models.md +0 -92
  43. package/library/examples/README.md +0 -151
  44. package/library/examples/finance-reporting/README.md +0 -351
  45. package/library/examples/finance-reporting/data-model.md +0 -267
  46. package/library/examples/finance-reporting/measures.dax +0 -557
  47. package/library/examples/hr-analytics/README.md +0 -371
  48. package/library/examples/hr-analytics/data-model.md +0 -315
  49. package/library/examples/hr-analytics/measures.dax +0 -460
  50. package/library/examples/marketing-analytics/README.md +0 -37
  51. package/library/examples/marketing-analytics/data-model.md +0 -62
  52. package/library/examples/marketing-analytics/measures.dax +0 -110
  53. package/library/examples/retail-analytics/README.md +0 -439
  54. package/library/examples/retail-analytics/data-model.md +0 -288
  55. package/library/examples/retail-analytics/measures.dax +0 -481
  56. package/library/examples/supply-chain/README.md +0 -37
  57. package/library/examples/supply-chain/data-model.md +0 -69
  58. package/library/examples/supply-chain/measures.dax +0 -77
  59. package/library/examples/udf-library/README.md +0 -228
  60. package/library/examples/udf-library/functions.dax +0 -571
  61. package/library/snippets/dax/README.md +0 -292
  62. package/library/snippets/dax/business-domains.md +0 -576
  63. package/library/snippets/dax/calculate-patterns.md +0 -276
  64. package/library/snippets/dax/calculation-groups.md +0 -489
  65. package/library/snippets/dax/error-handling.md +0 -495
  66. package/library/snippets/dax/iterators-and-aggregations.md +0 -474
  67. package/library/snippets/dax/kpis-and-metrics.md +0 -293
  68. package/library/snippets/dax/rankings-and-topn.md +0 -235
  69. package/library/snippets/dax/security-patterns.md +0 -413
  70. package/library/snippets/dax/text-and-formatting.md +0 -316
  71. package/library/snippets/dax/time-intelligence.md +0 -196
  72. package/library/snippets/dax/user-defined-functions.md +0 -477
  73. package/library/snippets/dax/virtual-tables.md +0 -546
  74. package/library/snippets/excel-formulas/README.md +0 -84
  75. package/library/snippets/excel-formulas/aggregations.md +0 -330
  76. package/library/snippets/excel-formulas/dates-and-times.md +0 -361
  77. package/library/snippets/excel-formulas/dynamic-arrays.md +0 -314
  78. package/library/snippets/excel-formulas/lookups.md +0 -169
  79. package/library/snippets/excel-formulas/text-functions.md +0 -363
  80. package/library/snippets/governance/naming-conventions.md +0 -97
  81. package/library/snippets/governance/review-checklists.md +0 -107
  82. package/library/snippets/power-query/README.md +0 -389
  83. package/library/snippets/power-query/api-integration.md +0 -707
  84. package/library/snippets/power-query/connections.md +0 -434
  85. package/library/snippets/power-query/data-cleaning.md +0 -298
  86. package/library/snippets/power-query/error-handling.md +0 -526
  87. package/library/snippets/power-query/parameters.md +0 -350
  88. package/library/snippets/power-query/performance.md +0 -506
  89. package/library/snippets/power-query/transformations.md +0 -330
  90. package/library/snippets/report-design/accessibility.md +0 -78
  91. package/library/snippets/report-design/chart-selection.md +0 -54
  92. package/library/snippets/report-design/layout-patterns.md +0 -87
  93. package/library/templates/data-models/README.md +0 -93
  94. package/library/templates/data-models/finance-model.md +0 -627
  95. package/library/templates/data-models/retail-star-schema.md +0 -473
  96. package/library/templates/excel/README.md +0 -83
  97. package/library/templates/excel/budget-tracker.md +0 -432
  98. package/library/templates/excel/data-entry-form.md +0 -533
  99. package/library/templates/power-bi/README.md +0 -72
  100. package/library/templates/power-bi/finance-report.md +0 -449
  101. package/library/templates/power-bi/kpi-scorecard.md +0 -461
  102. package/library/templates/power-bi/sales-dashboard.md +0 -281
  103. package/library/themes/excel/README.md +0 -436
  104. package/library/themes/power-bi/README.md +0 -271
  105. package/library/themes/power-bi/accessible.json +0 -307
  106. package/library/themes/power-bi/bi-superpowers-default.json +0 -858
  107. package/library/themes/power-bi/corporate-blue.json +0 -291
  108. package/library/themes/power-bi/dark-mode.json +0 -291
  109. package/library/themes/power-bi/minimal.json +0 -292
  110. 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,159 +0,0 @@
1
- /**
2
- * Error Handling Utilities
3
- * ========================
4
- *
5
- * Standardized error handling for the CLI.
6
- * Provides consistent error messages and exit codes.
7
- *
8
- * @module utils/errors
9
- */
10
-
11
- /**
12
- * Custom CLI Error class
13
- * Extends Error with exit code and optional suggestion
14
- */
15
- class CLIError extends Error {
16
- /**
17
- * Create a CLI error
18
- * @param {string} message - Error message
19
- * @param {number} code - Exit code (default: 1)
20
- * @param {string|null} suggestion - Optional suggestion for fixing the error
21
- */
22
- constructor(message, code = 1, suggestion = null) {
23
- super(message);
24
- this.name = 'CLIError';
25
- this.code = code;
26
- this.suggestion = suggestion;
27
- }
28
- }
29
-
30
- /**
31
- * Error codes for common scenarios
32
- */
33
- const ErrorCodes = {
34
- GENERAL: 1,
35
- INVALID_INPUT: 2,
36
- FILE_NOT_FOUND: 3,
37
- PERMISSION_DENIED: 4,
38
- NETWORK_ERROR: 5,
39
- CONFIG_ERROR: 6,
40
- GIT_ERROR: 7,
41
- VALIDATION_ERROR: 8,
42
- };
43
-
44
- /**
45
- * Handle an error with consistent formatting
46
- * @param {Error} error - The error to handle
47
- * @param {Object} options - Options for handling
48
- * @param {boolean} options.exit - Whether to exit the process (default: true)
49
- * @param {boolean} options.verbose - Show stack trace (default: false)
50
- */
51
- function handleError(error, options = {}) {
52
- const { exit = true, verbose = process.env.DEBUG === 'true' } = options;
53
-
54
- if (error instanceof CLIError) {
55
- console.error(`Error: ${error.message}`);
56
- if (error.suggestion) {
57
- console.error(`\nSuggestion: ${error.suggestion}`);
58
- }
59
- if (exit) {
60
- process.exit(error.code);
61
- }
62
- } else if (error instanceof Error) {
63
- console.error(`Error: ${error.message}`);
64
- if (verbose && error.stack) {
65
- console.error(`\nStack trace:\n${error.stack}`);
66
- }
67
- if (exit) {
68
- process.exit(ErrorCodes.GENERAL);
69
- }
70
- } else {
71
- console.error(`Error: ${String(error)}`);
72
- if (exit) {
73
- process.exit(ErrorCodes.GENERAL);
74
- }
75
- }
76
- }
77
-
78
- /**
79
- * Wrap an async function with error handling
80
- * @param {Function} fn - Async function to wrap
81
- * @param {Object} options - Error handling options
82
- * @returns {Function} Wrapped function
83
- */
84
- function withErrorHandling(fn, options = {}) {
85
- return async (...args) => {
86
- try {
87
- return await fn(...args);
88
- } catch (error) {
89
- handleError(error, options);
90
- }
91
- };
92
- }
93
-
94
- /**
95
- * Log a warning without exiting
96
- * @param {string} message - Warning message
97
- * @param {Object} context - Additional context (optional)
98
- */
99
- function logWarning(message, context = null) {
100
- console.warn(`Warning: ${message}`);
101
- if (context && process.env.DEBUG === 'true') {
102
- console.warn('Context:', context);
103
- }
104
- }
105
-
106
- /**
107
- * Create a CLIError for common scenarios
108
- */
109
- const createError = {
110
- fileNotFound: (path) =>
111
- new CLIError(
112
- `File not found: ${path}`,
113
- ErrorCodes.FILE_NOT_FOUND,
114
- 'Check that the file path is correct.'
115
- ),
116
-
117
- invalidInput: (message, suggestion = null) =>
118
- new CLIError(message, ErrorCodes.INVALID_INPUT, suggestion),
119
-
120
- configError: (message) =>
121
- new CLIError(
122
- message,
123
- ErrorCodes.CONFIG_ERROR,
124
- 'Run "bi-superpowers setup" to configure the repository.'
125
- ),
126
-
127
- gitError: (message) =>
128
- new CLIError(
129
- message,
130
- ErrorCodes.GIT_ERROR,
131
- 'Make sure Git is installed and you are in a Git repository.'
132
- ),
133
-
134
- networkError: (message) =>
135
- new CLIError(
136
- message,
137
- ErrorCodes.NETWORK_ERROR,
138
- 'Check your internet connection and try again.'
139
- ),
140
-
141
- permissionDenied: (path) =>
142
- new CLIError(
143
- `Permission denied: ${path}`,
144
- ErrorCodes.PERMISSION_DENIED,
145
- 'Check file permissions.'
146
- ),
147
-
148
- validationError: (message, suggestion = null) =>
149
- new CLIError(message, ErrorCodes.VALIDATION_ERROR, suggestion),
150
- };
151
-
152
- module.exports = {
153
- CLIError,
154
- ErrorCodes,
155
- handleError,
156
- withErrorHandling,
157
- logWarning,
158
- createError,
159
- };