@hyperdrive.bot/gut 0.1.3 → 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.
- package/README.md +1 -779
- package/bin/run.js +5 -0
- package/package.json +10 -10
- package/bin/run +0 -5
- package/dist/base-command.d.ts +0 -21
- package/dist/base-command.js +0 -110
- package/dist/commands/add.d.ts +0 -13
- package/dist/commands/add.js +0 -73
- package/dist/commands/affected.d.ts +0 -23
- package/dist/commands/affected.js +0 -326
- package/dist/commands/audit.d.ts +0 -33
- package/dist/commands/audit.js +0 -593
- package/dist/commands/back.d.ts +0 -6
- package/dist/commands/back.js +0 -29
- package/dist/commands/commit.d.ts +0 -11
- package/dist/commands/commit.js +0 -113
- package/dist/commands/context.d.ts +0 -6
- package/dist/commands/context.js +0 -36
- package/dist/commands/contexts.d.ts +0 -7
- package/dist/commands/contexts.js +0 -92
- package/dist/commands/deps.d.ts +0 -10
- package/dist/commands/deps.js +0 -104
- package/dist/commands/entity/add.d.ts +0 -16
- package/dist/commands/entity/add.js +0 -105
- package/dist/commands/entity/clone-all.d.ts +0 -17
- package/dist/commands/entity/clone-all.js +0 -135
- package/dist/commands/entity/clone.d.ts +0 -15
- package/dist/commands/entity/clone.js +0 -109
- package/dist/commands/entity/list.d.ts +0 -11
- package/dist/commands/entity/list.js +0 -82
- package/dist/commands/entity/remove.d.ts +0 -12
- package/dist/commands/entity/remove.js +0 -58
- package/dist/commands/focus.d.ts +0 -19
- package/dist/commands/focus.js +0 -139
- package/dist/commands/graph.d.ts +0 -18
- package/dist/commands/graph.js +0 -238
- package/dist/commands/init.d.ts +0 -11
- package/dist/commands/init.js +0 -84
- package/dist/commands/insights.d.ts +0 -21
- package/dist/commands/insights.js +0 -434
- package/dist/commands/patterns.d.ts +0 -40
- package/dist/commands/patterns.js +0 -412
- package/dist/commands/pull.d.ts +0 -11
- package/dist/commands/pull.js +0 -121
- package/dist/commands/push.d.ts +0 -11
- package/dist/commands/push.js +0 -101
- package/dist/commands/quick-setup.d.ts +0 -20
- package/dist/commands/quick-setup.js +0 -422
- package/dist/commands/recent.d.ts +0 -9
- package/dist/commands/recent.js +0 -55
- package/dist/commands/related.d.ts +0 -23
- package/dist/commands/related.js +0 -257
- package/dist/commands/repos.d.ts +0 -14
- package/dist/commands/repos.js +0 -185
- package/dist/commands/stack.d.ts +0 -10
- package/dist/commands/stack.js +0 -83
- package/dist/commands/status.d.ts +0 -14
- package/dist/commands/status.js +0 -246
- package/dist/commands/sync.d.ts +0 -11
- package/dist/commands/sync.js +0 -142
- package/dist/commands/unfocus.d.ts +0 -6
- package/dist/commands/unfocus.js +0 -23
- package/dist/commands/used-by.d.ts +0 -10
- package/dist/commands/used-by.js +0 -111
- package/dist/commands/workspace.d.ts +0 -20
- package/dist/commands/workspace.js +0 -365
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -5
- package/dist/models/entity.model.d.ts +0 -81
- package/dist/models/entity.model.js +0 -2
- package/dist/services/config.service.d.ts +0 -34
- package/dist/services/config.service.js +0 -230
- package/dist/services/entity.service.d.ts +0 -19
- package/dist/services/entity.service.js +0 -130
- package/dist/services/focus.service.d.ts +0 -70
- package/dist/services/focus.service.js +0 -587
- package/dist/services/git.service.d.ts +0 -37
- package/dist/services/git.service.js +0 -180
- package/dist/utils/display.d.ts +0 -25
- package/dist/utils/display.js +0 -150
- package/dist/utils/filesystem.d.ts +0 -32
- package/dist/utils/filesystem.js +0 -220
- package/dist/utils/index.d.ts +0 -13
- package/dist/utils/index.js +0 -18
- package/dist/utils/validation.d.ts +0 -22
- package/dist/utils/validation.js +0 -196
- package/oclif.manifest.json +0 -1463
package/dist/commands/commit.js
DELETED
|
@@ -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;
|
package/dist/commands/context.js
DELETED
|
@@ -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,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;
|
package/dist/commands/deps.d.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/commands/deps.js
DELETED
|
@@ -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
|
-
}
|