@constellation-network/node-pilot 0.0.7 → 0.0.8

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 (41) hide show
  1. package/README.md +14 -13
  2. package/dist/checks/check-dependencies.d.ts +1 -0
  3. package/dist/checks/check-dependencies.js +44 -0
  4. package/dist/checks/check-initial-setup.js +6 -4
  5. package/dist/checks/check-network.d.ts +1 -0
  6. package/dist/checks/check-network.js +48 -0
  7. package/dist/checks/check-node-ctl.d.ts +5 -0
  8. package/dist/checks/check-node-ctl.js +88 -0
  9. package/dist/checks/check-project.js +22 -7
  10. package/dist/clm.js +1 -1
  11. package/dist/commands/logs.d.ts +1 -0
  12. package/dist/commands/logs.js +5 -3
  13. package/dist/commands/status.js +4 -0
  14. package/dist/commands/test.d.ts +1 -0
  15. package/dist/commands/test.js +27 -5
  16. package/dist/config-store.d.ts +8 -5
  17. package/dist/config-store.js +10 -0
  18. package/dist/helpers/docker-helper.js +18 -5
  19. package/dist/helpers/key-file-helper.js +1 -1
  20. package/dist/helpers/project-helper.d.ts +1 -0
  21. package/dist/helpers/project-helper.js +52 -0
  22. package/dist/helpers/prompt-helper.d.ts +0 -1
  23. package/dist/helpers/prompt-helper.js +0 -51
  24. package/dist/services/cluster-service.d.ts +2 -1
  25. package/dist/services/cluster-service.js +10 -0
  26. package/dist/services/fastforward-service.js +9 -3
  27. package/dist/services/get-random-node.d.ts +2 -0
  28. package/dist/services/get-random-node.js +16 -0
  29. package/dist/services/node-service.d.ts +4 -0
  30. package/dist/services/node-service.js +15 -0
  31. package/dist/services/shell-service.d.ts +3 -1
  32. package/dist/services/shell-service.js +32 -6
  33. package/dist/types.d.ts +36 -3
  34. package/install-dependencies.sh +100 -0
  35. package/oclif.manifest.json +9 -1
  36. package/package.json +5 -2
  37. package/projects/hypergraph/networks/integrationnet.env +16 -8
  38. package/projects/hypergraph/networks/mainnet.env +16 -7
  39. package/projects/hypergraph/networks/testnet.env +16 -8
  40. package/projects/hypergraph/scripts/install-dependencies.sh +3 -3
  41. package/projects/hypergraph/scripts/install.sh +4 -6
package/README.md CHANGED
@@ -11,7 +11,7 @@ A new CLI generated with oclif
11
11
 
12
12
  <!-- toc -->
13
13
  * [Usage](#usage)
14
- * [The TLDR Version](#the-tldr-version)
14
+ * [The TL;DR Version](#the-tldr-version)
15
15
  * [Commands](#commands)
16
16
  <!-- tocstop -->
17
17
  # Usage
@@ -21,14 +21,14 @@ $ npm install -g @constellation-network/node-pilot
21
21
  $ cpilot COMMAND
22
22
  running command...
23
23
  $ cpilot (--version|-v)
24
- @constellation-network/node-pilot/0.0.7 darwin-arm64 node-v22.15.0
24
+ @constellation-network/node-pilot/0.0.8 darwin-arm64 node-v22.15.0
25
25
  $ cpilot --help [COMMAND]
26
26
  USAGE
27
27
  $ cpilot COMMAND
28
28
  ...
29
29
  ```
30
30
  <!-- usagestop -->
31
- # The TLDR Version
31
+ # The TL;DR Version
32
32
  #### Simply run cpilot with no commands.
33
33
  ```sh-session
34
34
  $ cpilot
@@ -62,7 +62,7 @@ EXAMPLES
62
62
  $ cpilot config
63
63
  ```
64
64
 
65
- _See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/config.ts)_
65
+ _See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config.ts)_
66
66
 
67
67
  ## `cpilot config get [NAME]`
68
68
 
@@ -86,7 +86,7 @@ EXAMPLES
86
86
  $ cpilot config get gl0:CL_PUBLIC_HTTP_PORT
87
87
  ```
88
88
 
89
- _See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/config/get.ts)_
89
+ _See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config/get.ts)_
90
90
 
91
91
  ## `cpilot config set NAME VALUE`
92
92
 
@@ -109,7 +109,7 @@ EXAMPLES
109
109
  $ cpilot config set gl0:CL_PUBLIC_HTTP_PORT 9000
110
110
  ```
111
111
 
112
- _See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/config/set.ts)_
112
+ _See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/config/set.ts)_
113
113
 
114
114
  ## `cpilot help [COMMAND]`
115
115
 
@@ -146,7 +146,7 @@ EXAMPLES
146
146
  $ cpilot info
147
147
  ```
148
148
 
149
- _See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/info.ts)_
149
+ _See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/info.ts)_
150
150
 
151
151
  ## `cpilot logs [LAYER]`
152
152
 
@@ -154,13 +154,14 @@ view validator node runtime logs
154
154
 
155
155
  ```
156
156
  USAGE
157
- $ cpilot logs [LAYER] [-f]
157
+ $ cpilot logs [LAYER] [-f] [-n <value>]
158
158
 
159
159
  ARGUMENTS
160
160
  LAYER network layer to view. e.g. gl0
161
161
 
162
162
  FLAGS
163
- -f, --follow continuously wait for additional data to be appended
163
+ -f, --follow continuously wait for additional data to be appended
164
+ -n, --numOfLines=<value> number of lines at the end of the log to display
164
165
 
165
166
  DESCRIPTION
166
167
  view validator node runtime logs
@@ -169,7 +170,7 @@ EXAMPLES
169
170
  $ cpilot logs
170
171
  ```
171
172
 
172
- _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/logs.ts)_
173
+ _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/logs.ts)_
173
174
 
174
175
  ## `cpilot restart`
175
176
 
@@ -186,7 +187,7 @@ EXAMPLES
186
187
  $ cpilot restart
187
188
  ```
188
189
 
189
- _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/restart.ts)_
190
+ _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/restart.ts)_
190
191
 
191
192
  ## `cpilot shutdown`
192
193
 
@@ -203,7 +204,7 @@ EXAMPLES
203
204
  $ cpilot shutdown
204
205
  ```
205
206
 
206
- _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/shutdown.ts)_
207
+ _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/shutdown.ts)_
207
208
 
208
209
  ## `cpilot status`
209
210
 
@@ -217,5 +218,5 @@ DESCRIPTION
217
218
  Display node status and configuration settings
218
219
  ```
219
220
 
220
- _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.7/src/commands/status.ts)_
221
+ _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.8/src/commands/status.ts)_
221
222
  <!-- commandsstop -->
@@ -0,0 +1 @@
1
+ export declare const checkDependencies: () => Promise<void>;
@@ -0,0 +1,44 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import shell from "shelljs";
5
+ import { clm } from "../clm.js";
6
+ import { promptHelper } from "../helpers/prompt-helper.js";
7
+ import { shellService } from "../services/shell-service.js";
8
+ export const checkDependencies = async () => {
9
+ const dockerComposeVersion = await shellService.runCommand('docker compose version').catch(() => '');
10
+ clm.debug(`Docker compose version check: ${dockerComposeVersion || 'NOT_INSTALLED'}`);
11
+ if (dockerComposeVersion) {
12
+ return;
13
+ }
14
+ const isDockerV1Installed = await shellService.checkCommandAvailable('docker-compose');
15
+ if (isDockerV1Installed) {
16
+ clm.warn('You are using docker-compose v1. It needs to be uninstalled before upgrading to the latest version.');
17
+ // await promptHelper.doYouWishToContinue();
18
+ clm.step('\nRun the following command to uninstall docker-compose v1 and then run cpilot again:');
19
+ clm.preStep('for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done');
20
+ clm.echo('');
21
+ process.exit(0);
22
+ }
23
+ const isDockerInstalled = await shellService.checkCommandAvailable('docker');
24
+ if (!isDockerInstalled) {
25
+ const pilotDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../..`);
26
+ if (fs.existsSync(path.join(pilotDir, 'install-dependencies.sh'))) {
27
+ // Skip prompt if already informed user of the upgrade
28
+ if (!isDockerV1Installed) {
29
+ clm.step('Docker is required and needs to be installed.');
30
+ await promptHelper.doYouWishToContinue();
31
+ }
32
+ clm.debug(`Running install-dependencies.sh from ${pilotDir}`);
33
+ const silent = !process.env.DEBUG;
34
+ const result = shell.exec('bash install-dependencies.sh', { cwd: pilotDir, silent });
35
+ if (result.code > 0) {
36
+ console.log(result.stderr);
37
+ clm.error(`Failed to install dependencies. Please try again after resolving any errors.`);
38
+ }
39
+ clm.postStep(`\nDocker has been installed. Please logout and login again to ensure the changes take effect. Then run cpilot again.`);
40
+ clm.echo('');
41
+ process.exit(0);
42
+ }
43
+ }
44
+ };
@@ -1,15 +1,17 @@
1
1
  import chalk from "chalk";
2
2
  import { configStore } from "../config-store.js";
3
+ import { checkDependencies } from "./check-dependencies.js";
3
4
  import { checkHardware } from "./check-hardware.js";
4
5
  export const checkInitialSetup = {
5
6
  async firstTimeRun() {
6
7
  if (configStore.getSystemInfo() !== null) {
7
8
  return;
8
9
  }
9
- console.log(chalk.white("\n ****************************************"));
10
- console.log(" " + chalk.white("CONSTELLATION NETWORK") + " ");
11
- console.log(" " + chalk.white("NODE PILOT") + " ");
12
- console.log(chalk.white(" ****************************************"));
10
+ await checkDependencies();
11
+ console.log(chalk.whiteBright("\n ****************************************"));
12
+ console.log(" " + chalk.whiteBright("CONSTELLATION NETWORK") + " ");
13
+ console.log(" " + chalk.whiteBright("NODE PILOT") + " ");
14
+ console.log(chalk.whiteBright(" ****************************************"));
13
15
  await checkHardware.systemRequirements();
14
16
  },
15
17
  };
@@ -1,4 +1,5 @@
1
1
  export declare const checkNetwork: {
2
+ checkSeedList(): Promise<void>;
2
3
  configureIpAddress(): Promise<void>;
3
4
  detectExternalIpAddress(): Promise<void>;
4
5
  enterIpAddressManually(): Promise<string>;
@@ -1,8 +1,56 @@
1
1
  import { input, select } from "@inquirer/prompts";
2
2
  import chalk from "chalk";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
3
5
  import { clm } from "../clm.js";
4
6
  import { configStore } from "../config-store.js";
5
7
  export const checkNetwork = {
8
+ async checkSeedList() {
9
+ if (configStore.hasProjectFlag('seedListChecked')) {
10
+ return;
11
+ }
12
+ const { type } = configStore.getNetworkInfo();
13
+ clm.preStep(`Checking inclusion into seed list for ${type.toUpperCase()} network...`);
14
+ const { nodeId, projectDir } = configStore.getProjectInfo();
15
+ const seedListFile = path.resolve(projectDir, 'seedlist');
16
+ if (fs.existsSync(seedListFile)) {
17
+ const found = fs.readFileSync(seedListFile, 'utf8').includes(nodeId);
18
+ if (found) {
19
+ clm.postStep(`Node ID found in ${type.toUpperCase()} seed list.`);
20
+ configStore.setProjectFlag('seedListChecked', true);
21
+ return;
22
+ }
23
+ }
24
+ const printNotFoundError = () => {
25
+ clm.warn(`Node ID not found in ${type.toUpperCase()} seed list. You may try again later.`);
26
+ clm.error(`To change the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
27
+ };
28
+ if (type === 'mainnet') {
29
+ // the mainnet seed list comed from a network release files
30
+ printNotFoundError();
31
+ }
32
+ else {
33
+ const url = `https://constellationlabs-dag.s3.us-west-1.amazonaws.com/${type}-seedlist`;
34
+ const seedList = await fetch(url)
35
+ .then(res => {
36
+ if (res.ok)
37
+ return res.text();
38
+ throw new Error(`Failed`);
39
+ })
40
+ .catch(() => {
41
+ clm.error(`Failed to fetch seed list from ${url}. Try again later.`);
42
+ return '';
43
+ });
44
+ if (seedList.includes(nodeId)) {
45
+ clm.postStep(`Node ID found in ${type.toUpperCase()} seed list.`);
46
+ fs.writeFileSync(seedListFile, seedList);
47
+ configStore.setProjectFlag('seedListChecked', true);
48
+ }
49
+ else {
50
+ printNotFoundError();
51
+ }
52
+ }
53
+ },
6
54
  async configureIpAddress() {
7
55
  const { CL_EXTERNAL_IP: currentIpAddress } = configStore.getEnvCommonInfo();
8
56
  const detectedIpAddress = await checkNetwork.fetchIPAddress().catch(() => '');
@@ -0,0 +1,5 @@
1
+ export declare const checkNodeCtl: {
2
+ check4Migration(): Promise<void>;
3
+ importKeyInfo(cnPath: string): Promise<void>;
4
+ promptForKeyFile(pilotKeyPath: string): Promise<void>;
5
+ };
@@ -0,0 +1,88 @@
1
+ import { input, password } from "@inquirer/prompts";
2
+ import chalk from "chalk";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import yaml from "yaml";
6
+ import { clm } from "../clm.js";
7
+ import { configStore } from "../config-store.js";
8
+ import { dockerHelper } from "../helpers/docker-helper.js";
9
+ import { keyFileHelper } from "../helpers/key-file-helper.js";
10
+ import { promptHelper } from "../helpers/prompt-helper.js";
11
+ import { shellService } from "../services/shell-service.js";
12
+ import { nodeService } from "../services/node-service.js";
13
+ export const checkNodeCtl = {
14
+ async check4Migration() {
15
+ if (configStore.hasProjectFlag('nodeCtlChecked')) {
16
+ return;
17
+ }
18
+ const { name } = configStore.getProjectInfo();
19
+ if (name.toLowerCase() !== 'hypergraph') {
20
+ configStore.setProjectFlag('nodeCtlChecked', true);
21
+ return;
22
+ }
23
+ const hasNodeAdminUser = fs.existsSync('/home/nodeadmin');
24
+ if (hasNodeAdminUser) {
25
+ const isDockerRunning = await dockerHelper.isRunning();
26
+ const isPortOpen = await nodeService.isPortInUse(9000);
27
+ clm.step(chalk.bold('NODECTL has been detected.'));
28
+ if (!isDockerRunning && isPortOpen) {
29
+ clm.error('Please shutdown any Nodes being managed by NODECTL before proceeding.');
30
+ }
31
+ const cnPath = path.resolve('/var/tessellation/nodectl/cn-config.yaml');
32
+ if (fs.existsSync(cnPath)) {
33
+ const answer = await input({
34
+ default: 'y',
35
+ message: 'Would you like to import key file from nodectl? (y/n): '
36
+ });
37
+ if (answer.toLowerCase() === 'y') {
38
+ await this.importKeyInfo(cnPath);
39
+ }
40
+ }
41
+ }
42
+ configStore.setProjectFlag('nodeCtlChecked', true);
43
+ },
44
+ async importKeyInfo(cnPath) {
45
+ clm.step('Importing key file from nodectl...');
46
+ try {
47
+ clm.preStep('Making a sudo call to read the nodectl config file...');
48
+ await shellService.runCommand(`sudo chmod +r ${cnPath}`);
49
+ const doc = yaml.parse(fs.readFileSync(cnPath, 'utf8'));
50
+ // console.log(JSON.stringify(doc,null,2));
51
+ // eslint-disable-next-line camelcase
52
+ const { key_location, key_name } = doc.nodectl.global_p12;
53
+ const nodeCtlKeyPath = path.resolve(key_location, key_name);
54
+ clm.debug(`Found key file path in nodectl config file: ${nodeCtlKeyPath}`);
55
+ clm.step('Key file found at ' + chalk.cyan(nodeCtlKeyPath));
56
+ clm.preStep('Importing key file...');
57
+ const { projectDir } = configStore.getProjectInfo();
58
+ const pilotKeyPath = path.join(projectDir, 'key.p12');
59
+ // copy file to home directory, change owner to current user, and make it readable by all
60
+ clm.preStep('Making a sudo call to copy the key file...');
61
+ await shellService.runCommand(`sudo cp ${nodeCtlKeyPath} ${pilotKeyPath}; sudo chown $(whoami) ${pilotKeyPath}; chmod +r ${pilotKeyPath}`);
62
+ await this.promptForKeyFile(pilotKeyPath);
63
+ }
64
+ catch (error) {
65
+ console.error(error);
66
+ clm.warn('Failed to import key information from nodectl. You will need to import it manually.');
67
+ await promptHelper.doYouWishToContinue();
68
+ }
69
+ },
70
+ async promptForKeyFile(pilotKeyPath) {
71
+ // prompt for password
72
+ const keyPassword = await password({ message: 'Enter the key file password:' });
73
+ const keyAlias = await input({ message: 'Enter the key file alias:' });
74
+ configStore.setEnvCommonInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: pilotKeyPath, CL_PASSWORD: keyPassword });
75
+ try {
76
+ const dagAddress = await keyFileHelper.getAddress();
77
+ const nodeId = await keyFileHelper.getId();
78
+ configStore.setProjectInfo({ dagAddress, nodeId });
79
+ }
80
+ catch {
81
+ clm.warn('Failed to unlock the key file. Please check your key file information and try again.');
82
+ fs.rmSync(pilotKeyPath);
83
+ await this.promptForKeyFile(pilotKeyPath);
84
+ return;
85
+ }
86
+ clm.postStep('Key file imported successfully.\n');
87
+ }
88
+ };
@@ -1,11 +1,12 @@
1
1
  import { input, select } from "@inquirer/prompts";
2
+ import ora from 'ora';
2
3
  import { clm } from "../clm.js";
3
4
  import { configStore } from "../config-store.js";
4
5
  import { configHelper } from "../helpers/config-helper.js";
5
6
  import { dockerHelper } from "../helpers/docker-helper.js";
7
+ import { projectHelper } from "../helpers/project-helper.js";
6
8
  import { promptHelper } from "../helpers/prompt-helper.js";
7
9
  import { clusterService } from "../services/cluster-service.js";
8
- import { nodeService } from "../services/node-service.js";
9
10
  import { shellService } from "../services/shell-service.js";
10
11
  import { checkNetwork } from "./check-network.js";
11
12
  export const checkProject = {
@@ -13,7 +14,7 @@ export const checkProject = {
13
14
  let updateNetworkType = false;
14
15
  let updateLayers = false;
15
16
  if (!configStore.hasProjects() || process.env.PILOT_ENV === 'test') {
16
- await promptHelper.selectProject();
17
+ await projectHelper.selectProject();
17
18
  await checkNetwork.configureIpAddress();
18
19
  updateNetworkType = true;
19
20
  updateLayers = true;
@@ -85,14 +86,28 @@ export const checkProject = {
85
86
  clm.postStep(`Network files are already installed for ${nInfo.type} version ${clusterVersion}`);
86
87
  return false;
87
88
  }
88
- const nodeInfo = await nodeService.getNodeInfo('first');
89
- const isRunning = nodeInfo.state !== 'Unavailable';
89
+ const isRunning = await dockerHelper.isRunning();
90
90
  if (isRunning) {
91
91
  await dockerHelper.dockerDown();
92
92
  }
93
- clm.preStep('Running install script...');
94
- const silent = false; // !process.env.DEBUG;
95
- await shellService.runCommand(`scripts/install.sh ${nInfo.type}`, undefined, silent); // different for metagraphs
93
+ const silent = !process.env.DEBUG;
94
+ const spinner = ora('Running install script...');
95
+ if (silent) {
96
+ spinner.start();
97
+ spinner.color = 'green';
98
+ }
99
+ else {
100
+ clm.preStep('Running install script...');
101
+ }
102
+ // NOTE: may be different for metagraphs
103
+ await shellService.runProjectCommand(`scripts/install.sh ${nInfo.type}`, undefined, silent)
104
+ .catch(() => {
105
+ spinner.stop();
106
+ clm.error('Install script failed. Please run cpilot again after correcting the error');
107
+ });
108
+ if (silent) {
109
+ spinner.stop();
110
+ }
96
111
  rInfo = await configHelper.getReleaseInfo();
97
112
  configStore.setNetworkInfo({
98
113
  type: rInfo.network,
package/dist/clm.js CHANGED
@@ -19,7 +19,7 @@ export const clm = {
19
19
  console.log(chalk.green(s));
20
20
  },
21
21
  preStep(s) {
22
- console.log('\n', chalk.italic(chalk.green(s)));
22
+ console.log('\n' + chalk.italic(chalk.green(s)));
23
23
  },
24
24
  step(msg) {
25
25
  console.warn(chalk.whiteBright(msg));
@@ -7,6 +7,7 @@ export default class Logs extends Command {
7
7
  static examples: string[];
8
8
  static flags: {
9
9
  follow: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ numOfLines: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
11
  };
11
12
  run(): Promise<void>;
12
13
  }
@@ -1,8 +1,8 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
2
  import path from "node:path";
3
- import { shellService } from "../services/shell-service.js";
4
3
  import { configStore } from "../config-store.js";
5
4
  import { configHelper } from "../helpers/config-helper.js";
5
+ import { shellService } from "../services/shell-service.js";
6
6
  export default class Logs extends Command {
7
7
  static args = {
8
8
  layer: Args.string({ description: 'network layer to view. e.g. gl0' }),
@@ -13,13 +13,15 @@ export default class Logs extends Command {
13
13
  ];
14
14
  static flags = {
15
15
  follow: Flags.boolean({ char: 'f', description: 'continuously wait for additional data to be appended' }),
16
+ numOfLines: Flags.string({ char: 'n', description: 'number of lines at the end of the log to display' }),
16
17
  };
17
18
  async run() {
18
19
  configHelper.assertProject('No project found. ');
19
- let tailFlag = '';
20
20
  const { flags } = await this.parse(Logs);
21
+ const numOfLines = Number.isNaN(Number(flags.numOfLines)) ? 100 : Number(flags.numOfLines);
22
+ let tailFlag = flags.numOfLines ? `-n ${numOfLines}` : '-n 100';
21
23
  if (flags.follow) {
22
- tailFlag = '-f';
24
+ tailFlag = ' -f';
23
25
  }
24
26
  const { projectDir } = configStore.getProjectInfo();
25
27
  const logPath = path.join(projectDir, 'app-data', 'gl0-logs', 'app.log');
@@ -1,6 +1,8 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import { checkInitialSetup } from "../checks/check-initial-setup.js";
3
3
  import { checkLayers } from "../checks/check-layers.js";
4
+ import { checkNetwork } from "../checks/check-network.js";
5
+ import { checkNodeCtl } from "../checks/check-node-ctl.js";
4
6
  import { checkProject } from "../checks/check-project.js";
5
7
  import { keyFileHelper } from "../helpers/key-file-helper.js";
6
8
  export default class Status extends Command {
@@ -15,7 +17,9 @@ export async function checkInstallationAndConfigurationStatus() {
15
17
  await checkInitialSetup.firstTimeRun();
16
18
  await checkProject.projectInstallation();
17
19
  await checkProject.releaseVersion();
20
+ await checkNodeCtl.check4Migration();
18
21
  await keyFileHelper.promptIfNoKeyFile();
22
+ await checkNetwork.checkSeedList();
19
23
  await checkLayers.layersRunning();
20
24
  await checkLayers.layersReadyToJoin();
21
25
  await checkLayers.layersStatus();
@@ -3,4 +3,5 @@ export default class Test extends Command {
3
3
  static description: string;
4
4
  static hidden: boolean;
5
5
  run(): Promise<void>;
6
+ testRandomNode(): Promise<void>;
6
7
  }
@@ -1,13 +1,35 @@
1
1
  import { Command } from "@oclif/core";
2
+ import dotenv from "dotenv";
2
3
  import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { getRandomNode } from "../services/get-random-node.js";
7
+ import { checkNodeCtl } from "../checks/check-node-ctl.js";
3
8
  export default class Test extends Command {
4
9
  static description = 'node pilot test command';
5
10
  static hidden = true;
6
11
  async run() {
7
- // await promptHelper.configureJavaMemoryArguments();
8
- const r = fs.statfsSync('/');
9
- const totalSpace = (r.bsize * r.blocks / (1024 * 1024 * 1024)).toFixed(2);
10
- const totalFreeSpace = (r.bsize * r.bfree / (1024 * 1024 * 1024)).toFixed(2);
11
- console.log(totalSpace, totalFreeSpace);
12
+ await checkNodeCtl.importKeyInfo(path.resolve('/Users/ffox/Projects/Constellation/node-pilot/cn-config.yaml'));
13
+ }
14
+ async testRandomNode() {
15
+ const filePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../projects/hypergraph/networks/mainnet.env`);
16
+ const conetent = fs.readFileSync(filePath);
17
+ const parsed = dotenv.parse(conetent);
18
+ const nodes = ['1', '2', '3'].map(i => {
19
+ return { host: parsed[`SOURCE_NODE_${i}_HOST`], id: parsed[`SOURCE_NODE_${i}_ID`], publicPort: parsed[`SOURCE_NODE_${i}_PORT`] };
20
+ });
21
+ const n = await getRandomNode(nodes);
22
+ console.log('Random node:', n);
12
23
  }
13
24
  }
25
+ // type NetworkEnvType = {
26
+ // SOURCE_NODE_1_HOST:string,
27
+ // SOURCE_NODE_1_ID:string,
28
+ // SOURCE_NODE_1_PORT:string,
29
+ // SOURCE_NODE_2_HOST:string,
30
+ // SOURCE_NODE_2_ID:string,
31
+ // SOURCE_NODE_2_PORT:string,
32
+ // SOURCE_NODE_3_HOST:string,
33
+ // SOURCE_NODE_3_ID:string,
34
+ // SOURCE_NODE_3_PORT:string,
35
+ // }
@@ -14,6 +14,7 @@ declare class ConfigStore {
14
14
  getNetworkInfo(): NetworkInfo;
15
15
  getProjectInfo(): ProjectInfo;
16
16
  getSystemInfo(): SystemInfo;
17
+ hasProjectFlag(name: string): boolean;
17
18
  hasProjects(): boolean;
18
19
  setDockerEnvInfo(info: Partial<{
19
20
  DOCKER_IMAGE_VERSION: string;
@@ -24,8 +25,9 @@ declare class ConfigStore {
24
25
  setEnvLayerInfo(layer: TessellationLayer, info: Partial<EnvLayerInfo>): void;
25
26
  setNetworkEnvInfo(info: NetworkEnvInfo): void;
26
27
  setNetworkInfo(info: Partial<NetworkInfo>): void;
28
+ setProjectFlag(name: string, value: boolean): any;
27
29
  setProjectInfo(info: Partial<ProjectInfo>): void;
28
- setSystemInfo(info: SystemInfo): void;
30
+ setSystemInfo(info: Partial<SystemInfo>): void;
29
31
  }
30
32
  export declare const configStore: ConfigStore;
31
33
  type DeepPartial<T> = {
@@ -77,10 +79,11 @@ export declare const layerEnvNames: {
77
79
  CL_PUBLIC_HTTP_PORT: number;
78
80
  };
79
81
  export type SystemInfo = {
80
- cores?: number;
81
- disk?: string;
82
- memory?: string;
83
- platform?: string;
82
+ cores: number;
83
+ disk: string;
84
+ isDockerInstalled: boolean;
85
+ memory: string;
86
+ platform: string;
84
87
  };
85
88
  export type NetworkType = 'integrationnet' | 'mainnet' | 'testnet';
86
89
  export type ProjectInfo = {
@@ -90,6 +90,10 @@ class ConfigStore {
90
90
  getSystemInfo() {
91
91
  return this.pilotStore.getItem('system');
92
92
  }
93
+ hasProjectFlag(name) {
94
+ const flags = this.projectStore.getItem('flags') || {};
95
+ return flags[name] !== undefined;
96
+ }
93
97
  hasProjects() {
94
98
  const { projects } = this.pilotStore.getItem('pilot');
95
99
  return projects.length > 0;
@@ -119,6 +123,12 @@ class ConfigStore {
119
123
  const oldInfo = this.projectStore.getItem('network');
120
124
  this.projectStore.setItem('network', { ...oldInfo, ...info });
121
125
  }
126
+ setProjectFlag(name, value) {
127
+ const flags = this.projectStore.getItem('flags') || {};
128
+ flags[name] = value;
129
+ this.projectStore.setItem('flags', flags);
130
+ return flags;
131
+ }
122
132
  setProjectInfo(info) {
123
133
  const oldInfo = this.projectStore.getItem('project');
124
134
  this.projectStore.setItem('project', { ...oldInfo, ...info });
@@ -1,12 +1,25 @@
1
+ import ora from "ora";
1
2
  import { clm } from "../clm.js";
2
3
  import { configStore } from "../config-store.js";
3
4
  import { shellService } from "../services/shell-service.js";
4
5
  import { projectHelper } from "./project-helper.js";
5
6
  export const dockerHelper = {
6
7
  async dockerBuild() {
7
- if (shellService.existsScript('scripts/docker-build.sh')) {
8
- clm.preStep('Building the node container...');
9
- await shellService.runCommand('bash scripts/docker-build.sh');
8
+ if (shellService.existsProjectScript('scripts/docker-build.sh')) {
9
+ const silent = !process.env.DEBUG;
10
+ const spinner = ora('Building the node container...');
11
+ if (silent) {
12
+ spinner.start();
13
+ spinner.color = 'green';
14
+ }
15
+ else {
16
+ clm.preStep('Building the node container...');
17
+ }
18
+ await shellService.runProjectCommand('bash scripts/docker-build.sh', undefined, silent);
19
+ if (silent) {
20
+ spinner.stop();
21
+ }
22
+ clm.postStep('Node container built.');
10
23
  }
11
24
  },
12
25
  async dockerDown() {
@@ -27,11 +40,11 @@ export const dockerHelper = {
27
40
  await run('up -d');
28
41
  },
29
42
  async isRunning() {
30
- return shellService.runCommand('docker ps | grep entrypoint.sh', undefined, true).then(() => true).catch(() => false);
43
+ return shellService.runCommand('docker ps | grep entrypoint.sh', undefined, true).then(Boolean).catch(() => false);
31
44
  }
32
45
  };
33
46
  function run(command, layers) {
34
47
  const { layersToRun } = configStore.getProjectInfo();
35
48
  const args = (layers || layersToRun).map(l => `--profile ${l}`).join(' ');
36
- return shellService.runCommand(`docker compose ${args} ${command}`, configStore.getDockerEnvInfo());
49
+ return shellService.runProjectCommand(`docker compose ${args} ${command}`, configStore.getDockerEnvInfo());
37
50
  }
@@ -118,7 +118,7 @@ export const keyFileHelper = {
118
118
  await this.promptForKeyFile();
119
119
  },
120
120
  async showKeyFileInfo(prompt4ShowPassword = true) {
121
- clm.preStep('Key File Information:');
121
+ clm.preStep('Current key file information:');
122
122
  const { dagAddress, nodeId } = configStore.getProjectInfo();
123
123
  configHelper.showEnvInfo('Node ID', nodeId);
124
124
  configHelper.showEnvInfo('DAG Address', dagAddress);
@@ -6,4 +6,5 @@ export declare const projectHelper: {
6
6
  installEmbedded(name: string): Promise<void>;
7
7
  installFromGithub(_repo: string): Promise<never>;
8
8
  installHypergraph(): Promise<void>;
9
+ selectProject(): Promise<void>;
9
10
  };