@hyperdrive.bot/gut 0.1.4 → 0.1.6

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 (87) hide show
  1. package/README.md +1 -779
  2. package/bin/run.js +5 -0
  3. package/package.json +10 -10
  4. package/bin/run +0 -5
  5. package/dist/base-command.d.ts +0 -21
  6. package/dist/base-command.js +0 -110
  7. package/dist/commands/add.d.ts +0 -13
  8. package/dist/commands/add.js +0 -73
  9. package/dist/commands/affected.d.ts +0 -23
  10. package/dist/commands/affected.js +0 -326
  11. package/dist/commands/audit.d.ts +0 -33
  12. package/dist/commands/audit.js +0 -593
  13. package/dist/commands/back.d.ts +0 -6
  14. package/dist/commands/back.js +0 -29
  15. package/dist/commands/commit.d.ts +0 -11
  16. package/dist/commands/commit.js +0 -113
  17. package/dist/commands/context.d.ts +0 -6
  18. package/dist/commands/context.js +0 -36
  19. package/dist/commands/contexts.d.ts +0 -7
  20. package/dist/commands/contexts.js +0 -92
  21. package/dist/commands/deps.d.ts +0 -10
  22. package/dist/commands/deps.js +0 -104
  23. package/dist/commands/entity/add.d.ts +0 -16
  24. package/dist/commands/entity/add.js +0 -105
  25. package/dist/commands/entity/clone-all.d.ts +0 -17
  26. package/dist/commands/entity/clone-all.js +0 -135
  27. package/dist/commands/entity/clone.d.ts +0 -15
  28. package/dist/commands/entity/clone.js +0 -109
  29. package/dist/commands/entity/list.d.ts +0 -11
  30. package/dist/commands/entity/list.js +0 -82
  31. package/dist/commands/entity/remove.d.ts +0 -12
  32. package/dist/commands/entity/remove.js +0 -58
  33. package/dist/commands/focus.d.ts +0 -19
  34. package/dist/commands/focus.js +0 -139
  35. package/dist/commands/graph.d.ts +0 -18
  36. package/dist/commands/graph.js +0 -238
  37. package/dist/commands/init.d.ts +0 -11
  38. package/dist/commands/init.js +0 -84
  39. package/dist/commands/insights.d.ts +0 -21
  40. package/dist/commands/insights.js +0 -434
  41. package/dist/commands/patterns.d.ts +0 -40
  42. package/dist/commands/patterns.js +0 -412
  43. package/dist/commands/pull.d.ts +0 -11
  44. package/dist/commands/pull.js +0 -121
  45. package/dist/commands/push.d.ts +0 -11
  46. package/dist/commands/push.js +0 -101
  47. package/dist/commands/quick-setup.d.ts +0 -20
  48. package/dist/commands/quick-setup.js +0 -422
  49. package/dist/commands/recent.d.ts +0 -9
  50. package/dist/commands/recent.js +0 -55
  51. package/dist/commands/related.d.ts +0 -23
  52. package/dist/commands/related.js +0 -257
  53. package/dist/commands/repos.d.ts +0 -14
  54. package/dist/commands/repos.js +0 -185
  55. package/dist/commands/stack.d.ts +0 -10
  56. package/dist/commands/stack.js +0 -83
  57. package/dist/commands/status.d.ts +0 -14
  58. package/dist/commands/status.js +0 -246
  59. package/dist/commands/sync.d.ts +0 -11
  60. package/dist/commands/sync.js +0 -142
  61. package/dist/commands/unfocus.d.ts +0 -6
  62. package/dist/commands/unfocus.js +0 -23
  63. package/dist/commands/used-by.d.ts +0 -10
  64. package/dist/commands/used-by.js +0 -111
  65. package/dist/commands/workspace.d.ts +0 -20
  66. package/dist/commands/workspace.js +0 -365
  67. package/dist/index.d.ts +0 -1
  68. package/dist/index.js +0 -5
  69. package/dist/models/entity.model.d.ts +0 -81
  70. package/dist/models/entity.model.js +0 -2
  71. package/dist/services/config.service.d.ts +0 -34
  72. package/dist/services/config.service.js +0 -230
  73. package/dist/services/entity.service.d.ts +0 -19
  74. package/dist/services/entity.service.js +0 -130
  75. package/dist/services/focus.service.d.ts +0 -70
  76. package/dist/services/focus.service.js +0 -587
  77. package/dist/services/git.service.d.ts +0 -37
  78. package/dist/services/git.service.js +0 -180
  79. package/dist/utils/display.d.ts +0 -25
  80. package/dist/utils/display.js +0 -150
  81. package/dist/utils/filesystem.d.ts +0 -32
  82. package/dist/utils/filesystem.js +0 -220
  83. package/dist/utils/index.d.ts +0 -13
  84. package/dist/utils/index.js +0 -18
  85. package/dist/utils/validation.d.ts +0 -22
  86. package/dist/utils/validation.js +0 -196
  87. package/oclif.manifest.json +0 -1463
@@ -1,113 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const base_command_1 = require("../base-command");
6
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
- const ora_1 = tslib_1.__importDefault(require("ora"));
8
- const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
9
- class Commit extends base_command_1.BaseCommand {
10
- static description = 'Commit changes in focused repositories';
11
- static examples = [
12
- '<%= config.bin %> <%= command.id %> -m "Fix bug"',
13
- '<%= config.bin %> <%= command.id %> --message "Add feature"',
14
- '<%= config.bin %> <%= command.id %>', // Interactive mode
15
- ];
16
- static flags = {
17
- message: core_1.Flags.string({
18
- char: 'm',
19
- description: 'Commit message',
20
- required: false,
21
- }),
22
- all: core_1.Flags.boolean({
23
- char: 'a',
24
- description: 'Stage all changes before committing',
25
- default: false,
26
- }),
27
- amend: core_1.Flags.boolean({
28
- description: 'Amend the previous commit',
29
- default: false,
30
- }),
31
- };
32
- async run() {
33
- const { flags } = await this.parse(Commit);
34
- const focusedEntities = await this.focusService.getFocusedEntities();
35
- if (focusedEntities.length === 0) {
36
- this.error('No entities are focused. Use "gut focus <entity>" first.');
37
- }
38
- let message = flags.message;
39
- // Interactive prompt for commit message if not provided
40
- if (!message && !flags.amend) {
41
- const response = await inquirer_1.default.prompt([
42
- {
43
- type: 'input',
44
- name: 'message',
45
- message: 'Enter commit message:',
46
- validate: (input) => {
47
- if (!input || input.trim().length === 0) {
48
- return 'Commit message cannot be empty';
49
- }
50
- return true;
51
- },
52
- },
53
- ]);
54
- message = response.message;
55
- }
56
- this.log(chalk_1.default.bold('\n💾 Committing changes in focused entities\n'));
57
- const results = {
58
- success: [],
59
- failed: [],
60
- noChanges: [],
61
- };
62
- for (const entity of focusedEntities) {
63
- const spinner = (0, ora_1.default)(`Committing in ${chalk_1.default.cyan(entity.name)}`).start();
64
- try {
65
- // Check if there are changes to commit
66
- const status = await this.gitService.getStatus(entity.path);
67
- const hasChanges = status.changes.length > 0 || status.untracked.length > 0;
68
- if (!hasChanges && !flags.amend) {
69
- spinner.info(chalk_1.default.yellow(`${entity.name}: No changes to commit`));
70
- results.noChanges.push(entity.name);
71
- continue;
72
- }
73
- // Build commit options
74
- const options = {
75
- all: flags.all,
76
- amend: flags.amend,
77
- };
78
- if (!message && flags.amend) {
79
- // Amend without changing message
80
- await this.gitService.exec(['commit', '--amend', '--no-edit'], { cwd: entity.path });
81
- }
82
- else {
83
- await this.gitService.commit(entity.path, message || '', options);
84
- }
85
- spinner.succeed(chalk_1.default.green(`✓ ${entity.name}: Committed successfully`));
86
- results.success.push(entity.name);
87
- }
88
- catch (error) {
89
- spinner.fail(chalk_1.default.red(`✗ ${entity.name}: ${error.message}`));
90
- results.failed.push({ repo: entity.name, error: error.message });
91
- }
92
- }
93
- // Summary
94
- this.log(chalk_1.default.bold('\n📊 Commit Summary'));
95
- this.log(chalk_1.default.dim('─'.repeat(50)));
96
- if (results.success.length > 0) {
97
- this.log(chalk_1.default.green(`✓ Success: ${results.success.length} entities`));
98
- }
99
- if (results.noChanges.length > 0) {
100
- this.log(chalk_1.default.yellow(`○ No changes: ${results.noChanges.length} entities`));
101
- }
102
- if (results.failed.length > 0) {
103
- this.log(chalk_1.default.red(`✗ Failed: ${results.failed.length} entities`));
104
- for (const failure of results.failed) {
105
- this.log(chalk_1.default.red(` - ${failure.repo}: ${failure.error}`));
106
- }
107
- }
108
- if (results.success.length > 0) {
109
- this.log(chalk_1.default.dim('\nTip: Use "gut push" to push commits to remote'));
110
- }
111
- }
112
- }
113
- exports.default = Commit;
@@ -1,6 +0,0 @@
1
- import { BaseCommand } from '../base-command';
2
- export default class Context extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- run(): Promise<void>;
6
- }
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const base_command_1 = require("../base-command");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const path = tslib_1.__importStar(require("path"));
7
- class Context extends base_command_1.BaseCommand {
8
- static description = 'Show current focus context with entity details';
9
- static examples = [
10
- '<%= config.bin %> <%= command.id %>',
11
- ];
12
- async run() {
13
- await this.parse(Context);
14
- const focusedEntities = await this.focusService.getFocusedEntities();
15
- if (focusedEntities.length === 0) {
16
- this.log(chalk_1.default.yellow('No entities are currently focused'));
17
- this.log(chalk_1.default.dim('Use "gut focus <entity>" to set focus'));
18
- return;
19
- }
20
- const workspaceRoot = this.configService.getWorkspaceRoot();
21
- this.log(chalk_1.default.bold('\n📍 Current Focus Context'));
22
- this.log(chalk_1.default.dim('─'.repeat(50)));
23
- for (const entity of focusedEntities) {
24
- this.log(`\n${chalk_1.default.green('▸')} ${chalk_1.default.bold(entity.name)}`);
25
- this.log(` ${chalk_1.default.dim('Type:')} ${entity.type}`);
26
- this.log(` ${chalk_1.default.dim('Path:')} ${path.relative(workspaceRoot, entity.path)}`);
27
- }
28
- this.log(chalk_1.default.dim('\n─'.repeat(50)));
29
- this.log(`${chalk_1.default.dim('Total focused entities:')} ${focusedEntities.length}`);
30
- const history = await this.configService.getHistory();
31
- if (history.length > 1) {
32
- this.log(`${chalk_1.default.dim('Previous focus:')} ${history[1].entities.join(', ')}`);
33
- }
34
- }
35
- }
36
- exports.default = Context;
@@ -1,7 +0,0 @@
1
- import { BaseCommand } from '../base-command';
2
- export default class Contexts extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- run(): Promise<void>;
6
- private formatTimeAgo;
7
- }
@@ -1,92 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const base_command_1 = require("../base-command");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- class Contexts extends base_command_1.BaseCommand {
7
- static description = 'List all available contexts and focus history';
8
- static examples = [
9
- '<%= config.bin %> <%= command.id %>',
10
- ];
11
- async run() {
12
- await this.parse(Contexts);
13
- // Show current focus
14
- const currentFocus = await this.focusService.getCurrentFocus();
15
- if (currentFocus) {
16
- this.log(chalk_1.default.bold('\n🎯 Current Focus'));
17
- this.log(chalk_1.default.dim('─'.repeat(50)));
18
- const description = await this.focusService.getFocusDescription();
19
- this.log(`${chalk_1.default.green('▸')} ${description}`);
20
- if (currentFocus.mode) {
21
- this.log(` ${chalk_1.default.dim('Mode:')} ${currentFocus.mode}`);
22
- }
23
- }
24
- // Show focus stack
25
- const focusStack = this.focusService.getFocusStack();
26
- if (focusStack.length > 0) {
27
- this.log(chalk_1.default.bold('\n📚 Focus Stack'));
28
- this.log(chalk_1.default.dim('─'.repeat(50)));
29
- focusStack.forEach((focus, index) => {
30
- const entities = focus.entities?.map(e => e.name).join(', ') || focus.name;
31
- const modeText = focus.mode ? ` (${focus.mode})` : '';
32
- this.log(`${chalk_1.default.yellow(`${index + 1}.`)} ${entities}${modeText}`);
33
- });
34
- this.log(chalk_1.default.dim('\nUse "gut back" to return to previous focus'));
35
- }
36
- // Show recent history
37
- const history = this.configService.getHistory();
38
- if (history.length > 0) {
39
- this.log(chalk_1.default.bold('\n📋 Recent Focus History'));
40
- this.log(chalk_1.default.dim('─'.repeat(50)));
41
- const recentHistory = history.slice(-5).reverse();
42
- recentHistory.forEach((entry, index) => {
43
- const timeAgo = this.formatTimeAgo(entry.timestamp);
44
- const entities = entry.entities.join(', ');
45
- this.log(`${chalk_1.default.dim(`${index + 1}.`)} ${entities} ${chalk_1.default.dim(`(${timeAgo})`)}`);
46
- });
47
- }
48
- // Show available entities by type
49
- const entities = this.entityService.getAllEntities();
50
- if (entities.length > 0) {
51
- this.log(chalk_1.default.bold('\n🏢 Available Entities'));
52
- this.log(chalk_1.default.dim('─'.repeat(50)));
53
- const entityTypes = ['client', 'prospect', 'company', 'initiative', 'system'];
54
- for (const type of entityTypes) {
55
- const entitiesOfType = entities.filter(e => e.type === type);
56
- if (entitiesOfType.length > 0) {
57
- this.log(`\n${chalk_1.default.bold(type.toUpperCase())}:`);
58
- entitiesOfType.forEach(entity => {
59
- const emoji = this.getTypeEmoji(entity.type);
60
- this.log(` ${emoji} ${entity.name}`);
61
- });
62
- }
63
- }
64
- // Show other types
65
- const otherEntities = entities.filter(e => !entityTypes.includes(e.type));
66
- if (otherEntities.length > 0) {
67
- this.log(`\n${chalk_1.default.bold('OTHER')}:`);
68
- otherEntities.forEach(entity => {
69
- const emoji = this.getTypeEmoji(entity.type);
70
- this.log(` ${emoji} ${entity.name} (${entity.type})`);
71
- });
72
- }
73
- }
74
- this.log(chalk_1.default.dim('\n─'.repeat(50)));
75
- this.log(chalk_1.default.dim('Use "gut focus <entity>" or "gut focus <type> <name>" to set focus'));
76
- }
77
- formatTimeAgo(timestamp) {
78
- const now = Date.now();
79
- const diff = now - timestamp;
80
- const minutes = Math.floor(diff / (1000 * 60));
81
- const hours = Math.floor(minutes / 60);
82
- const days = Math.floor(hours / 24);
83
- if (days > 0)
84
- return `${days}d ago`;
85
- if (hours > 0)
86
- return `${hours}h ago`;
87
- if (minutes > 0)
88
- return `${minutes}m ago`;
89
- return 'just now';
90
- }
91
- }
92
- exports.default = Contexts;
@@ -1,10 +0,0 @@
1
- import { BaseCommand } from '../base-command';
2
- export default class Deps extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- entity: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
- };
8
- run(): Promise<void>;
9
- private analyzeDependencies;
10
- }
@@ -1,104 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const base_command_1 = require("../base-command");
6
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
- class Deps extends base_command_1.BaseCommand {
8
- static description = 'Show dependencies of current focus or specified entity';
9
- static examples = [
10
- '<%= config.bin %> <%= command.id %>',
11
- '<%= config.bin %> <%= command.id %> mindtools',
12
- ];
13
- static args = {
14
- entity: core_1.Args.string({
15
- name: 'entity',
16
- required: false,
17
- description: 'Entity name to analyze dependencies for',
18
- }),
19
- };
20
- async run() {
21
- const { args } = await this.parse(Deps);
22
- let targetEntities = [];
23
- if (args.entity) {
24
- // Analyze specific entity
25
- const entity = this.entityService.findEntity(args.entity);
26
- if (!entity) {
27
- this.error(`Entity '${args.entity}' not found`);
28
- }
29
- targetEntities = [entity];
30
- }
31
- else {
32
- // Analyze current focus
33
- targetEntities = await this.focusService.getFocusedEntities();
34
- if (targetEntities.length === 0) {
35
- this.error('No entities in focus. Use "gut focus <entity>" first or specify an entity name.');
36
- }
37
- }
38
- this.log(chalk_1.default.bold('\n🔗 Dependencies Analysis'));
39
- this.log(chalk_1.default.dim('─'.repeat(50)));
40
- for (const entity of targetEntities) {
41
- this.log(`\n${chalk_1.default.green('▸')} ${chalk_1.default.bold(entity.name)} (${entity.type})`);
42
- const dependencies = await this.analyzeDependencies(entity);
43
- if (dependencies.direct.length > 0) {
44
- this.log(`\n ${chalk_1.default.yellow('Direct Dependencies:')}`);
45
- dependencies.direct.forEach(dep => {
46
- this.log(` ${this.getTypeEmoji(dep.type)} ${dep.name} (${dep.type})`);
47
- });
48
- }
49
- if (dependencies.system.length > 0) {
50
- this.log(`\n ${chalk_1.default.blue('System Dependencies:')}`);
51
- dependencies.system.forEach(dep => {
52
- this.log(` ${this.getTypeEmoji(dep.type)} ${dep.name} (${dep.type})`);
53
- });
54
- }
55
- if (dependencies.inferred.length > 0) {
56
- this.log(`\n ${chalk_1.default.dim('Inferred Dependencies:')}`);
57
- dependencies.inferred.forEach(dep => {
58
- this.log(` ${this.getTypeEmoji(dep.type)} ${dep.name} (${dep.type}) ${chalk_1.default.dim('- pattern based')}`);
59
- });
60
- }
61
- if (dependencies.direct.length === 0 && dependencies.system.length === 0 && dependencies.inferred.length === 0) {
62
- this.log(` ${chalk_1.default.dim('No dependencies found')}`);
63
- }
64
- }
65
- this.log(chalk_1.default.dim('\n─'.repeat(50)));
66
- this.log(chalk_1.default.dim('Dependencies are determined from entity metadata and usage patterns'));
67
- }
68
- async analyzeDependencies(entity) {
69
- const allEntities = this.entityService.getAllEntities();
70
- // Direct dependencies from metadata
71
- const directDeps = [];
72
- if (entity.metadata?.relationships?.dependent_systems) {
73
- for (const depName of entity.metadata.relationships.dependent_systems) {
74
- const depEntity = allEntities.find(e => e.name === depName || e.path.includes(depName));
75
- if (depEntity) {
76
- directDeps.push(depEntity);
77
- }
78
- }
79
- }
80
- // System dependencies (all entities depend on systems)
81
- const systemDeps = allEntities.filter(e => e.type === 'system' && e.name !== entity.name);
82
- // Inferred dependencies based on patterns
83
- const inferredDeps = [];
84
- // Clients typically depend on shared design systems
85
- if (entity.type === 'client') {
86
- const designSystem = allEntities.find(e => e.name.includes('design') || e.name.includes('shared') || e.type === 'module');
87
- if (designSystem && !directDeps.includes(designSystem) && !systemDeps.includes(designSystem)) {
88
- inferredDeps.push(designSystem);
89
- }
90
- }
91
- // Prospects might depend on similar client patterns
92
- if (entity.type === 'prospect') {
93
- const similarClients = allEntities.filter(e => e.type === 'client' &&
94
- entity.metadata?.relationships?.similar_entities?.includes(e.name));
95
- inferredDeps.push(...similarClients);
96
- }
97
- return {
98
- direct: directDeps,
99
- system: systemDeps.slice(0, 3), // Limit to avoid clutter
100
- inferred: inferredDeps
101
- };
102
- }
103
- }
104
- exports.default = Deps;
@@ -1,16 +0,0 @@
1
- import { BaseCommand } from '../../base-command';
2
- export default class AddEntity extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- type: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
- name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- path: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
- remote: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
- description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
- repo: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
- };
15
- run(): Promise<void>;
16
- }
@@ -1,105 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const base_command_1 = require("../../base-command");
6
- const path = tslib_1.__importStar(require("path"));
7
- const fs = tslib_1.__importStar(require("fs"));
8
- class AddEntity extends base_command_1.BaseCommand {
9
- static description = 'Add a new entity to the workspace';
10
- static examples = [
11
- '<%= config.bin %> <%= command.id %> delivery my-app --path ./apps/my-app',
12
- '<%= config.bin %> <%= command.id %> module my-lib --path ./libs/my-lib --remote git@github.com:org/my-lib.git',
13
- ];
14
- static args = {
15
- type: core_1.Args.string({
16
- name: 'type',
17
- required: true,
18
- description: 'Entity type',
19
- options: ['client', 'prospect', 'company', 'initiative', 'system', 'delivery', 'module', 'service', 'tool'],
20
- }),
21
- name: core_1.Args.string({
22
- name: 'name',
23
- required: true,
24
- description: 'Entity name',
25
- }),
26
- };
27
- static flags = {
28
- path: core_1.Flags.string({
29
- char: 'p',
30
- description: 'path to entity',
31
- required: true,
32
- }),
33
- remote: core_1.Flags.string({
34
- char: 'r',
35
- description: 'git remote URL',
36
- }),
37
- description: core_1.Flags.string({
38
- char: 'd',
39
- description: 'entity description',
40
- }),
41
- repo: core_1.Flags.string({
42
- description: 'repository name (for GitLab/GitHub)',
43
- }),
44
- };
45
- async run() {
46
- const { args, flags } = await this.parse(AddEntity);
47
- // Validate entity name
48
- if (!this.entityService.validateEntityName(args.name)) {
49
- this.error('Entity name must be alphanumeric with hyphens or underscores');
50
- }
51
- // Check if entity already exists
52
- if (this.entityService.findEntity(args.name)) {
53
- this.error(`Entity '${args.name}' already exists`);
54
- }
55
- // Validate and resolve path
56
- const entityPath = path.isAbsolute(flags.path)
57
- ? flags.path
58
- : path.join(this.configService.getWorkspaceRoot(), flags.path);
59
- // Create directory if it doesn't exist (especially for new entity types)
60
- if (!fs.existsSync(entityPath)) {
61
- const isNewEntityType = ['client', 'prospect', 'company', 'initiative', 'system'].includes(args.type);
62
- if (isNewEntityType) {
63
- fs.mkdirSync(entityPath, { recursive: true });
64
- this.log(`✓ Created directory: ${flags.path}`);
65
- }
66
- else {
67
- this.error(`Path '${flags.path}' does not exist`);
68
- }
69
- }
70
- if (!fs.statSync(entityPath).isDirectory()) {
71
- this.error(`Path '${flags.path}' is not a directory`);
72
- }
73
- // Check if it's a git repository
74
- const isGitRepo = await this.gitService.isRepository(entityPath);
75
- // Get remote URL if it's a git repo and no remote provided
76
- let remoteUrl = flags.remote;
77
- if (isGitRepo && !remoteUrl) {
78
- remoteUrl = await this.gitService.getRemoteUrl(entityPath) || undefined;
79
- }
80
- // Create entity
81
- const entity = {
82
- name: args.name,
83
- type: args.type,
84
- path: flags.path.startsWith('./') ? flags.path : `./${flags.path}`,
85
- remote: remoteUrl,
86
- repo: flags.repo,
87
- description: flags.description,
88
- };
89
- // Add entity
90
- await this.entityService.addEntity(entity.name, entity.type, entity.path, entity.remote || entity.repo);
91
- this.log(`✅ Added ${args.type} entity '${args.name}'`);
92
- this.log(` Path: ${entity.path}`);
93
- if (entity.remote) {
94
- this.log(` Remote: ${entity.remote}`);
95
- }
96
- if (entity.description) {
97
- this.log(` Description: ${entity.description}`);
98
- }
99
- this.log('\nYou can now:');
100
- this.log(` • Focus on this entity: gut focus ${args.name}`);
101
- this.log(` • Clone it elsewhere: gut entity clone ${args.name}`);
102
- this.log(` • View all entities: gut entity list`);
103
- }
104
- }
105
- exports.default = AddEntity;
@@ -1,17 +0,0 @@
1
- import BaseCommand from '../../base-command';
2
- export default class CloneAll extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- branch: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- depth: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- parallel: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
- 'skip-existing': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
- force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
- };
12
- run(): Promise<void>;
13
- private cloneSequentially;
14
- private cloneInParallel;
15
- private cloneEntity;
16
- private printSummary;
17
- }
@@ -1,135 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const base_command_1 = tslib_1.__importDefault(require("../../base-command"));
6
- const path = tslib_1.__importStar(require("path"));
7
- const fs = tslib_1.__importStar(require("fs"));
8
- const child_process_1 = require("child_process");
9
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
10
- const ora_1 = tslib_1.__importDefault(require("ora"));
11
- class CloneAll extends base_command_1.default {
12
- static description = 'Clone all configured entities from their repositories';
13
- static examples = [
14
- '<%= config.bin %> <%= command.id %>',
15
- '<%= config.bin %> <%= command.id %> --parallel',
16
- '<%= config.bin %> <%= command.id %> --branch develop',
17
- '<%= config.bin %> <%= command.id %> --skip-existing',
18
- ];
19
- static flags = {
20
- branch: core_1.Flags.string({
21
- char: 'b',
22
- description: 'Branch to clone for all entities',
23
- default: 'main',
24
- }),
25
- depth: core_1.Flags.integer({
26
- char: 'd',
27
- description: 'Create shallow clones with specified depth',
28
- }),
29
- parallel: core_1.Flags.boolean({
30
- char: 'p',
31
- description: 'Clone entities in parallel',
32
- default: false,
33
- }),
34
- 'skip-existing': core_1.Flags.boolean({
35
- description: 'Skip entities that already exist',
36
- default: false,
37
- }),
38
- force: core_1.Flags.boolean({
39
- char: 'f',
40
- description: 'Force clone even if directories exist',
41
- default: false,
42
- }),
43
- };
44
- async run() {
45
- const { flags } = await this.parse(CloneAll);
46
- const { branch, depth, parallel, 'skip-existing': skipExisting, force } = flags;
47
- const entities = await this.entityService.listEntities();
48
- const entitiesToClone = entities.filter(e => e.repository);
49
- if (entitiesToClone.length === 0) {
50
- this.log(chalk_1.default.yellow('No entities with repositories configured'));
51
- return;
52
- }
53
- this.log(chalk_1.default.blue(`Found ${entitiesToClone.length} entities to clone`));
54
- const results = [];
55
- if (parallel) {
56
- await this.cloneInParallel(entitiesToClone, branch, depth, skipExisting, force, results);
57
- }
58
- else {
59
- await this.cloneSequentially(entitiesToClone, branch, depth, skipExisting, force, results);
60
- }
61
- this.printSummary(results);
62
- }
63
- async cloneSequentially(entities, branch, depth, skipExisting, force, results) {
64
- for (const entity of entities) {
65
- const result = await this.cloneEntity(entity, branch, depth, skipExisting, force);
66
- results.push(result);
67
- }
68
- }
69
- async cloneInParallel(entities, branch, depth, skipExisting, force, results) {
70
- const promises = entities.map(entity => this.cloneEntity(entity, branch, depth, skipExisting, force));
71
- const parallelResults = await Promise.all(promises);
72
- results.push(...parallelResults);
73
- }
74
- async cloneEntity(entity, branch, depth, skipExisting, force) {
75
- const spinner = (0, ora_1.default)(`Cloning ${entity.name}`).start();
76
- try {
77
- const clonePath = path.resolve(this.config.root, entity.path);
78
- if (fs.existsSync(clonePath)) {
79
- if (skipExisting) {
80
- spinner.info(`Skipped ${entity.name} (already exists)`);
81
- return { entity, success: true, message: 'Skipped (exists)' };
82
- }
83
- if (!force) {
84
- spinner.fail(`${entity.name} already exists (use --force to overwrite)`);
85
- return { entity, success: false, message: 'Already exists' };
86
- }
87
- (0, child_process_1.execSync)(`rm -rf ${clonePath}`, { stdio: 'pipe' });
88
- }
89
- const parentDir = path.dirname(clonePath);
90
- if (!fs.existsSync(parentDir)) {
91
- fs.mkdirSync(parentDir, { recursive: true });
92
- }
93
- let cloneCommand = `git clone`;
94
- if (branch && branch !== 'main') {
95
- cloneCommand += ` -b ${branch}`;
96
- }
97
- if (depth) {
98
- cloneCommand += ` --depth ${depth}`;
99
- }
100
- cloneCommand += ` ${entity.repository || entity.repo} ${clonePath}`;
101
- (0, child_process_1.execSync)(cloneCommand, { stdio: 'pipe' });
102
- const gitBranch = (0, child_process_1.execSync)('git branch --show-current', {
103
- cwd: clonePath,
104
- encoding: 'utf-8'
105
- }).trim();
106
- spinner.succeed(`Cloned ${entity.name} (${gitBranch})`);
107
- return { entity, success: true, message: `Cloned (${gitBranch})` };
108
- }
109
- catch (error) {
110
- spinner.fail(`Failed to clone ${entity.name}`);
111
- return { entity, success: false, message: error.message };
112
- }
113
- }
114
- printSummary(results) {
115
- const successful = results.filter(r => r.success);
116
- const failed = results.filter(r => !r.success);
117
- this.log('');
118
- this.log(chalk_1.default.bold('Clone Summary:'));
119
- this.log(chalk_1.default.green(` ✓ Successful: ${successful.length}`));
120
- if (failed.length > 0) {
121
- this.log(chalk_1.default.red(` ✗ Failed: ${failed.length}`));
122
- this.log('');
123
- this.log(chalk_1.default.red('Failed entities:'));
124
- failed.forEach(r => {
125
- this.log(chalk_1.default.red(` - ${r.entity.name}: ${r.message}`));
126
- });
127
- }
128
- this.log('');
129
- this.log(chalk_1.default.dim('Entity locations:'));
130
- successful.forEach(r => {
131
- this.log(chalk_1.default.dim(` ${r.entity.name}: ${r.entity.path}`));
132
- });
133
- }
134
- }
135
- exports.default = CloneAll;
@@ -1,15 +0,0 @@
1
- import BaseCommand from '../../base-command';
2
- export default class Clone extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- branch: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- depth: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- path: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
- };
11
- static args: {
12
- name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
13
- };
14
- run(): Promise<void>;
15
- }