@chabokan.net/cli 0.8.15 → 0.9.1

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 (54) hide show
  1. package/README.md +520 -66
  2. package/dist/base.d.ts +30 -7
  3. package/dist/base.js +163 -14
  4. package/dist/commands/account/info.d.ts +12 -0
  5. package/dist/commands/account/info.js +40 -0
  6. package/dist/commands/account/list.d.ts +5 -1
  7. package/dist/commands/account/list.js +29 -19
  8. package/dist/commands/account/remove.d.ts +5 -1
  9. package/dist/commands/account/remove.js +23 -12
  10. package/dist/commands/account/use.d.ts +6 -2
  11. package/dist/commands/account/use.js +22 -11
  12. package/dist/commands/cloudserver/create.d.ts +40 -0
  13. package/dist/commands/cloudserver/create.js +242 -0
  14. package/dist/commands/cloudserver/delete.d.ts +14 -0
  15. package/dist/commands/cloudserver/delete.js +65 -0
  16. package/dist/commands/cloudserver/list.d.ts +12 -0
  17. package/dist/commands/cloudserver/list.js +46 -0
  18. package/dist/commands/cloudserver/restart.d.ts +13 -0
  19. package/dist/commands/cloudserver/restart.js +51 -0
  20. package/dist/commands/cloudserver/start.d.ts +13 -0
  21. package/dist/commands/cloudserver/start.js +51 -0
  22. package/dist/commands/cloudserver/stop.d.ts +13 -0
  23. package/dist/commands/cloudserver/stop.js +52 -0
  24. package/dist/commands/deploy.d.ts +13 -3
  25. package/dist/commands/deploy.js +96 -60
  26. package/dist/commands/login.d.ts +8 -4
  27. package/dist/commands/login.js +69 -41
  28. package/dist/commands/service/domain/add.d.ts +15 -0
  29. package/dist/commands/service/domain/add.js +74 -0
  30. package/dist/commands/service/domain/remove.d.ts +15 -0
  31. package/dist/commands/service/domain/remove.js +72 -0
  32. package/dist/commands/service/list.d.ts +5 -1
  33. package/dist/commands/service/list.js +29 -21
  34. package/dist/commands/service/logs.d.ts +6 -2
  35. package/dist/commands/service/logs.js +33 -30
  36. package/dist/commands/service/resize.d.ts +9 -5
  37. package/dist/commands/service/resize.js +73 -69
  38. package/dist/commands/service/restart.d.ts +6 -2
  39. package/dist/commands/service/restart.js +28 -32
  40. package/dist/commands/service/start.d.ts +6 -2
  41. package/dist/commands/service/start.js +29 -31
  42. package/dist/commands/service/stop.d.ts +6 -2
  43. package/dist/commands/service/stop.js +29 -31
  44. package/dist/commands/wallet/list.d.ts +12 -0
  45. package/dist/commands/wallet/list.js +41 -0
  46. package/dist/constants.d.ts +2 -0
  47. package/dist/constants.js +7 -2
  48. package/dist/helper.d.ts +23 -7
  49. package/dist/helper.js +294 -113
  50. package/dist/types.d.ts +28 -8
  51. package/dist/ui.d.ts +23 -0
  52. package/dist/ui.js +70 -0
  53. package/oclif.manifest.json +635 -25
  54. package/package.json +39 -35
@@ -1,44 +1,52 @@
1
1
  import Command from "../../base.js";
2
- import { ux } from "@oclif/core";
3
- import chalk from "chalk";
4
- import { isEmptyObject, handleApiError, logErrorDetails } from "../../helper.js";
2
+ import { printTable } from "@oclif/table";
3
+ import * as ui from "../../ui.js";
4
+ import { handleApiError, logErrorDetails } from "../../helper.js";
5
5
  export default class ServiceList extends Command {
6
- static description = "show account services list";
6
+ static description = "list the services on your account";
7
+ static examples = [
8
+ {
9
+ description: 'List every service on the active account',
10
+ command: '<%= config.bin %> service list',
11
+ },
12
+ {
13
+ description: 'Switch account first, then list that account’s services',
14
+ command: '<%= config.bin %> account use -u me@example.com && <%= config.bin %> service list',
15
+ },
16
+ ];
7
17
  static flags = {
8
18
  ...Command.flags,
9
19
  };
10
20
  async run() {
11
- const { flags } = await this.parse(ServiceList);
21
+ await this.parse(ServiceList);
12
22
  const cli = this;
13
23
  try {
14
24
  await this.init_run();
15
- const config_json = await this.read_config();
16
- if (isEmptyObject(config_json.users)) {
17
- cli.log(`${chalk.red('[Error]')} Please login first using 'chabok login'.`);
25
+ if (!(await this.require_login())) {
18
26
  return;
19
27
  }
20
28
  const all_services = await this.get_services();
21
- if (all_services.length > 0) {
22
- const services_data = all_services.map((service) => {
23
- return {
24
- Name: service.name,
25
- };
26
- });
27
- ux.table(services_data, {
28
- Name: {},
29
- }, flags);
30
- }
31
- else {
32
- cli.log(`${chalk.yellow('[Info]')} No services found. Please create a service first.`);
29
+ if (all_services.length === 0) {
30
+ cli.log(ui.info('You have no services yet.'));
31
+ cli.log(ui.hint('Create one at https://hub.chabokan.net, then come back here'));
33
32
  return;
34
33
  }
34
+ const services_data = all_services.map((service) => ({
35
+ Service: service.value,
36
+ Platform: service.platform,
37
+ }));
38
+ printTable({
39
+ data: services_data,
40
+ columns: ["Service", "Platform"],
41
+ });
42
+ cli.log(ui.hint(`Act on one with ${ui.cmd('chabok service logs -s <name>')}, ${ui.cmd('restart')}, ${ui.cmd('stop')} …`));
35
43
  }
36
44
  catch (error) {
37
45
  const errorInfo = handleApiError(error, 'Failed to fetch services list.', {
38
46
  endpoint: 'services/',
39
47
  operation: 'List Services'
40
48
  });
41
- cli.log(`${chalk.red('[Error]')} ${errorInfo.message}`);
49
+ cli.log(ui.error(errorInfo.message));
42
50
  logErrorDetails(errorInfo, cli);
43
51
  }
44
52
  }
@@ -1,9 +1,13 @@
1
1
  import Command from "../../base.js";
2
2
  export default class ServiceLogs extends Command {
3
3
  static description: string;
4
+ static examples: {
5
+ description: string;
6
+ command: string;
7
+ }[];
4
8
  static flags: {
5
- service: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
- help: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<void>;
9
+ service: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
7
11
  };
8
12
  run(): Promise<void>;
9
13
  send_request(cli: Command, selected_service: string): Promise<void>;
@@ -1,53 +1,55 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import Command from "../../base.js";
3
- import { isEmptyObject, handleApiError, logErrorDetails } from "../../helper.js";
4
- import chalk from "chalk";
5
- import inquirer from 'inquirer';
3
+ import { handleApiError, logErrorDetails } from "../../helper.js";
4
+ import * as ui from "../../ui.js";
6
5
  import axios from "axios";
7
6
  export default class ServiceLogs extends Command {
8
- static description = 'read latest logs from service';
7
+ static description = 'read the latest logs from a service';
8
+ static examples = [
9
+ {
10
+ description: 'Pick a service from an interactive list',
11
+ command: '<%= config.bin %> service logs',
12
+ },
13
+ {
14
+ description: 'Read logs for a specific service',
15
+ command: '<%= config.bin %> service logs --service my-app',
16
+ },
17
+ {
18
+ description: 'Search the logs for errors',
19
+ command: '<%= config.bin %> service logs -s my-app | grep -i error',
20
+ },
21
+ {
22
+ description: 'Save the logs to a file',
23
+ command: '<%= config.bin %> service logs -s my-app > my-app.log',
24
+ },
25
+ ];
9
26
  static flags = {
10
27
  ...Command.flags,
11
- service: Flags.string({ char: 's', description: 'service name' }),
28
+ service: Flags.string({ char: 's', description: 'name of the service to read logs from' }),
12
29
  };
13
30
  async run() {
14
31
  const { flags } = await this.parse(ServiceLogs);
15
32
  const cli = this;
16
33
  await this.init_run();
17
- const config_json = await this.read_config();
18
- let selected_service = flags.service;
19
- if (isEmptyObject(config_json.users)) {
20
- cli.log(`${chalk.red('[Error]')} first you should login!`);
34
+ if (!(await this.require_login())) {
21
35
  return;
22
36
  }
23
- if (!flags.service) {
24
- const all_services = await this.get_services();
25
- if (all_services.length > 0) {
26
- const { service } = await inquirer.prompt({
27
- type: 'list',
28
- message: 'Please select a service:',
29
- name: 'service',
30
- choices: all_services
31
- });
32
- selected_service = service;
33
- }
34
- else {
35
- cli.log("first you should create service");
36
- return;
37
- }
38
- }
39
- if (selected_service) {
40
- await this.send_request(cli, selected_service);
37
+ const selected_service = await this.select_service(flags.service, {}, 'Fetch Logs');
38
+ if (!selected_service) {
39
+ return;
41
40
  }
41
+ await this.send_request(cli, selected_service);
42
42
  }
43
43
  async send_request(cli, selected_service) {
44
44
  try {
45
45
  const { data } = await axios.get(`services/${selected_service}/logs/`, this.axiosConfig);
46
46
  if (data.success && data.logs) {
47
+ // Logs go out verbatim so they stay pipeable into grep, tee and friends.
47
48
  cli.log(data.logs);
48
49
  }
49
50
  else {
50
- cli.log(`${chalk.yellow('[Warning]')} No logs available for service '${selected_service}'. The service may not have generated any logs yet.`);
51
+ cli.log(ui.info(`No logs yet for ${ui.value(selected_service)}.`));
52
+ cli.log(ui.hint('A service that has just started may take a moment to produce output'));
51
53
  }
52
54
  }
53
55
  catch (error) {
@@ -57,10 +59,11 @@ export default class ServiceLogs extends Command {
57
59
  operation: 'Fetch Logs'
58
60
  });
59
61
  if (errorInfo.status === 404) {
60
- cli.log(`${chalk.red('[Error]')} Service '${selected_service}' not found. Please verify the service name using 'chabok service list' and try again.`);
62
+ cli.log(ui.error(`Service ${ui.value(selected_service)} was not found.`));
63
+ cli.log(ui.hint(`Check the available names with ${ui.cmd('chabok service list')}`));
61
64
  }
62
65
  else {
63
- cli.log(`${chalk.red('[Error]')} ${errorInfo.message}`);
66
+ cli.log(ui.error(errorInfo.message));
64
67
  }
65
68
  logErrorDetails(errorInfo, cli);
66
69
  }
@@ -1,12 +1,16 @@
1
1
  import Command from "../../base.js";
2
2
  export default class ServiceResize extends Command {
3
3
  static description: string;
4
+ static examples: {
5
+ description: string;
6
+ command: string;
7
+ }[];
4
8
  static flags: {
5
- service: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
- ram: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
7
- cpu: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
- disk: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
- help: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<void>;
9
+ service: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ ram: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ cpu: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ disk: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
10
14
  };
11
15
  run(): Promise<void>;
12
16
  send_request(cli: Command, selected_service: string, ram: string, cpu: string, disk: string): Promise<void>;
@@ -1,130 +1,132 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import Command from "../../base.js";
3
- import { isEmptyObject, handleApiError, logErrorDetails } from "../../helper.js";
4
- import chalk from "chalk";
3
+ import { handleApiError, logErrorDetails } from "../../helper.js";
4
+ import * as ui from "../../ui.js";
5
5
  import inquirer from 'inquirer';
6
6
  import axios from "axios";
7
7
  export default class ServiceResize extends Command {
8
- static description = 'resize a service';
8
+ static description = 'change the RAM, CPU and disk allocated to a service';
9
+ static examples = [
10
+ {
11
+ description: 'Choose the service and every resource interactively',
12
+ command: '<%= config.bin %> service resize',
13
+ },
14
+ {
15
+ description: 'Resize a service in one non-interactive command',
16
+ command: '<%= config.bin %> service resize -s my-app --ram 2 --cpu 1 --disk 10',
17
+ },
18
+ {
19
+ description: 'Set only the RAM and pick the rest from the prompts',
20
+ command: '<%= config.bin %> service resize -s my-app --ram 4',
21
+ },
22
+ ];
9
23
  static flags = {
10
24
  ...Command.flags,
11
- service: Flags.string({ char: 's', description: 'service name' }),
12
- ram: Flags.string({ char: 'r', description: 'RAM' }),
13
- cpu: Flags.string({ char: 'c', description: 'CPU' }),
14
- disk: Flags.string({ char: 'd', description: 'DISK' }),
25
+ service: Flags.string({ char: 's', description: 'name of the service to resize' }),
26
+ ram: Flags.string({ char: 'r', description: 'RAM in GB, in steps of 0.5 (e.g. 0.5, 1, 2)' }),
27
+ cpu: Flags.string({ char: 'c', description: 'CPU cores, in steps of 0.5 (e.g. 0.5, 1, 2)' }),
28
+ disk: Flags.string({ char: 'd', description: 'disk in GB, in steps of 5 (e.g. 5, 10, 30)' }),
15
29
  };
16
30
  async run() {
17
31
  const { flags } = await this.parse(ServiceResize);
18
32
  const cli = this;
19
33
  await this.init_run();
20
- const config_json = await this.read_config();
21
- let selected_service = flags.service;
22
34
  let selected_ram = flags.ram;
23
35
  let selected_cpu = flags.cpu;
24
36
  let selected_disk = flags.disk;
25
- if (isEmptyObject(config_json.users)) {
26
- cli.log(`${chalk.red('[Error]')} first you should login!`);
37
+ if (!(await this.require_login())) {
27
38
  return;
28
39
  }
40
+ const selected_service = await this.select_service(flags.service, { 'not_status': 'pending', 'has_custom_plan': 'true' }, 'Resize Service');
29
41
  if (!selected_service) {
30
- const all_services = await this.get_services({ 'not_status': 'pending', 'has_custom_plan': 'true' });
31
- if (all_services && all_services.length > 0) {
32
- const { service } = await inquirer.prompt({
33
- type: 'list',
34
- message: 'Please select a service:',
35
- name: 'service',
36
- choices: all_services
37
- });
38
- selected_service = service;
39
- }
40
- else {
41
- cli.log("No services available for resize.");
42
- return;
43
- }
42
+ return;
44
43
  }
45
44
  if (!selected_ram) {
46
45
  const { ram } = await inquirer.prompt({
47
- type: 'list',
48
- message: 'Please select service ram:',
46
+ type: 'select',
47
+ message: 'RAM:',
49
48
  name: 'ram',
50
49
  choices: [
51
- { value: "0.5", name: "0.5G" },
52
- { value: "1", name: "1G" },
53
- { value: "2", name: "2G" },
54
- { value: "4", name: "4G" },
55
- { value: "6", name: "6G" },
56
- { value: "8", name: "8G" },
50
+ { value: "0.5", name: "0.5 GB" },
51
+ { value: "1", name: "1 GB" },
52
+ { value: "2", name: "2 GB" },
53
+ { value: "4", name: "4 GB" },
54
+ { value: "6", name: "6 GB" },
55
+ { value: "8", name: "8 GB" },
57
56
  ]
58
57
  });
59
58
  selected_ram = ram;
60
59
  }
61
60
  if (!selected_cpu) {
62
61
  const { cpu } = await inquirer.prompt({
63
- type: 'list',
64
- message: 'Please select service cpu:',
62
+ type: 'select',
63
+ message: 'CPU:',
65
64
  name: 'cpu',
66
65
  choices: [
67
- { value: "0.5", name: "0.5 Core" },
68
- { value: "1", name: "1 Core" },
69
- { value: "2", name: "2 Core" },
70
- { value: "3", name: "3 Core" },
71
- { value: "4", name: "4 Core" },
66
+ { value: "0.5", name: "0.5 core" },
67
+ { value: "1", name: "1 core" },
68
+ { value: "2", name: "2 cores" },
69
+ { value: "3", name: "3 cores" },
70
+ { value: "4", name: "4 cores" },
72
71
  ]
73
72
  });
74
73
  selected_cpu = cpu;
75
74
  }
76
75
  if (!selected_disk) {
77
76
  const { disk } = await inquirer.prompt({
78
- type: 'list',
79
- message: 'Please select service disk:',
77
+ type: 'select',
78
+ message: 'Disk:',
80
79
  name: 'disk',
81
80
  choices: [
82
- { value: "5", name: "5G" },
83
- { value: "10", name: "10G" },
84
- { value: "15", name: "15G" },
85
- { value: "30", name: "30G" },
86
- { value: "40", name: "40G" },
87
- { value: "50", name: "50G" },
81
+ { value: "5", name: "5 GB" },
82
+ { value: "10", name: "10 GB" },
83
+ { value: "15", name: "15 GB" },
84
+ { value: "30", name: "30 GB" },
85
+ { value: "40", name: "40 GB" },
86
+ { value: "50", name: "50 GB" },
88
87
  ]
89
88
  });
90
89
  selected_disk = disk;
91
90
  }
92
- if (!selected_service || !selected_ram || !selected_cpu || !selected_disk) {
93
- cli.log(`${chalk.red('[Error]')} All parameters are required.`);
91
+ if (!selected_ram || !selected_cpu || !selected_disk) {
92
+ cli.log(ui.error('RAM, CPU and disk are all required.'));
94
93
  return;
95
94
  }
96
95
  let wrong_value = false;
97
- const ramNum = parseFloat(selected_ram);
98
- const cpuNum = parseFloat(selected_cpu);
99
- const diskNum = parseFloat(selected_disk);
100
- if (isNaN(ramNum) || ramNum % 0.5 !== 0) {
101
- cli.log(`${chalk.red('[Error]')} RAM amount should be a multiple of 0.5`);
96
+ const ramNum = Number.parseFloat(selected_ram);
97
+ const cpuNum = Number.parseFloat(selected_cpu);
98
+ const diskNum = Number.parseFloat(selected_disk);
99
+ if (Number.isNaN(ramNum) || ramNum % 0.5 !== 0) {
100
+ cli.log(ui.error(`RAM must be a multiple of 0.5 GB, got ${ui.value(selected_ram)}.`));
102
101
  wrong_value = true;
103
102
  }
104
- if (isNaN(cpuNum) || cpuNum % 0.5 !== 0) {
105
- cli.log(`${chalk.red('[Error]')} CPU amount should be a multiple of 0.5`);
103
+ if (Number.isNaN(cpuNum) || cpuNum % 0.5 !== 0) {
104
+ cli.log(ui.error(`CPU must be a multiple of 0.5 cores, got ${ui.value(selected_cpu)}.`));
106
105
  wrong_value = true;
107
106
  }
108
- if (isNaN(diskNum) || diskNum % 5 !== 0) {
109
- cli.log(`${chalk.red('[Error]')} Disk amount should be a multiple of 5`);
107
+ if (Number.isNaN(diskNum) || diskNum % 5 !== 0) {
108
+ cli.log(ui.error(`Disk must be a multiple of 5 GB, got ${ui.value(selected_disk)}.`));
110
109
  wrong_value = true;
111
110
  }
112
- if (!wrong_value) {
113
- await this.send_request(cli, selected_service, selected_ram, selected_cpu, selected_disk);
111
+ if (wrong_value) {
112
+ cli.log(ui.hint(`Example: ${ui.cmd(`chabok service resize -s ${selected_service} --ram 2 --cpu 1 --disk 10`)}`));
113
+ return;
114
114
  }
115
+ await this.send_request(cli, selected_service, selected_ram, selected_cpu, selected_disk);
115
116
  }
116
117
  async send_request(cli, selected_service, ram, cpu, disk) {
117
118
  try {
118
119
  const { data } = await axios.post(`services/${selected_service}/resize/`, {
119
- ram: ram,
120
- cpu: cpu,
121
- disk: disk,
120
+ ram,
121
+ cpu,
122
+ disk,
122
123
  }, this.axiosConfig);
123
124
  if (data.success) {
124
- cli.log(`${chalk.green('[Success]')} Service '${selected_service}' resized successfully (RAM: ${ram}G, CPU: ${cpu} cores, Disk: ${disk}G).`);
125
+ cli.log(ui.success(`Service ${ui.value(selected_service)} resized to ${ui.value(`${ram} GB RAM`)}, ${ui.value(`${cpu} CPU`)}, ${ui.value(`${disk} GB disk`)}.`));
126
+ cli.log(ui.hint(`Restart it to apply the new limits: ${ui.cmd(`chabok service restart -s ${selected_service}`)}`));
125
127
  }
126
128
  else {
127
- cli.log(`${chalk.red('[Error]')} Failed to resize service '${selected_service}'. ${data.message || 'Please verify the resource values and try again.'}`);
129
+ cli.log(ui.error(`Could not resize ${ui.value(selected_service)}. ${data.message || 'Check the resource values and try again.'}`));
128
130
  }
129
131
  }
130
132
  catch (error) {
@@ -134,13 +136,15 @@ export default class ServiceResize extends Command {
134
136
  operation: 'Resize Service'
135
137
  });
136
138
  if (errorInfo.status === 404) {
137
- cli.log(`${chalk.red('[Error]')} Service '${selected_service}' not found. Please verify the service name using 'chabok service list' and try again.`);
139
+ cli.log(ui.error(`Service ${ui.value(selected_service)} was not found.`));
140
+ cli.log(ui.hint(`Check the available names with ${ui.cmd('chabok service list')}`));
138
141
  }
139
142
  else if (errorInfo.status === 400 || errorInfo.status === 422) {
140
- cli.log(`${chalk.red('[Error]')} Invalid resize parameters: ${errorInfo.message}. Please check that RAM is a multiple of 0.5, CPU is a multiple of 0.5, and Disk is a multiple of 5.`);
143
+ cli.log(ui.error(errorInfo.message));
144
+ cli.log(ui.hint('RAM and CPU go in steps of 0.5; disk goes in steps of 5'));
141
145
  }
142
146
  else {
143
- cli.log(`${chalk.red('[Error]')} ${errorInfo.message}`);
147
+ cli.log(ui.error(errorInfo.message));
144
148
  }
145
149
  logErrorDetails(errorInfo, cli);
146
150
  }
@@ -1,9 +1,13 @@
1
1
  import Command from "../../base.js";
2
2
  export default class ServiceRestart extends Command {
3
3
  static description: string;
4
+ static examples: {
5
+ description: string;
6
+ command: string;
7
+ }[];
4
8
  static flags: {
5
- service: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
- help: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<void>;
9
+ service: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
7
11
  };
8
12
  run(): Promise<void>;
9
13
  send_request(cli: Command, selected_service: string): Promise<void>;
@@ -1,55 +1,50 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import Command from "../../base.js";
3
- import { isEmptyObject, handleApiError, logErrorDetails } from "../../helper.js";
4
- import chalk from "chalk";
5
- import inquirer from "inquirer";
3
+ import { handleApiError, logErrorDetails } from "../../helper.js";
4
+ import * as ui from "../../ui.js";
6
5
  import axios from "axios";
7
6
  export default class ServiceRestart extends Command {
8
7
  static description = "restart a service";
8
+ static examples = [
9
+ {
10
+ description: 'Pick a service from an interactive list',
11
+ command: '<%= config.bin %> service restart',
12
+ },
13
+ {
14
+ description: 'Restart a specific service by name',
15
+ command: '<%= config.bin %> service restart --service my-app',
16
+ },
17
+ {
18
+ description: 'Restart, then tail the logs to confirm it came back up',
19
+ command: '<%= config.bin %> service restart -s my-app && <%= config.bin %> service logs -s my-app',
20
+ },
21
+ ];
9
22
  static flags = {
10
23
  ...Command.flags,
11
- service: Flags.string({ char: "s", description: "service name" }),
24
+ service: Flags.string({ char: "s", description: "name of the service to restart" }),
12
25
  };
13
26
  async run() {
14
27
  const { flags } = await this.parse(ServiceRestart);
15
28
  const cli = this;
16
29
  await this.init_run();
17
- const config_json = await this.read_config();
18
- let selected_service = flags.service;
19
- if (isEmptyObject(config_json.users)) {
20
- cli.log(`${chalk.red("[Error]")} first you should login!`);
30
+ if (!(await this.require_login())) {
21
31
  return;
22
32
  }
23
- if (!flags.service) {
24
- const all_services = await this.get_services({
25
- not_status: "pending",
26
- });
27
- if (all_services && all_services.length > 0) {
28
- const { service } = await inquirer.prompt({
29
- type: "list",
30
- message: "Please select a service:",
31
- name: "service",
32
- choices: all_services,
33
- });
34
- selected_service = service;
35
- }
36
- else {
37
- cli.log("No services available.");
38
- return;
39
- }
40
- }
41
- if (selected_service) {
42
- await this.send_request(cli, selected_service);
33
+ const selected_service = await this.select_service(flags.service, { not_status: "pending" }, "Restart Service");
34
+ if (!selected_service) {
35
+ return;
43
36
  }
37
+ await this.send_request(cli, selected_service);
44
38
  }
45
39
  async send_request(cli, selected_service) {
46
40
  try {
47
41
  const { data } = await axios.get(`services/${selected_service}/restart/`, this.axiosConfig);
48
42
  if (data.success) {
49
- cli.log(`${chalk.green("[Success]")} Service '${selected_service}' restarted successfully.`);
43
+ cli.log(ui.success(`Service ${ui.value(selected_service)} is restarting.`));
44
+ cli.log(ui.hint(`Follow its output with ${ui.cmd(`chabok service logs -s ${selected_service}`)}`));
50
45
  }
51
46
  else {
52
- cli.log(`${chalk.red("[Error]")} Failed to restart service '${selected_service}'. ${data.message || 'Please try again later.'}`);
47
+ cli.log(ui.error(`Could not restart ${ui.value(selected_service)}. ${data.message || 'Please try again in a moment.'}`));
53
48
  }
54
49
  }
55
50
  catch (error) {
@@ -59,10 +54,11 @@ export default class ServiceRestart extends Command {
59
54
  operation: 'Restart Service'
60
55
  });
61
56
  if (errorInfo.status === 404) {
62
- cli.log(`${chalk.red("[Error]")} Service '${selected_service}' not found. Please verify the service name using 'chabok service list' and try again.`);
57
+ cli.log(ui.error(`Service ${ui.value(selected_service)} was not found.`));
58
+ cli.log(ui.hint(`Check the available names with ${ui.cmd('chabok service list')}`));
63
59
  }
64
60
  else {
65
- cli.log(`${chalk.red("[Error]")} ${errorInfo.message}`);
61
+ cli.log(ui.error(errorInfo.message));
66
62
  }
67
63
  logErrorDetails(errorInfo, cli);
68
64
  }
@@ -1,9 +1,13 @@
1
1
  import Command from "../../base.js";
2
2
  export default class ServiceStart extends Command {
3
3
  static description: string;
4
+ static examples: {
5
+ description: string;
6
+ command: string;
7
+ }[];
4
8
  static flags: {
5
- service: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
6
- help: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<void>;
9
+ service: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
7
11
  };
8
12
  run(): Promise<void>;
9
13
  send_request(cli: Command, selected_service: string): Promise<void>;