@aptos-labs/aptos-cli 0.1.9 → 1.0.0
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/bin/aptos.ts +42 -0
- package/bin/tasks/install.ts +55 -0
- package/bin/tasks/run.ts +23 -0
- package/bin/tasks/update.ts +33 -0
- package/bin/utils/aptosExecutableIsAvailable.ts +14 -0
- package/bin/utils/brewOperations.ts +23 -0
- package/bin/utils/consts.ts +3 -0
- package/bin/utils/execSyncShell.ts +8 -0
- package/bin/utils/getAptosCliLatestVersion.ts +14 -0
- package/bin/utils/getLocalBinPath.ts +28 -0
- package/bin/utils/getUserOs.ts +18 -0
- package/bin/utils/ghOperations.ts +20 -0
- package/bin/utils/handleHelpOptions.ts +38 -0
- package/bin/utils/parseCommandOptions.ts +28 -0
- package/bin/utils/versions.ts +9 -0
- package/dist/aptos.js +24 -0
- package/package.json +31 -4
- package/CONTRIBUTING.md +0 -8
- package/bin/aptos +0 -177
package/bin/aptos.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// On MacOS we install the CLI with brew. There are two main reasons for this:
|
|
4
|
+
// 1. Brew builds the CLI for the native CPU architecture for the user, which
|
|
5
|
+
// eliminates any issues arising from using x86 binaries on ARM machines.
|
|
6
|
+
// 2. Brew handles dependency management for us. This isn't relevant right now but
|
|
7
|
+
// might become necessary later if we reintroduce OpenSSL as a dep for the CLI.
|
|
8
|
+
//
|
|
9
|
+
// On Linux and Windows we just query the GH API for the latest CLI release and
|
|
10
|
+
// download and extract that.
|
|
11
|
+
|
|
12
|
+
import { program } from "commander";
|
|
13
|
+
|
|
14
|
+
import { parseCommandOptions } from "./utils/parseCommandOptions.js";
|
|
15
|
+
import { runCLI } from "./tasks/run.js";
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name("aptos")
|
|
19
|
+
.helpOption(false)
|
|
20
|
+
.option("-i, --install", "install the latest version of the CLI")
|
|
21
|
+
.option("-u, --update", "update the CLI to the latest version")
|
|
22
|
+
.allowUnknownOption();
|
|
23
|
+
|
|
24
|
+
program.parse(process.argv);
|
|
25
|
+
|
|
26
|
+
const main = async () => {
|
|
27
|
+
const options = {
|
|
28
|
+
install: program.opts().install,
|
|
29
|
+
update: program.opts().update,
|
|
30
|
+
};
|
|
31
|
+
const unknownOptions = program.args;
|
|
32
|
+
|
|
33
|
+
// Manually check for `--help` and handle the CLI `--help`
|
|
34
|
+
if (process.argv.includes("--help")) {
|
|
35
|
+
// Forward to the CLI
|
|
36
|
+
return runCLI(unknownOptions);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await parseCommandOptions(options, unknownOptions);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
|
|
4
|
+
import { GH_CLI_DOWNLOAD_URL, PNAME } from "../utils/consts.js";
|
|
5
|
+
import { execSyncShell } from "../utils/execSyncShell.js";
|
|
6
|
+
import { getCurrentOpenSSLVersion } from "../utils/versions.js";
|
|
7
|
+
import { getOS } from "../utils/getUserOs.js";
|
|
8
|
+
import { getLatestVersion } from "../utils/getAptosCliLatestVersion.js";
|
|
9
|
+
import { getLocalBinPath } from "../utils/getLocalBinPath.js";
|
|
10
|
+
|
|
11
|
+
// Install the CLI.
|
|
12
|
+
export const installCli = async () => {
|
|
13
|
+
const path = getLocalBinPath();
|
|
14
|
+
if (existsSync(path)) {
|
|
15
|
+
console.log("Aptos CLI is already installed");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// Look up the latest version.
|
|
19
|
+
const latestCLIVersion = await getLatestVersion();
|
|
20
|
+
console.log(`Downloading aptos CLI version ${latestCLIVersion}`);
|
|
21
|
+
const os = getOS();
|
|
22
|
+
|
|
23
|
+
if (os === "Windows") {
|
|
24
|
+
const url = `${GH_CLI_DOWNLOAD_URL}/${PNAME}-v${latestCLIVersion}/${PNAME}-${latestCLIVersion}-${os}-x86_64.zip`;
|
|
25
|
+
// Download the zip file, extract it, and move the binary to the correct location.
|
|
26
|
+
execSync(
|
|
27
|
+
`powershell -Command "if (!(Test-Path -Path 'C:\\tmp')) { New-Item -ItemType Directory -Path 'C:\\tmp' } ; Invoke-RestMethod -Uri ${url} -OutFile C:\\tmp\\aptos.zip; Expand-Archive -Path C:\\tmp\\aptos.zip -DestinationPath C:\\tmp -Force; Move-Item -Path C:\\tmp\\aptos.exe -Destination \"${path}\""`
|
|
28
|
+
);
|
|
29
|
+
} else if (os === "MacOS") {
|
|
30
|
+
// Install the CLI with brew.
|
|
31
|
+
execSyncShell("brew install aptos", { encoding: "utf8" });
|
|
32
|
+
} else {
|
|
33
|
+
// On Linux, we check what version of OpenSSL we're working with to figure out
|
|
34
|
+
// which binary to download.
|
|
35
|
+
let osVersion = "x86_64";
|
|
36
|
+
let opensSslVersion = "1.0.0";
|
|
37
|
+
try {
|
|
38
|
+
opensSslVersion = getCurrentOpenSSLVersion();
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.log(
|
|
41
|
+
"Could not determine OpenSSL version, assuming older version (1.x.x)"
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (opensSslVersion.startsWith("3.")) {
|
|
46
|
+
osVersion = "22.04-x86_64";
|
|
47
|
+
}
|
|
48
|
+
console.log(`Downloading CLI binary ${os}-${osVersion}`);
|
|
49
|
+
const url = `${GH_CLI_DOWNLOAD_URL}/${PNAME}-v${latestCLIVersion}/${PNAME}-${latestCLIVersion}-${os}-${osVersion}.zip`;
|
|
50
|
+
// Download the zip file, extract it, and move the binary to the correct location.
|
|
51
|
+
execSync(
|
|
52
|
+
`curl -L -o /tmp/aptos.zip ${url}; unzip -o -q /tmp/aptos.zip -d /tmp; mv /tmp/aptos ${path};`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
};
|
package/bin/tasks/run.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
|
|
4
|
+
import { getOS } from "../utils/getUserOs.js";
|
|
5
|
+
import { getLocalBinPath } from "../utils/getLocalBinPath.js";
|
|
6
|
+
|
|
7
|
+
export const runCLI = async (args: string[] = []) => {
|
|
8
|
+
const path = getLocalBinPath();
|
|
9
|
+
if (!existsSync(path)) {
|
|
10
|
+
console.log(
|
|
11
|
+
"Aptos CLI not installed, run `npx aptos --install` to install"
|
|
12
|
+
);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const os = getOS();
|
|
16
|
+
|
|
17
|
+
// Spawn a child process to execute the binary with the provided arguments.
|
|
18
|
+
// Spawn the child process to run the real CLI executable with the forwarded arguments
|
|
19
|
+
spawn(path, args, {
|
|
20
|
+
stdio: "inherit", // Forward the stdio so output is visible
|
|
21
|
+
shell: os === "Windows", // Use shell on Windows
|
|
22
|
+
});
|
|
23
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
|
|
3
|
+
import { execSyncShell } from "../utils/execSyncShell.js";
|
|
4
|
+
import { getLatestVersion } from "../utils/getAptosCliLatestVersion.js";
|
|
5
|
+
import { installCli } from "./install.js";
|
|
6
|
+
import { getLocalBinPath } from "../utils/getLocalBinPath.js";
|
|
7
|
+
|
|
8
|
+
export const updateCli = async () => {
|
|
9
|
+
const path = getLocalBinPath();
|
|
10
|
+
if (!existsSync(path)) {
|
|
11
|
+
console.log(
|
|
12
|
+
"Aptos CLI not installed, run `npx aptos --install` to install"
|
|
13
|
+
);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// Look up the latest version.
|
|
17
|
+
const latestVersion = await getLatestVersion();
|
|
18
|
+
// Get the current version of the CLI.
|
|
19
|
+
const currentVersion = execSyncShell(`${path} --version`, {
|
|
20
|
+
encoding: "utf8",
|
|
21
|
+
})
|
|
22
|
+
.trim()
|
|
23
|
+
.split(" ")[1];
|
|
24
|
+
// Check if the installed version is the latest version.
|
|
25
|
+
if (currentVersion !== latestVersion) {
|
|
26
|
+
console.log(
|
|
27
|
+
`A newer version of the CLI is available: ${latestVersion}, installing...`
|
|
28
|
+
);
|
|
29
|
+
installCli();
|
|
30
|
+
} else {
|
|
31
|
+
console.log(`CLI is up to date`);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { execSyncShell } from "./execSyncShell.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Only works on Unix systems. This is fine because we only need to check for brew on
|
|
5
|
+
* MacOS.
|
|
6
|
+
*/
|
|
7
|
+
export const executableIsAvailable = (name) => {
|
|
8
|
+
try {
|
|
9
|
+
execSyncShell(`which ${name}`, { encoding: "utf8" });
|
|
10
|
+
return true;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { execSyncShell } from "./execSyncShell.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Based on the installation path of the aptos formula, determine the path where the
|
|
5
|
+
* CLI should be installed.
|
|
6
|
+
*/
|
|
7
|
+
export const getCliPathBrew = () => {
|
|
8
|
+
const directory = execSyncShell("brew --prefix aptos", { encoding: "utf8" })
|
|
9
|
+
.toString()
|
|
10
|
+
.trim();
|
|
11
|
+
return `${directory}/bin/aptos`;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Use brew to find the latest version of the CLI. Make sure to confirm that brew
|
|
16
|
+
* is installed before calling this function.
|
|
17
|
+
*/
|
|
18
|
+
export const getLatestVersionBrew = () => {
|
|
19
|
+
const out = JSON.parse(
|
|
20
|
+
execSyncShell("brew info --json aptos", { encoding: "utf8" })
|
|
21
|
+
);
|
|
22
|
+
return out[0].versions.stable;
|
|
23
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getLatestVersionBrew } from "./brewOperations.js";
|
|
2
|
+
import { getOS } from "./getUserOs.js";
|
|
3
|
+
import { getLatestVersionGh } from "./ghOperations.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Determine the latest version of the CLI.
|
|
7
|
+
*/
|
|
8
|
+
export const getLatestVersion = async () => {
|
|
9
|
+
if (getOS() === "MacOS") {
|
|
10
|
+
return getLatestVersionBrew();
|
|
11
|
+
} else {
|
|
12
|
+
return getLatestVersionGh();
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { executableIsAvailable } from "./aptosExecutableIsAvailable.js";
|
|
3
|
+
import { getCliPathBrew } from "./brewOperations.js";
|
|
4
|
+
import { PNAME } from "./consts.js";
|
|
5
|
+
import { getOS } from "./getUserOs.js";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
|
|
8
|
+
export const getLocalBinPath = () => {
|
|
9
|
+
let path;
|
|
10
|
+
const os = getOS();
|
|
11
|
+
if (os === "MacOS") {
|
|
12
|
+
// Confirm brew is installed.
|
|
13
|
+
const brewInstalled = executableIsAvailable("brew");
|
|
14
|
+
if (!brewInstalled) {
|
|
15
|
+
throw "Please install brew to continue: https://brew.sh/";
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
path = getCliPathBrew();
|
|
19
|
+
} catch (e) {
|
|
20
|
+
path = "";
|
|
21
|
+
}
|
|
22
|
+
} else if (os === "Windows") {
|
|
23
|
+
path = `${dirname(fileURLToPath(import.meta.url))}\\${PNAME}.exe`;
|
|
24
|
+
} else {
|
|
25
|
+
path = `${dirname(fileURLToPath(import.meta.url))}/${PNAME}`;
|
|
26
|
+
}
|
|
27
|
+
return path;
|
|
28
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { platform } from "os";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determine what OS we're running on.
|
|
5
|
+
*/
|
|
6
|
+
export const getOS = () => {
|
|
7
|
+
const osPlatform = platform();
|
|
8
|
+
switch (osPlatform) {
|
|
9
|
+
case "darwin":
|
|
10
|
+
return "MacOS";
|
|
11
|
+
case "linux":
|
|
12
|
+
return "Ubuntu";
|
|
13
|
+
case "win32":
|
|
14
|
+
return "Windows";
|
|
15
|
+
default:
|
|
16
|
+
throw new Error(`Unsupported OS ${osPlatform}`);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PNAME } from "./consts.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Query the GitHub API to find the latest CLI release. We assume that the CLI is in
|
|
5
|
+
* the last 100 releases so we don't paginate through the releases.
|
|
6
|
+
*/
|
|
7
|
+
export const getLatestVersionGh = async () => {
|
|
8
|
+
const prefix = `${PNAME}-v`;
|
|
9
|
+
const response = await (
|
|
10
|
+
await fetch(
|
|
11
|
+
"https://api.github.com/repos/aptos-labs/aptos-core/releases?per_page=100"
|
|
12
|
+
)
|
|
13
|
+
).json();
|
|
14
|
+
for (const release of response) {
|
|
15
|
+
if (release["tag_name"].startsWith(`${prefix}`)) {
|
|
16
|
+
return release.tag_name.replace(`${prefix}`, "");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
throw "Could not determine latest version of Aptos CLI";
|
|
20
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { spawnSync } from "child_process";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handle the `--help` option for the Aptos CLI. This function is used to combine
|
|
6
|
+
* the Aptos CLI help output with the Commander help output.
|
|
7
|
+
* @param program - The Commander program instance.
|
|
8
|
+
* @param unknownOptions - The unknown options passed to the CLI.
|
|
9
|
+
* @returns void
|
|
10
|
+
*/
|
|
11
|
+
export const handleHelpOptions = (
|
|
12
|
+
program: Command,
|
|
13
|
+
unknownOptions: string[]
|
|
14
|
+
) => {
|
|
15
|
+
// Capture the Aptos CLI help output
|
|
16
|
+
const cliHelp = spawnSync(`aptos`, unknownOptions, {
|
|
17
|
+
stdio: "pipe",
|
|
18
|
+
encoding: "utf-8",
|
|
19
|
+
});
|
|
20
|
+
// Generate Commander help text
|
|
21
|
+
const commanderHelp = program.helpInformation();
|
|
22
|
+
|
|
23
|
+
// Remove the "Usage" and "Options" lines from the Commander output
|
|
24
|
+
const commanderOptionsOnly = commanderHelp
|
|
25
|
+
.split("\n")
|
|
26
|
+
.filter((line) => !line.startsWith("Usage") && !line.startsWith("Options"))
|
|
27
|
+
.join("\n");
|
|
28
|
+
|
|
29
|
+
// Find where the CLI options start and append the Commander options to the existing CLI options
|
|
30
|
+
const combinedHelp = cliHelp.stdout.replace(
|
|
31
|
+
"Options:",
|
|
32
|
+
`Options:\n${commanderOptionsOnly.trim()}`
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Output the combined help
|
|
36
|
+
console.log(combinedHelp);
|
|
37
|
+
return;
|
|
38
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { installCli } from "../tasks/install.js";
|
|
3
|
+
import { runCLI } from "../tasks/run.js";
|
|
4
|
+
import { updateCli } from "../tasks/update.js";
|
|
5
|
+
import { getLocalBinPath } from "./getLocalBinPath.js";
|
|
6
|
+
|
|
7
|
+
export const parseCommandOptions = async (
|
|
8
|
+
options: { install: boolean; update: boolean },
|
|
9
|
+
unknownOptions: string[]
|
|
10
|
+
) => {
|
|
11
|
+
// if `--install` flag is set, only install the cli and dont run it
|
|
12
|
+
if (options.install) {
|
|
13
|
+
await installCli();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// if `--update` flag is set, update the cli and dont run it
|
|
17
|
+
if (options.update) {
|
|
18
|
+
await updateCli();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// if no flags are set, install and run the cli
|
|
23
|
+
const path = getLocalBinPath();
|
|
24
|
+
if (!existsSync(path)) {
|
|
25
|
+
await installCli();
|
|
26
|
+
}
|
|
27
|
+
await runCLI(unknownOptions);
|
|
28
|
+
};
|
package/dist/aptos.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from "commander";
|
|
3
|
+
import { parseCommandOptions } from "./utils/parseCommandOptions.js";
|
|
4
|
+
import { runCLI } from "./tasks/run.js";
|
|
5
|
+
program
|
|
6
|
+
.name("aptos")
|
|
7
|
+
.helpOption(false)
|
|
8
|
+
.option("-i, --install", "install the latest version of the CLI")
|
|
9
|
+
.option("-u, --update", "update the CLI to the latest version")
|
|
10
|
+
.allowUnknownOption();
|
|
11
|
+
program.parse(process.argv);
|
|
12
|
+
const main = async () => {
|
|
13
|
+
const options = {
|
|
14
|
+
install: program.opts().install,
|
|
15
|
+
update: program.opts().update,
|
|
16
|
+
};
|
|
17
|
+
const unknownOptions = program.args;
|
|
18
|
+
if (process.argv.includes("--help")) {
|
|
19
|
+
return runCLI(unknownOptions);
|
|
20
|
+
}
|
|
21
|
+
await parseCommandOptions(options, unknownOptions);
|
|
22
|
+
};
|
|
23
|
+
main().catch(console.error);
|
|
24
|
+
//# sourceMappingURL=aptos.js.map
|
package/package.json
CHANGED
|
@@ -1,10 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aptos-labs/aptos-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Aptos CLI available from npmjs",
|
|
5
5
|
"bin": {
|
|
6
|
-
"aptos": "
|
|
6
|
+
"aptos": "./dist/aptos.js"
|
|
7
7
|
},
|
|
8
|
-
"
|
|
9
|
-
"
|
|
8
|
+
"type": "module",
|
|
9
|
+
"author": "aptoslabs.com",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"aptos node cli",
|
|
12
|
+
"aptos"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/aptos-labs/aptos-cli"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/aptos-labs/aptos-cli/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"clean": "rm -rf dist",
|
|
24
|
+
"build": "npm run clean && tsc",
|
|
25
|
+
"dev": "npm run build && node ./dist/aptos.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"commander": "^12.1.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.5.0",
|
|
35
|
+
"typescript": "^5.6.2"
|
|
36
|
+
}
|
|
10
37
|
}
|
package/CONTRIBUTING.md
DELETED
package/bin/aptos
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// On MacOS we install the CLI with brew. There are two main reasons for this:
|
|
4
|
-
// 1. Brew builds the CLI for the native CPU architecture for the user, which
|
|
5
|
-
// eliminates any issues arising from using x86 binaries on ARM machines.
|
|
6
|
-
// 2. Brew handles dependency management for us. This isn't relevant right now but
|
|
7
|
-
// might become necessary later if we reintroduce OpenSSL as a dep for the CLI.
|
|
8
|
-
//
|
|
9
|
-
// On Linux and Windows we just query the GH API for the latest CLI release and
|
|
10
|
-
// download and extract that.
|
|
11
|
-
|
|
12
|
-
const { execSync, spawn } = require("child_process");
|
|
13
|
-
const fs = require("fs");
|
|
14
|
-
const os = require("os");
|
|
15
|
-
|
|
16
|
-
const PNAME = "aptos-cli";
|
|
17
|
-
|
|
18
|
-
// Wrapper around execSync that uses the shell.
|
|
19
|
-
const execSyncShell = (command, options) => {
|
|
20
|
-
return execSync(command, { shell: true, ...options });
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// Determine what OS we're running on.
|
|
24
|
-
const getOS = () => {
|
|
25
|
-
const platform = os.platform();
|
|
26
|
-
switch (platform) {
|
|
27
|
-
case "darwin":
|
|
28
|
-
return "MacOS";
|
|
29
|
-
case "linux":
|
|
30
|
-
return "Ubuntu";
|
|
31
|
-
case "win32":
|
|
32
|
-
return "Windows";
|
|
33
|
-
default:
|
|
34
|
-
throw new Error(`Unsupported OS ${platform}`);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// Only works on Unix systems. This is fine because we only need to check for brew on
|
|
39
|
-
// MacOS.
|
|
40
|
-
const executableIsAvailable = (name) => {
|
|
41
|
-
try {
|
|
42
|
-
execSyncShell(`which ${name}`, { encoding: "utf8" });
|
|
43
|
-
return true;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// Query the GitHub API to find the latest CLI release. We assume that the CLI is in
|
|
50
|
-
// the last 100 releases so we don't paginate through the releases.
|
|
51
|
-
const getLatestVersionGh = async () => {
|
|
52
|
-
const prefix = `${PNAME}-v`;
|
|
53
|
-
const response = await (
|
|
54
|
-
await fetch(
|
|
55
|
-
"https://api.github.com/repos/aptos-labs/aptos-core/releases?per_page=100"
|
|
56
|
-
)
|
|
57
|
-
).json();
|
|
58
|
-
for (release of response) {
|
|
59
|
-
if (release["tag_name"].startsWith(`${prefix}`)) {
|
|
60
|
-
return release.tag_name.replace(`${prefix}`, "");
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
throw "Could not determine latest version of Aptos CLI";
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// Use brew to find the latest version of the CLI. Make sure to confirm that brew
|
|
67
|
-
// is installed before calling this function.
|
|
68
|
-
const getLatestVersionBrew = () => {
|
|
69
|
-
const out = JSON.parse(
|
|
70
|
-
execSyncShell("brew info --json aptos", { encoding: "utf8" })
|
|
71
|
-
);
|
|
72
|
-
return out[0].versions.stable;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Determine the latest version of the CLI.
|
|
76
|
-
const getLatestVersion = async () => {
|
|
77
|
-
if (os === "MacOS") {
|
|
78
|
-
return getLatestVersionBrew();
|
|
79
|
-
} else {
|
|
80
|
-
return getLatestVersionGh();
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// Based on the installation path of the aptos formula, determine the path where the
|
|
85
|
-
// CLI should be installed.
|
|
86
|
-
const getCliPathBrew = () => {
|
|
87
|
-
const directory = execSyncShell("brew --prefix aptos", { encoding: "utf8" })
|
|
88
|
-
.toString()
|
|
89
|
-
.trim();
|
|
90
|
-
return `${directory}/bin/aptos`;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// Install or update the CLI.
|
|
94
|
-
const installCli = (os, path, latestVersion) => {
|
|
95
|
-
const url = `https://github.com/aptos-labs/aptos-core/releases/download/${PNAME}-v${latestVersion}/${PNAME}-${latestVersion}-${os}-x86_64.zip`;
|
|
96
|
-
|
|
97
|
-
console.log(`Downloading aptos CLI version ${latestVersion}`);
|
|
98
|
-
if (os === "Windows") {
|
|
99
|
-
// Download the zip file, extract it, and move the binary to the correct location.
|
|
100
|
-
execSync(
|
|
101
|
-
`powershell -Command "if (!(Test-Path -Path 'C:\\tmp')) { New-Item -ItemType Directory -Path 'C:\\tmp' } ; Invoke-RestMethod -Uri ${url} -OutFile C:\\tmp\\aptos.zip; Expand-Archive -Path C:\\tmp\\aptos.zip -DestinationPath C:\\tmp -Force; Move-Item -Path C:\\tmp\\aptos.exe -Destination ${path}"`
|
|
102
|
-
);
|
|
103
|
-
} else if (os === "MacOS") {
|
|
104
|
-
// Install the CLI with brew.
|
|
105
|
-
execSyncShell("brew install aptos");
|
|
106
|
-
// Get the path of the CLI.
|
|
107
|
-
path = getCliPathBrew();
|
|
108
|
-
} else {
|
|
109
|
-
// Download the zip file, extract it, and move the binary to the correct location.
|
|
110
|
-
execSync(
|
|
111
|
-
`curl -L -o /tmp/aptos.zip ${url}; unzip -o -q /tmp/aptos.zip -d /tmp; mv /tmp/aptos ${path};`
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const main = async () => {
|
|
117
|
-
const os = getOS();
|
|
118
|
-
|
|
119
|
-
let path;
|
|
120
|
-
if (os === "MacOS") {
|
|
121
|
-
// Confirm brew is installed.
|
|
122
|
-
const brewInstalled = executableIsAvailable("brew");
|
|
123
|
-
if (!brewInstalled) {
|
|
124
|
-
throw "Please install brew to continue: https://brew.sh/";
|
|
125
|
-
}
|
|
126
|
-
try {
|
|
127
|
-
path = getCliPathBrew();
|
|
128
|
-
} catch (e) {
|
|
129
|
-
path = "";
|
|
130
|
-
}
|
|
131
|
-
} else if (os === "Windows") {
|
|
132
|
-
path = `${__dirname}\\${PNAME}.exe`;
|
|
133
|
-
} else {
|
|
134
|
-
path = `${__dirname}/${PNAME}`;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Look up the latest version.
|
|
138
|
-
const latestVersion = await getLatestVersion();
|
|
139
|
-
|
|
140
|
-
// If binary does not exist, download it.
|
|
141
|
-
if (!fs.existsSync(path)) {
|
|
142
|
-
console.log("CLI not installed");
|
|
143
|
-
// Install the latest version.
|
|
144
|
-
installCli(os, path, latestVersion);
|
|
145
|
-
} else {
|
|
146
|
-
// Get the current version of the CLI.
|
|
147
|
-
const currentVersion = execSyncShell(`${path} --version`, {
|
|
148
|
-
encoding: "utf8",
|
|
149
|
-
})
|
|
150
|
-
.trim()
|
|
151
|
-
.split(" ")[1];
|
|
152
|
-
console.log(
|
|
153
|
-
`Previously installed CLI version ${currentVersion}, checking for updates`
|
|
154
|
-
);
|
|
155
|
-
// Check if the installed version is the latest version.
|
|
156
|
-
if (currentVersion !== latestVersion) {
|
|
157
|
-
console.log(`A newer version of the CLI is available: ${latestVersion}`);
|
|
158
|
-
installCli(os, path, latestVersion);
|
|
159
|
-
} else {
|
|
160
|
-
console.log(`CLI is up to date`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Spawn a child process to execute the binary with the provided arguments.
|
|
165
|
-
if (os === "Windows") {
|
|
166
|
-
spawn(path, process.argv.slice(2), {
|
|
167
|
-
stdio: "inherit",
|
|
168
|
-
shell: true,
|
|
169
|
-
});
|
|
170
|
-
} else {
|
|
171
|
-
spawn(path, process.argv.slice(2), {
|
|
172
|
-
stdio: "inherit",
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
main().catch(console.error);
|