@hyperdrive.bot/cli 1.0.2

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 (127) hide show
  1. package/README.md +1598 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +3 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/commands/account/add.d.ts +16 -0
  7. package/dist/commands/account/add.js +185 -0
  8. package/dist/commands/account/list.d.ts +6 -0
  9. package/dist/commands/account/list.js +37 -0
  10. package/dist/commands/account/remove.d.ts +11 -0
  11. package/dist/commands/account/remove.js +57 -0
  12. package/dist/commands/auth/login.d.ts +16 -0
  13. package/dist/commands/auth/login.js +178 -0
  14. package/dist/commands/auth/logout.d.ts +6 -0
  15. package/dist/commands/auth/logout.js +39 -0
  16. package/dist/commands/auth/refresh.d.ts +6 -0
  17. package/dist/commands/auth/refresh.js +66 -0
  18. package/dist/commands/auth/status.d.ts +6 -0
  19. package/dist/commands/auth/status.js +63 -0
  20. package/dist/commands/ci/account/create.d.ts +16 -0
  21. package/dist/commands/ci/account/create.js +158 -0
  22. package/dist/commands/ci/account/delete.d.ts +14 -0
  23. package/dist/commands/ci/account/delete.js +88 -0
  24. package/dist/commands/ci/account/list.d.ts +10 -0
  25. package/dist/commands/ci/account/list.js +65 -0
  26. package/dist/commands/config/get.d.ts +9 -0
  27. package/dist/commands/config/get.js +37 -0
  28. package/dist/commands/config/set.d.ts +10 -0
  29. package/dist/commands/config/set.js +48 -0
  30. package/dist/commands/config/show.d.ts +6 -0
  31. package/dist/commands/config/show.js +10 -0
  32. package/dist/commands/deployment/create.d.ts +30 -0
  33. package/dist/commands/deployment/create.js +188 -0
  34. package/dist/commands/deployment/get.d.ts +13 -0
  35. package/dist/commands/deployment/get.js +101 -0
  36. package/dist/commands/deployment/launch.d.ts +15 -0
  37. package/dist/commands/deployment/launch.js +105 -0
  38. package/dist/commands/deployment/list.d.ts +11 -0
  39. package/dist/commands/deployment/list.js +91 -0
  40. package/dist/commands/domain/current.d.ts +6 -0
  41. package/dist/commands/domain/current.js +18 -0
  42. package/dist/commands/domain/list.d.ts +6 -0
  43. package/dist/commands/domain/list.js +42 -0
  44. package/dist/commands/domain/switch.d.ts +9 -0
  45. package/dist/commands/domain/switch.js +40 -0
  46. package/dist/commands/example.d.ts +13 -0
  47. package/dist/commands/example.js +24 -0
  48. package/dist/commands/git/connect.d.ts +10 -0
  49. package/dist/commands/git/connect.js +56 -0
  50. package/dist/commands/git/disconnect.d.ts +11 -0
  51. package/dist/commands/git/disconnect.js +93 -0
  52. package/dist/commands/git/list.d.ts +10 -0
  53. package/dist/commands/git/list.js +53 -0
  54. package/dist/commands/git/sync.d.ts +18 -0
  55. package/dist/commands/git/sync.js +235 -0
  56. package/dist/commands/init.d.ts +188 -0
  57. package/dist/commands/init.js +817 -0
  58. package/dist/commands/jira/connect.d.ts +9 -0
  59. package/dist/commands/jira/connect.js +141 -0
  60. package/dist/commands/jira/status.d.ts +9 -0
  61. package/dist/commands/jira/status.js +118 -0
  62. package/dist/commands/module/analyze.d.ts +29 -0
  63. package/dist/commands/module/analyze.js +201 -0
  64. package/dist/commands/module/create.d.ts +42 -0
  65. package/dist/commands/module/create.js +498 -0
  66. package/dist/commands/module/destroy.d.ts +11 -0
  67. package/dist/commands/module/destroy.js +77 -0
  68. package/dist/commands/module/get.d.ts +10 -0
  69. package/dist/commands/module/get.js +43 -0
  70. package/dist/commands/module/link.d.ts +15 -0
  71. package/dist/commands/module/link.js +175 -0
  72. package/dist/commands/module/list.d.ts +9 -0
  73. package/dist/commands/module/list.js +51 -0
  74. package/dist/commands/module/reanalyze.d.ts +30 -0
  75. package/dist/commands/module/reanalyze.js +206 -0
  76. package/dist/commands/module/update.d.ts +27 -0
  77. package/dist/commands/module/update.js +102 -0
  78. package/dist/commands/parameter/add.d.ts +15 -0
  79. package/dist/commands/parameter/add.js +99 -0
  80. package/dist/commands/parameter/backfill.d.ts +12 -0
  81. package/dist/commands/parameter/backfill.js +113 -0
  82. package/dist/commands/parameter/clear.d.ts +14 -0
  83. package/dist/commands/parameter/clear.js +95 -0
  84. package/dist/commands/parameter/list.d.ts +14 -0
  85. package/dist/commands/parameter/list.js +92 -0
  86. package/dist/commands/parameter/pull.d.ts +14 -0
  87. package/dist/commands/parameter/pull.js +124 -0
  88. package/dist/commands/parameter/remove.d.ts +15 -0
  89. package/dist/commands/parameter/remove.js +90 -0
  90. package/dist/commands/parameter/sync.d.ts +14 -0
  91. package/dist/commands/parameter/sync.js +153 -0
  92. package/dist/commands/parameter/update.d.ts +15 -0
  93. package/dist/commands/parameter/update.js +100 -0
  94. package/dist/commands/stage/create.d.ts +28 -0
  95. package/dist/commands/stage/create.js +312 -0
  96. package/dist/commands/stage/list.d.ts +9 -0
  97. package/dist/commands/stage/list.js +63 -0
  98. package/dist/commands/test-api.d.ts +9 -0
  99. package/dist/commands/test-api.js +40 -0
  100. package/dist/index.d.ts +1 -0
  101. package/dist/index.js +1 -0
  102. package/dist/services/auth-service.d.ts +84 -0
  103. package/dist/services/auth-service.js +240 -0
  104. package/dist/services/git.d.ts +46 -0
  105. package/dist/services/git.js +409 -0
  106. package/dist/services/hyperdrive-sigv4.d.ts +449 -0
  107. package/dist/services/hyperdrive-sigv4.js +375 -0
  108. package/dist/services/hyperdrive.d.ts +87 -0
  109. package/dist/services/hyperdrive.js +108 -0
  110. package/dist/services/log-tailer.d.ts +95 -0
  111. package/dist/services/log-tailer.js +242 -0
  112. package/dist/services/tenant-service.d.ts +106 -0
  113. package/dist/services/tenant-service.js +332 -0
  114. package/dist/utils/account-flow.d.ts +74 -0
  115. package/dist/utils/account-flow.js +228 -0
  116. package/dist/utils/auth-flow.d.ts +146 -0
  117. package/dist/utils/auth-flow.js +477 -0
  118. package/dist/utils/git-flow.d.ts +72 -0
  119. package/dist/utils/git-flow.js +232 -0
  120. package/dist/utils/jira-flow.d.ts +71 -0
  121. package/dist/utils/jira-flow.js +120 -0
  122. package/dist/utils/summary-display.d.ts +59 -0
  123. package/dist/utils/summary-display.js +140 -0
  124. package/dist/utils/validation.d.ts +15 -0
  125. package/dist/utils/validation.js +32 -0
  126. package/oclif.manifest.json +2819 -0
  127. package/package.json +112 -0
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Example extends Command {
3
+ static args: {
4
+ file: import("@oclif/core/lib/interfaces/parser.js").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
+ name: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,24 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ export default class Example extends Command {
3
+ static args = {
4
+ file: Args.string({ description: 'file to read' }),
5
+ };
6
+ static description = 'describe the command here';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ ];
10
+ static flags = {
11
+ // flag with no value (-f, --force)
12
+ force: Flags.boolean({ char: 'f' }),
13
+ // flag with a value (-n, --name=VALUE)
14
+ name: Flags.string({ char: 'n', description: 'name to print' }),
15
+ };
16
+ async run() {
17
+ const { args, flags } = await this.parse(Example);
18
+ const name = flags.name ?? 'world';
19
+ this.log(`hello ${name} from /Users/marcelomarra/Developer/devsquad/hyperdrive/cli/src/commands/example.ts`);
20
+ if (args.file && flags.force) {
21
+ this.log(`you input --force and --file: ${args.file}`);
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class GitConnect extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ domain: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ provider: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,56 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { executeGitConnect } from '../../utils/git-flow.js';
4
+ export default class GitConnect extends Command {
5
+ static description = 'Connect a GitHub or GitLab account to Hyperdrive';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %> --provider=github',
8
+ '<%= config.bin %> <%= command.id %> --provider=gitlab',
9
+ ];
10
+ static flags = {
11
+ domain: Flags.string({
12
+ char: 'd',
13
+ description: 'Tenant domain (for multi-domain setups)',
14
+ }),
15
+ provider: Flags.string({
16
+ char: 'p',
17
+ description: 'Git provider to connect',
18
+ options: ['github', 'gitlab'],
19
+ }),
20
+ };
21
+ async run() {
22
+ const { flags } = await this.parse(GitConnect);
23
+ const provider = flags.provider;
24
+ if (provider) {
25
+ this.log(chalk.blue(`\nConnecting to ${provider === 'github' ? 'GitHub' : 'GitLab'}...`));
26
+ }
27
+ try {
28
+ const result = await executeGitConnect({
29
+ logger: (message) => this.log(chalk.gray(message)),
30
+ provider,
31
+ });
32
+ if (result.success) {
33
+ const providerName = result.provider === 'github' ? 'GitHub' : 'GitLab';
34
+ this.log(chalk.green(`\n✅ Successfully connected to ${providerName}!`));
35
+ // Display connected accounts
36
+ if (result.installations && result.installations.length > 0) {
37
+ this.log(chalk.blue('\nConnected accounts:'));
38
+ for (const installation of result.installations) {
39
+ const accountName = installation.accountLogin || installation.gitlabUsername || 'Unknown';
40
+ this.log(chalk.white(` - ${accountName} (${installation.provider})`));
41
+ }
42
+ }
43
+ }
44
+ else if (result.skipped) {
45
+ this.log(chalk.yellow('\n⚠ Git provider connection skipped.'));
46
+ }
47
+ else {
48
+ this.log(chalk.red(`\n❌ Failed to connect: ${result.error || 'Unknown error'}`));
49
+ }
50
+ }
51
+ catch (error) {
52
+ const errorMessage = error instanceof Error ? error.message : String(error);
53
+ this.error(`Failed to connect: ${errorMessage}`);
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,11 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class GitDisconnect extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ domain: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ installationId: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ provider: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,93 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import { HyperdriveSigV4Service } from '../../services/hyperdrive-sigv4.js';
5
+ export default class GitDisconnect extends Command {
6
+ static description = 'Disconnect a Git account from Hyperdrive';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ '<%= config.bin %> <%= command.id %> --provider=github --installation-id=12345',
10
+ ];
11
+ static flags = {
12
+ domain: Flags.string({
13
+ char: 'd',
14
+ description: 'Tenant domain (for multi-domain setups)',
15
+ }),
16
+ installationId: Flags.string({
17
+ char: 'i',
18
+ description: 'Installation ID to disconnect',
19
+ }),
20
+ provider: Flags.string({
21
+ char: 'p',
22
+ description: 'Git provider',
23
+ options: ['github', 'gitlab'],
24
+ }),
25
+ };
26
+ async run() {
27
+ const { flags } = await this.parse(GitDisconnect);
28
+ const service = new HyperdriveSigV4Service(flags.domain);
29
+ try {
30
+ // List installations to let user select
31
+ const response = await service.gitListInstallations();
32
+ if (response.installations.length === 0) {
33
+ this.log(chalk.yellow('\nNo Git accounts connected.'));
34
+ return;
35
+ }
36
+ let provider = flags.provider;
37
+ let installationId = flags.installationId;
38
+ if (!installationId) {
39
+ // Show list and let user select
40
+ const choices = response.installations.map((installation) => ({
41
+ name: `${installation.provider === 'github' ? '🐙' : 'đŸĻŠ'} ${installation.accountLogin || installation.gitlabUsername || 'Unknown'} (${installation.provider})`,
42
+ value: {
43
+ installationId: installation.installationId,
44
+ provider: installation.provider,
45
+ },
46
+ }));
47
+ const selection = await inquirer.prompt([{
48
+ choices,
49
+ message: chalk.yellow('Which Git account would you like to disconnect?'),
50
+ name: 'installation',
51
+ type: 'list',
52
+ }]);
53
+ provider = selection.installation.provider;
54
+ installationId = selection.installation.installationId;
55
+ }
56
+ if (!provider) {
57
+ const providerResponse = await inquirer.prompt([{
58
+ choices: [
59
+ { name: 'GitHub', value: 'github' },
60
+ { name: 'GitLab', value: 'gitlab' },
61
+ ],
62
+ message: chalk.yellow('Which Git provider?'),
63
+ name: 'provider',
64
+ type: 'list',
65
+ }]);
66
+ provider = providerResponse.provider;
67
+ }
68
+ // Confirm disconnection
69
+ const confirm = await inquirer.prompt([{
70
+ default: false,
71
+ message: chalk.red('Are you sure you want to disconnect this Git account? This cannot be undone.'),
72
+ name: 'confirm',
73
+ type: 'confirm',
74
+ }]);
75
+ if (!confirm.confirm) {
76
+ this.log(chalk.gray('Disconnection cancelled.'));
77
+ return;
78
+ }
79
+ // Delete the installation
80
+ const result = await service.gitDeleteInstallation(provider, installationId);
81
+ if (result.success) {
82
+ this.log(chalk.green(`\n✅ ${result.message}`));
83
+ }
84
+ else {
85
+ this.log(chalk.red(`\n❌ Failed to disconnect: ${result.message}`));
86
+ }
87
+ }
88
+ catch (error) {
89
+ const errorMessage = error instanceof Error ? error.message : String(error);
90
+ this.error(`Failed to disconnect Git account: ${errorMessage}`);
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class GitList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ domain: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
+ provider: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,53 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import { HyperdriveSigV4Service } from '../../services/hyperdrive-sigv4.js';
4
+ export default class GitList extends Command {
5
+ static description = 'List connected Git accounts';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> <%= command.id %> --provider=github',
9
+ ];
10
+ static flags = {
11
+ domain: Flags.string({
12
+ char: 'd',
13
+ description: 'Tenant domain (for multi-domain setups)',
14
+ }),
15
+ provider: Flags.string({
16
+ char: 'p',
17
+ description: 'Filter by Git provider',
18
+ options: ['github', 'gitlab'],
19
+ }),
20
+ };
21
+ async run() {
22
+ const { flags } = await this.parse(GitList);
23
+ const service = new HyperdriveSigV4Service(flags.domain);
24
+ try {
25
+ const provider = flags.provider;
26
+ const response = await service.gitListInstallations(provider);
27
+ if (response.installations.length === 0) {
28
+ this.log(chalk.yellow('\nNo Git accounts connected.'));
29
+ this.log(chalk.gray('Run "hd git connect" to connect a GitHub or GitLab account.'));
30
+ return;
31
+ }
32
+ this.log(chalk.blue('\nConnected Git Accounts:'));
33
+ this.log('');
34
+ for (const installation of response.installations) {
35
+ const providerIcon = installation.provider === 'github' ? '🐙' : 'đŸĻŠ';
36
+ const accountName = installation.accountLogin || installation.gitlabUsername || 'Unknown';
37
+ const accountType = installation.accountType || '';
38
+ const status = installation.status === 'active'
39
+ ? chalk.green('active')
40
+ : chalk.yellow(installation.status);
41
+ this.log(`${providerIcon} ${chalk.white.bold(accountName)} ${accountType ? chalk.gray(`(${accountType})`) : ''}`);
42
+ this.log(` Provider: ${installation.provider}`);
43
+ this.log(` Status: ${status}`);
44
+ this.log(` Connected: ${new Date(installation.installedAt).toLocaleString()}`);
45
+ this.log('');
46
+ }
47
+ }
48
+ catch (error) {
49
+ const errorMessage = error instanceof Error ? error.message : String(error);
50
+ this.error(`Failed to list Git accounts: ${errorMessage}`);
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,18 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Sync extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ all: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ branch: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ domain: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ 'merge-strategy': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ remote: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
+ 'source-branch': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ verbose: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ private displayConfiguration;
16
+ private displayResults;
17
+ private formatDuration;
18
+ }
@@ -0,0 +1,235 @@
1
+ import { Command, Flags, ux } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import * as ora from 'ora';
4
+ import { GitService } from '../../services/git.js';
5
+ export default class Sync extends Command {
6
+ static description = 'Sync specific branches or all open branches with a source branch (default: master)';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> --branch feature-branch',
9
+ '<%= config.bin %> <%= command.id %> --branch feature-1 --branch feature-2',
10
+ '<%= config.bin %> <%= command.id %> --all',
11
+ '<%= config.bin %> <%= command.id %> --branch feature-branch --source-branch main',
12
+ '<%= config.bin %> <%= command.id %> --all --remote upstream --merge-strategy no-ff',
13
+ ];
14
+ static flags = {
15
+ all: Flags.boolean({
16
+ char: 'a',
17
+ default: false,
18
+ description: 'Sync all remote branches'
19
+ }),
20
+ branch: Flags.string({
21
+ char: 'b',
22
+ description: 'Specific branch(es) to sync (can be used multiple times)',
23
+ multiple: true
24
+ }),
25
+ domain: Flags.string({
26
+ char: 'd',
27
+ description: 'Tenant domain (for multi-domain setups)',
28
+ }),
29
+ 'merge-strategy': Flags.string({
30
+ char: 'm',
31
+ default: 'no-ff',
32
+ description: 'Git merge strategy',
33
+ options: ['no-ff', '--ff-only', '--no-ff', '--squash']
34
+ }),
35
+ remote: Flags.string({
36
+ char: 'r',
37
+ default: 'origin',
38
+ description: 'Remote repository name'
39
+ }),
40
+ 'source-branch': Flags.string({
41
+ char: 's',
42
+ default: 'master',
43
+ description: 'Source branch to merge from'
44
+ }),
45
+ verbose: Flags.boolean({
46
+ char: 'v',
47
+ default: false,
48
+ description: 'Show detailed progress information'
49
+ })
50
+ };
51
+ async run() {
52
+ const startTime = Date.now();
53
+ const { flags } = await this.parse(Sync);
54
+ // Validate arguments
55
+ if (!flags.all && (!flags.branch || flags.branch.length === 0)) {
56
+ this.error('Either specify branches with --branch or use --all flag', {
57
+ suggestions: [
58
+ 'Use --all to sync all branches: hd git sync --all',
59
+ 'Specify one or more branches: hd git sync --branch feature-1 --branch feature-2',
60
+ 'Specify a single branch: hd git sync --branch feature-branch'
61
+ ]
62
+ });
63
+ }
64
+ if (flags.all && flags.branch && flags.branch.length > 0) {
65
+ this.error('Cannot specify both --branch and --all flag', {
66
+ suggestions: [
67
+ 'Use only --all: hd git sync --all',
68
+ 'Use only branch names: hd git sync --branch feature-1 --branch feature-2'
69
+ ]
70
+ });
71
+ }
72
+ const syncOptions = {
73
+ all: flags.all,
74
+ mergeStrategy: flags['merge-strategy'],
75
+ remote: flags.remote,
76
+ sourceBranch: flags['source-branch'],
77
+ targetBranches: flags.branch,
78
+ verbose: flags.verbose
79
+ };
80
+ // Display configuration
81
+ this.displayConfiguration(syncOptions);
82
+ // Initialize git service
83
+ const gitService = new GitService();
84
+ let spinner;
85
+ try {
86
+ // Start operation with spinner
87
+ if (flags.verbose) {
88
+ this.log(chalk.blue('🚀 Initializing git service...'));
89
+ }
90
+ spinner = ora.default({
91
+ color: 'blue',
92
+ spinner: 'dots',
93
+ text: 'Starting branch sync operation...'
94
+ }).start();
95
+ if (flags.verbose) {
96
+ spinner.text = 'Creating temporary workspace...';
97
+ }
98
+ // Execute sync operation
99
+ const results = await gitService.syncBranches(syncOptions, (emoji, color, step) => {
100
+ if (spinner) {
101
+ spinner.text = `${emoji} ${step}`;
102
+ }
103
+ if (flags.verbose) {
104
+ // Use chalk to apply the color to the step text
105
+ const coloredStep = color === 'blue' ? chalk.blue(step) :
106
+ color === 'cyan' ? chalk.cyan(step) :
107
+ color === 'yellow' ? chalk.yellow(step) :
108
+ color === 'magenta' ? chalk.magenta(step) :
109
+ color === 'green' ? chalk.green(step) :
110
+ color === 'red' ? chalk.red(step) :
111
+ color === 'gray' ? chalk.gray(step) :
112
+ step;
113
+ this.log(`${emoji} ${coloredStep}`);
114
+ }
115
+ });
116
+ spinner.succeed(chalk.green('Sync operation completed!'));
117
+ // Display results
118
+ this.displayResults(results, this.formatDuration(startTime));
119
+ }
120
+ catch (error) {
121
+ if (spinner) {
122
+ spinner.fail(chalk.red('Sync operation failed'));
123
+ }
124
+ this.error(chalk.red(`Failed to sync branches: ${error instanceof Error ? error.message : String(error)}`), {
125
+ suggestions: [
126
+ 'Check that you are in a git repository',
127
+ 'Verify remote repository access',
128
+ 'Ensure git is installed and configured'
129
+ ]
130
+ });
131
+ }
132
+ }
133
+ displayConfiguration(syncOptions) {
134
+ ux.styledHeader('🔧 Sync Configuration');
135
+ const configTable = {
136
+ 'Merge Strategy': chalk.cyan(syncOptions.mergeStrategy),
137
+ 'Mode': syncOptions.all
138
+ ? chalk.yellow('Sync all remote branches')
139
+ : chalk.yellow(`Sync specific branches: ${syncOptions.targetBranches?.join(', ')}`),
140
+ 'Remote': chalk.cyan(syncOptions.remote),
141
+ 'Source Branch': chalk.cyan(syncOptions.sourceBranch)
142
+ };
143
+ Object.entries(configTable).forEach(([key, value]) => {
144
+ this.log(`${chalk.gray('â€ĸ')} ${chalk.bold(key)}: ${value}`);
145
+ });
146
+ this.log(); // Empty line for spacing
147
+ }
148
+ displayResults(results, duration) {
149
+ this.log(); // Empty line for spacing
150
+ ux.styledHeader('📊 Sync Results');
151
+ // Count results by type
152
+ const successCount = results.filter(r => r.success).length;
153
+ const conflictCount = results.filter(r => r.conflicts).length;
154
+ const errorCount = results.filter(r => !r.success && !r.conflicts).length;
155
+ // Display summary statistics
156
+ const summaryData = [
157
+ { metric: 'Total Branches', status: 'info', value: results.length.toString() },
158
+ { metric: 'Successful', status: 'success', value: successCount.toString() },
159
+ { metric: 'Conflicts', status: 'warning', value: conflictCount.toString() },
160
+ { metric: 'Errors', status: 'error', value: errorCount.toString() },
161
+ { metric: 'Duration', status: 'info', value: duration }
162
+ ];
163
+ ux.table(summaryData, {
164
+ metric: { header: 'Metric' },
165
+ status: {
166
+ get: (row) => {
167
+ switch (row.status) {
168
+ case 'success': return chalk.green('✅');
169
+ case 'warning': return chalk.yellow('âš ī¸');
170
+ case 'error': return chalk.red('❌');
171
+ default: return chalk.blue('â„šī¸');
172
+ }
173
+ },
174
+ header: 'Status'
175
+ },
176
+ value: { header: 'Count' }
177
+ }, { 'no-truncate': true });
178
+ if (results.length > 0) {
179
+ this.log(); // Empty line for spacing
180
+ ux.styledHeader('📋 Branch Details');
181
+ // Convert results to proper table format
182
+ const tableData = results.map(result => ({
183
+ branch: result.branch,
184
+ conflicts: result.conflicts,
185
+ error: result.error,
186
+ success: result.success
187
+ }));
188
+ // Display detailed results
189
+ ux.table(tableData, {
190
+ branch: {
191
+ get: (row) => chalk.cyan(row.branch),
192
+ header: 'Branch'
193
+ },
194
+ message: {
195
+ get: (row) => {
196
+ if (row.success)
197
+ return chalk.gray('Successfully merged and pushed');
198
+ if (row.conflicts)
199
+ return chalk.yellow('Merge conflicts detected - manual resolution required');
200
+ return chalk.red(row.error || 'Unknown error');
201
+ },
202
+ header: 'Message'
203
+ },
204
+ status: {
205
+ get: (row) => {
206
+ if (row.success)
207
+ return chalk.green('✅ Synced');
208
+ if (row.conflicts)
209
+ return chalk.yellow('âš ī¸ Conflicts');
210
+ return chalk.red('❌ Failed');
211
+ },
212
+ header: 'Status'
213
+ }
214
+ }, { 'no-truncate': true });
215
+ }
216
+ // Display actionable insights
217
+ this.log(); // Empty line for spacing
218
+ if (conflictCount > 0) {
219
+ ux.warn(`${conflictCount} branch(es) have merge conflicts and need manual resolution`);
220
+ this.log(chalk.gray(' 💡 Tip: Resolve conflicts manually and push the changes'));
221
+ }
222
+ if (errorCount > 0) {
223
+ ux.warn(`${errorCount} branch(es) failed to sync`);
224
+ this.log(chalk.gray(' 💡 Tip: Check branch permissions and network connectivity'));
225
+ }
226
+ if (successCount === results.length && results.length > 0) {
227
+ ux.info(chalk.green('🎉 All branches synced successfully!'));
228
+ }
229
+ }
230
+ formatDuration(startTime) {
231
+ const duration = Date.now() - startTime;
232
+ const seconds = Math.round(duration / 1000);
233
+ return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
234
+ }
235
+ }