From 3fcfea74878ba8a4f8eb4ab25bc9eb75c444028f Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sun, 24 Feb 2019 11:41:58 +0200 Subject: [PATCH 1/8] feat(core): configuration and channel support for the CLI --- packages/core/package.json | 5 ++- packages/core/src/commands/config/cli.ts | 44 +++++++++++++++++++ packages/core/src/helpers/config.ts | 31 +++++++++++++ packages/core/src/helpers/update.ts | 2 +- packages/core/src/hooks/init/config.ts | 7 +++ .../src/hooks/{init.ts => init/update.ts} | 2 +- 6 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 packages/core/src/commands/config/cli.ts create mode 100644 packages/core/src/helpers/config.ts create mode 100644 packages/core/src/hooks/init/config.ts rename packages/core/src/hooks/{init.ts => init/update.ts} (80%) diff --git a/packages/core/package.json b/packages/core/package.json index 2ec9f4d436..53001755d7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -122,7 +122,10 @@ "oclif": { "commands": "./dist/commands", "hooks": { - "init": "./dist/hooks/init" + "init": [ + "./dist/hooks/init/config", + "./dist/hooks/init/update" + ] }, "bin": "ark", "topics": { diff --git a/packages/core/src/commands/config/cli.ts b/packages/core/src/commands/config/cli.ts new file mode 100644 index 0000000000..9489601288 --- /dev/null +++ b/packages/core/src/commands/config/cli.ts @@ -0,0 +1,44 @@ +import { flags } from "@oclif/command"; +import { configManager } from "../../helpers/config"; +import { BaseCommand } from "../command"; + +export class CommandLineInterfaceCommand extends BaseCommand { + public static description: string = "Update the CLI configuration"; + + public static examples: string[] = [ + `Set the token that should be used for configuration +$ yarn ark config:cli --token=mine +`, + `Switch the npm registry channel +$ yarn ark config:cli --channel=mine +`, + ]; + + public static flags: Record = { + token: flags.string({ + description: "the name of the token that should be used", + }), + channel: flags.string({ + description: "the name of the token that should be used", + options: ["alpha", "beta", "rc", "stable"], + }), + }; + + public async run(): Promise { + const { flags } = this.parse(CommandLineInterfaceCommand); + + if (flags.token) { + configManager.update({ token: flags.token }); + } + + if (flags.channel) { + let channel = flags.channel; + + if (channel === "stable") { + channel = "latest"; + } + + configManager.update({ channel }); + } + } +} diff --git a/packages/core/src/helpers/config.ts b/packages/core/src/helpers/config.ts new file mode 100644 index 0000000000..cac6db58bc --- /dev/null +++ b/packages/core/src/helpers/config.ts @@ -0,0 +1,31 @@ +import { readFileSync, writeFileSync } from "fs"; +import { getUpdateChannel } from "./update"; + +class ConfigManager { + private config; + private file: string; + + public setup(config) { + this.config = config; + this.file = `${config.configDir}/config.json`; + + this.ensureDefaults(); + } + + public update(data) { + this.write({ ...JSON.parse(readFileSync(this.file).toString()), ...data }); + } + + private ensureDefaults() { + this.write({ + token: this.config.bin, + channel: getUpdateChannel(this.config), + }); + } + + private write(data) { + writeFileSync(this.file, JSON.stringify(data, null, 4)); + } +} + +export const configManager = new ConfigManager(); diff --git a/packages/core/src/helpers/update.ts b/packages/core/src/helpers/update.ts index ed6909f30a..b50e5c9db9 100644 --- a/packages/core/src/helpers/update.ts +++ b/packages/core/src/helpers/update.ts @@ -26,7 +26,7 @@ function ensureCacheFile(config: IConfig): string { return join(config.cacheDir, "update"); } -function getUpdateChannel(config: IConfig): string { +export function getUpdateChannel(config: IConfig): string { const channels: string[] = ["alpha", "beta", "rc"]; let channel: string = "latest"; diff --git a/packages/core/src/hooks/init/config.ts b/packages/core/src/hooks/init/config.ts new file mode 100644 index 0000000000..0999f41832 --- /dev/null +++ b/packages/core/src/hooks/init/config.ts @@ -0,0 +1,7 @@ +import { Hook } from "@oclif/config"; +import { configManager } from "../../helpers/config"; + +// tslint:disable-next-line:only-arrow-functions +export const init: Hook<"init"> = async function({ config }) { + configManager.setup(config); +}; diff --git a/packages/core/src/hooks/init.ts b/packages/core/src/hooks/init/update.ts similarity index 80% rename from packages/core/src/hooks/init.ts rename to packages/core/src/hooks/init/update.ts index 7f36278345..978d2dce13 100644 --- a/packages/core/src/hooks/init.ts +++ b/packages/core/src/hooks/init/update.ts @@ -1,5 +1,5 @@ import { Hook } from "@oclif/config"; -import { checkForUpdates, needsRefresh } from "../helpers/update"; +import { checkForUpdates, needsRefresh } from "../../helpers/update"; // tslint:disable-next-line:only-arrow-functions export const init: Hook<"init"> = async function({ id, config }) { From e9c38f746dbf52eb8c22de3263a7c3a3f4da1876 Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sun, 24 Feb 2019 11:46:16 +0200 Subject: [PATCH 2/8] fix(core): use the configured channel for updates --- packages/core/src/helpers/config.ts | 10 +++++++++- packages/core/src/helpers/update.ts | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/core/src/helpers/config.ts b/packages/core/src/helpers/config.ts index cac6db58bc..8d20bd14a1 100644 --- a/packages/core/src/helpers/config.ts +++ b/packages/core/src/helpers/config.ts @@ -12,8 +12,12 @@ class ConfigManager { this.ensureDefaults(); } + public get(key) { + return this.read()[key]; + } + public update(data) { - this.write({ ...JSON.parse(readFileSync(this.file).toString()), ...data }); + this.write({ ...this.read(), ...data }); } private ensureDefaults() { @@ -23,6 +27,10 @@ class ConfigManager { }); } + private read() { + return JSON.parse(readFileSync(this.file).toString()); + } + private write(data) { writeFileSync(this.file, JSON.stringify(data, null, 4)); } diff --git a/packages/core/src/helpers/update.ts b/packages/core/src/helpers/update.ts index b50e5c9db9..1e71d72167 100644 --- a/packages/core/src/helpers/update.ts +++ b/packages/core/src/helpers/update.ts @@ -9,6 +9,7 @@ import latestVersion from "latest-version"; import { join } from "path"; import prompts from "prompts"; import semver from "semver"; +import { configManager } from "./config"; async function getVersionFromNode(name: string, channel: string): Promise { try { @@ -61,7 +62,7 @@ export async function checkForUpdates({ config, error, log, warn }): Promise Date: Sun, 24 Feb 2019 11:50:48 +0200 Subject: [PATCH 3/8] fix(core): use the configured token if no token is passed in --- packages/core/src/commands/command.ts | 7 +++++-- packages/core/src/commands/config/publish.ts | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/core/src/commands/command.ts b/packages/core/src/commands/command.ts index 22c771d0bc..ea72eed2a9 100644 --- a/packages/core/src/commands/command.ts +++ b/packages/core/src/commands/command.ts @@ -6,6 +6,7 @@ import Listr from "listr"; import { join, resolve } from "path"; import pm2 from "pm2"; import prompts from "prompts"; +import { configManager } from "../helpers/config"; // tslint:disable-next-line:no-var-requires const { version } = require("../../package.json"); @@ -16,8 +17,6 @@ export abstract class BaseCommand extends Command { public static flagsNetwork: Record = { token: flags.string({ description: "the name of the token that should be used", - default: "ark", - required: true, }), network: flags.string({ description: "the name of the network that should be used", @@ -129,6 +128,10 @@ export abstract class BaseCommand extends Command { protected async parseWithNetwork(command: any): Promise { const { args, flags } = this.parse(command); + if (!flags.token) { + flags.token = configManager.get("token"); + } + if (process.env.CORE_PATH_CONFIG && !flags.network) { let config: string = process.env.CORE_PATH_CONFIG; diff --git a/packages/core/src/commands/config/publish.ts b/packages/core/src/commands/config/publish.ts index 9ace57a285..b3ad7b71b4 100644 --- a/packages/core/src/commands/config/publish.ts +++ b/packages/core/src/commands/config/publish.ts @@ -2,6 +2,7 @@ import { flags } from "@oclif/command"; import fs from "fs-extra"; import { resolve } from "path"; import prompts from "prompts"; +import { configManager } from "../../helpers/config"; import { BaseCommand } from "../command"; export class PublishCommand extends BaseCommand { @@ -20,6 +21,10 @@ $ ark config:publish --network=mainnet public async run(): Promise { const { flags } = this.parse(PublishCommand); + if (!flags.token) { + flags.token = configManager.get("token"); + } + if (flags.network) { return this.performPublishment(flags); } From d7ba8b15058d36aa321c935ff70e8c4d9d9a83b0 Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sun, 24 Feb 2019 12:13:35 +0200 Subject: [PATCH 4/8] Update cli.ts --- packages/core/src/commands/config/cli.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/commands/config/cli.ts b/packages/core/src/commands/config/cli.ts index 9489601288..e646ab14a4 100644 --- a/packages/core/src/commands/config/cli.ts +++ b/packages/core/src/commands/config/cli.ts @@ -7,10 +7,10 @@ export class CommandLineInterfaceCommand extends BaseCommand { public static examples: string[] = [ `Set the token that should be used for configuration -$ yarn ark config:cli --token=mine +$ ark config:cli --token=mine `, `Switch the npm registry channel -$ yarn ark config:cli --channel=mine +$ ark config:cli --channel=mine `, ]; From 2c678f8ee9d25e4208bf9c87ef664494ec275337 Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sun, 24 Feb 2019 18:44:15 +0200 Subject: [PATCH 5/8] feat(core): install core from the selected channel --- packages/core/package.json | 2 +- packages/core/src/commands/config/cli.ts | 34 +++++++++++++++++++----- packages/core/src/helpers/config.ts | 27 ++++++++++++------- packages/core/src/helpers/update.ts | 22 ++++++++------- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 53001755d7..36fc0ea17c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -23,7 +23,7 @@ "publish:alpha": "npm publish --tag alpha", "publish:beta": "npm publish --tag beta", "publish:rc": "npm publish --tag rc", - "publish:stable": "npm publish --tag latest", + "publish:latest": "npm publish --tag latest", "prepublishOnly": "yarn build", "pretest": "yarn lint && yarn build", "prepack": "oclif-dev manifest && npm shrinkwrap", diff --git a/packages/core/src/commands/config/cli.ts b/packages/core/src/commands/config/cli.ts index 9489601288..adb0aafeeb 100644 --- a/packages/core/src/commands/config/cli.ts +++ b/packages/core/src/commands/config/cli.ts @@ -1,5 +1,8 @@ import { flags } from "@oclif/command"; +import cli from "cli-ux"; +import { removeSync } from "fs-extra"; import { configManager } from "../../helpers/config"; +import { installFromChannel } from "../../helpers/update"; import { BaseCommand } from "../command"; export class CommandLineInterfaceCommand extends BaseCommand { @@ -20,7 +23,7 @@ $ yarn ark config:cli --channel=mine }), channel: flags.string({ description: "the name of the token that should be used", - options: ["alpha", "beta", "rc", "stable"], + options: ["alpha", "beta", "rc", "latest"], }), }; @@ -32,13 +35,32 @@ $ yarn ark config:cli --channel=mine } if (flags.channel) { - let channel = flags.channel; + this.changeChannel(flags.channel); + } + } + + private async changeChannel(newChannel): Promise { + const oldChannel = configManager.get("channel"); + + if (oldChannel === newChannel) { + this.warn(`You are already on the "${newChannel}" channel.`); + return; + } + + configManager.update({ channel: newChannel }); + + const pkg = `${this.config.name}@${newChannel}`; + + try { + cli.action.start(`Installing ${pkg}`); + + await installFromChannel(this.config.name, newChannel); - if (channel === "stable") { - channel = "latest"; - } + cli.action.stop(); - configManager.update({ channel }); + this.warn(`${pkg} has been installed. Please restart your relay and forger.`); + } catch (err) { + this.error(err.message); } } } diff --git a/packages/core/src/helpers/config.ts b/packages/core/src/helpers/config.ts index 8d20bd14a1..9955d1b431 100644 --- a/packages/core/src/helpers/config.ts +++ b/packages/core/src/helpers/config.ts @@ -1,4 +1,5 @@ -import { readFileSync, writeFileSync } from "fs"; +import { existsSync, readFileSync, writeFileSync } from "fs"; +import { removeSync } from "fs-extra"; import { getUpdateChannel } from "./update"; class ConfigManager { @@ -9,29 +10,37 @@ class ConfigManager { this.config = config; this.file = `${config.configDir}/config.json`; - this.ensureDefaults(); + try { + this.read(); + } catch (error) { + removeSync(this.file); + + this.ensureDefaults(); + } } public get(key) { return this.read()[key]; } - public update(data) { + public update(data): void { this.write({ ...this.read(), ...data }); } - private ensureDefaults() { - this.write({ - token: this.config.bin, - channel: getUpdateChannel(this.config), - }); + private ensureDefaults(): void { + if (!existsSync(this.file)) { + this.write({ + token: this.config.bin, + channel: getUpdateChannel(this.config), + }); + } } private read() { return JSON.parse(readFileSync(this.file).toString()); } - private write(data) { + private write(data): void { writeFileSync(this.file, JSON.stringify(data, null, 4)); } } diff --git a/packages/core/src/helpers/update.ts b/packages/core/src/helpers/update.ts index 1e71d72167..df523f8dd1 100644 --- a/packages/core/src/helpers/update.ts +++ b/packages/core/src/helpers/update.ts @@ -53,6 +53,16 @@ export function needsRefresh(config: IConfig): boolean { } } +export async function installFromChannel(pkg, channel) { + const { stdout, stderr } = await shell(`yarn global add ${pkg}@${channel}`); + + if (stderr) { + console.error(stderr); + } + + console.log(stdout); +} + export async function checkForUpdates({ config, error, log, warn }): Promise { if (existsSync(join(__dirname, "../../../..", ".git"))) { if (!process.env.CORE_DEVELOPER_MODE) { @@ -91,24 +101,16 @@ export async function checkForUpdates({ config, error, log, warn }): Promise Date: Sun, 24 Feb 2019 18:47:14 +0200 Subject: [PATCH 6/8] refactor(core): rename getUpdateChannel to getRegistryChannel --- packages/core/src/helpers/config.ts | 4 ++-- packages/core/src/helpers/update.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/helpers/config.ts b/packages/core/src/helpers/config.ts index 9955d1b431..0ff09e7f3b 100644 --- a/packages/core/src/helpers/config.ts +++ b/packages/core/src/helpers/config.ts @@ -1,6 +1,6 @@ import { existsSync, readFileSync, writeFileSync } from "fs"; import { removeSync } from "fs-extra"; -import { getUpdateChannel } from "./update"; +import { getRegistryChannel } from "./update"; class ConfigManager { private config; @@ -31,7 +31,7 @@ class ConfigManager { if (!existsSync(this.file)) { this.write({ token: this.config.bin, - channel: getUpdateChannel(this.config), + channel: getRegistryChannel(this.config), }); } } diff --git a/packages/core/src/helpers/update.ts b/packages/core/src/helpers/update.ts index df523f8dd1..5dd1661ca7 100644 --- a/packages/core/src/helpers/update.ts +++ b/packages/core/src/helpers/update.ts @@ -27,7 +27,7 @@ function ensureCacheFile(config: IConfig): string { return join(config.cacheDir, "update"); } -export function getUpdateChannel(config: IConfig): string { +export function getRegistryChannel(config: IConfig): string { const channels: string[] = ["alpha", "beta", "rc"]; let channel: string = "latest"; From 9c3fcd9e7610b936ce0442812a8bd7fdf0f65bf2 Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sun, 24 Feb 2019 18:50:46 +0200 Subject: [PATCH 7/8] refactor(core): use JSON read/write methods --- packages/core/src/helpers/config.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/helpers/config.ts b/packages/core/src/helpers/config.ts index 0ff09e7f3b..e386e5e96f 100644 --- a/packages/core/src/helpers/config.ts +++ b/packages/core/src/helpers/config.ts @@ -1,5 +1,5 @@ -import { existsSync, readFileSync, writeFileSync } from "fs"; -import { removeSync } from "fs-extra"; +import { existsSync } from "fs"; +import { readJsonSync, removeSync, writeJsonSync } from "fs-extra"; import { getRegistryChannel } from "./update"; class ConfigManager { @@ -37,11 +37,11 @@ class ConfigManager { } private read() { - return JSON.parse(readFileSync(this.file).toString()); + return readJsonSync(this.file); } private write(data): void { - writeFileSync(this.file, JSON.stringify(data, null, 4)); + writeJsonSync(this.file, data); } } From b9c33a604a1d94830348d3046ae5825b1a2560f9 Mon Sep 17 00:00:00 2001 From: Edgar Goetzendorff Date: Sun, 24 Feb 2019 20:31:07 +0200 Subject: [PATCH 8/8] Update packages/core/src/commands/config/cli.ts Co-Authored-By: faustbrian --- packages/core/src/commands/config/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/commands/config/cli.ts b/packages/core/src/commands/config/cli.ts index a65f56da95..9e769c1614 100644 --- a/packages/core/src/commands/config/cli.ts +++ b/packages/core/src/commands/config/cli.ts @@ -22,7 +22,7 @@ $ ark config:cli --channel=mine description: "the name of the token that should be used", }), channel: flags.string({ - description: "the name of the token that should be used", + description: "the name of the channel that should be used", options: ["alpha", "beta", "rc", "latest"], }), };