Skip to content

Commit

Permalink
feat(config): add config commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Alnyli07 committed Jan 23, 2024
1 parent a920471 commit 54b3adc
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 67 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"scripts": {
"watch": "rm -rf dist && tsc -w",
"build": "rm -rf dist && tsc",
"postversion": "git push && git push --tags"
"postversion": "git push && git push --tags",
"postuninstall": "node ./scripts/appcircle-uninstall.js"
},
"repository": {
"type": "git",
Expand All @@ -32,6 +33,7 @@
"axios": "^0.27.1",
"chalk": "^4.1.1",
"commander": "^11.1.0",
"conf": "10.2.0",
"enquirer": "^2.3.6",
"esm": "^3.2.25",
"form-data": "^4.0.0",
Expand Down
2 changes: 2 additions & 0 deletions scripts/appcircle-uninstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('../dist/config.js').clearConfigs();
88 changes: 48 additions & 40 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/**
* Implements CRUD options from a file. Replaces the usage of a database, acts like environment variables.
*/
import fs from "fs";
import jsonfile from "jsonfile";
import path from "path";

const FILE_NAME = "../data.json";
import Conf from "conf";

/**
* This variable exists only to specify which environment variables are being used.
Expand All @@ -14,67 +10,79 @@ export enum EnvironmentVariables {
AC_ACCESS_TOKEN = "AC_ACCESS_TOKEN",
API_HOSTNAME = "API_HOSTNAME",
AUTH_HOSTNAME = "AUTH_HOSTNAME",
OUTPUT = "plain",
}

const DefaultEnvironmentVariables = {
export const DefaultEnvironmentVariables = {
API_HOSTNAME: "https://api.appcircle.io",
AUTH_HOSTNAME: "https://auth.appcircle.io",
AC_ACCESS_TOKEN: "",
};

export type ConsoleOutputType = "json" | "plain"
const config = new Conf<{ current: string; envs: { [key: string]: typeof DefaultEnvironmentVariables } }>({
defaults: { current: "default", envs: { default: DefaultEnvironmentVariables } },
});

export type ConsoleOutputType = "json" | "plain";

let output_type = (process.env.CONSOLE_OUTPUT_TYPE || "plain") as ConsoleOutputType;

export const setConsoleOutputType = (type:ConsoleOutputType) => {
export const setConsoleOutputType = (type: ConsoleOutputType) => {
output_type = type;
};
export const getConsoleOutputType = () => {
return output_type;
};

export function writeVariable(variable: EnvironmentVariables, value: string): void {
const currentPath = path.join(__dirname, "", FILE_NAME);
export function getConfigStore(): any {
return { ...config.store };
}

export function getConfigFilePath(): any {
return config.path;
}


export function getCurrentConfigVariable(): string {
return config.get('current') || 'default';
}

export function setCurrentConfigVariable(val: string = 'default'): void {
config.set('current', val);
}


export function addNewConfigVariable(val: string = 'new'): void {
config.set('current', val);
config.set(`envs.${val}`, DefaultEnvironmentVariables);
}

export const getEnviromentsConfigToWriting = () => {
let resEnvs = {} as any;
Object.keys(config.store.envs).forEach( (key) => {
resEnvs[key] = { ...config.store.envs[key], AC_ACCESS_TOKEN: (config.store.envs[key].AC_ACCESS_TOKEN||'').substring(0,10)+"..." };
});
return resEnvs;
}

export function writeEnviromentConfigVariable(variable: EnvironmentVariables, value: string): void {
const current = config.get('current') || 'default';
try {
const currentData = jsonfile.readFileSync(currentPath);
currentData[variable] = value;
jsonfile.writeFile(currentPath, currentData, { flag: "w+" });
config.set(`envs.${current}.${variable}`, value);
} catch {
console.error("Could not write variable to the file.");
console.error("Could not write variable to the config file.");
}
}

export function readVariable(variable: EnvironmentVariables): string {
const currentPath = path.join(__dirname, "", FILE_NAME);
export function readEnviromentConfigVariable(variable: EnvironmentVariables): string {
const current = config.get('current') || 'default';
try {
const currentData = jsonfile.readFileSync(currentPath);
return currentData[variable] || "";
return config.get(`envs.${current}.${variable}`) || "";
} catch {
console.error("Could not read data, returning empty.");
return "";
}
}

/**
* Prioritizes environment variables over the file contents.
*/
function initializeFile() {
const currentPath = path.join(__dirname, "", FILE_NAME);
let currentData = { ...DefaultEnvironmentVariables };
if (fs.existsSync(currentPath)) {
try {
currentData = jsonfile.readFileSync(currentPath);
} catch (e) {
console.info("Corrupted data.json file, rewriting it...");
}
}
for (const key in EnvironmentVariables) {
(currentData as any)[key] = process.env[key] || (currentData as any)[key] || (DefaultEnvironmentVariables as any)[key];
}
jsonfile.writeFileSync(currentPath, currentData, { flag: "w+" });
export function clearConfigs() {
config.clear();
}

(async () => {
initializeFile();
})();
74 changes: 70 additions & 4 deletions src/core/command-runner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import path from "path";
import os from "os";
import { CommandTypes } from "./commands";
import { writeVariable, EnvironmentVariables } from "../config";
import {
EnvironmentVariables,
addNewConfigVariable,
clearConfigs,
getConfigFilePath,
getConfigStore,
getConsoleOutputType,
getCurrentConfigVariable,
getEnviromentsConfigToWriting,
readEnviromentConfigVariable,
setCurrentConfigVariable,
writeEnviromentConfigVariable,
} from "../config";
import { createOra } from "../utils/orahelper";
import { ProgramCommand } from "../program";
import {
Expand Down Expand Up @@ -30,17 +42,67 @@ import {
uploadEnterpriseAppVersion,
getEnterpriseDownloadLink,
} from "../services";
import { commandWriter } from "./writer";
import { commandWriter, configWriter } from "./writer";

const handleConfigCommand = (command: ProgramCommand) => {
const action = command.name();
const key = (command.args()[0] || "");
if (action === "list") {
const store = getConfigStore();
if (getConsoleOutputType() === "json") {
configWriter(store);
} else {
configWriter({ "current": store.current, path: getConfigFilePath() });
configWriter(getEnviromentsConfigToWriting());
}
} else if (action === "set") {
writeEnviromentConfigVariable(key, command.args()[1]);
configWriter({ [key]: readEnviromentConfigVariable(key)});
} else if (action === "get") {
configWriter({ [key]: readEnviromentConfigVariable(key)});
} else if (action === "current") {
const store = getConfigStore();
if(key){
if(store.envs[key]){
setCurrentConfigVariable(key);
configWriter({ "current": getCurrentConfigVariable() });
}else{
throw new Error("Config command 'current' action requires a valid value");
}
}else{
throw new Error("Config command 'current' action requires a value");
}
}else if (action === "add") {
if(key){
addNewConfigVariable(key);
configWriter({ "current": getCurrentConfigVariable() });
configWriter(getEnviromentsConfigToWriting());
}else{
throw new Error("Config command 'add' action requires a value(key)");
}
}else if (action === "reset") {
clearConfigs()
configWriter({ "current": getCurrentConfigVariable() });
configWriter(getEnviromentsConfigToWriting());
}else {
throw new Error("Config command action not found");
}
};

export const runCommand = async (command: ProgramCommand) => {
const params = command.opts() as any;
const commandName = command.name();
let responseData;


if(command.parent?.name() === 'config'){
return handleConfigCommand(command);
}

switch (commandName) {
case CommandTypes.LOGIN: {
responseData = await getToken(params);
writeVariable(EnvironmentVariables.AC_ACCESS_TOKEN, responseData.access_token);
writeEnviromentConfigVariable(EnvironmentVariables.AC_ACCESS_TOKEN, responseData.access_token);
commandWriter(CommandTypes.LOGIN, responseData);
break;
}
Expand Down Expand Up @@ -211,9 +273,13 @@ export const runCommand = async (command: ProgramCommand) => {
commandWriter(CommandTypes.GET_ENTERPRISE_DOWNLOAD_LINK, responseData);
break;
}
case "config":
handleConfigCommand(command);
break;
default: {
console.log('Coomd: ', command.name(), command.args())
console.error("Command not found");
break;
process.exit(1);
}
}
};
16 changes: 12 additions & 4 deletions src/core/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const CommandParameterTypes = {
};

export enum CommandTypes {
CONFIG = "config",
LOGIN = "login",
LIST_BUILD_PROFILES = "listBuildProfiles",
LIST_BUILD_PROFILE_BRANCHES = "listBuildProfileBranches",
Expand Down Expand Up @@ -38,6 +39,7 @@ export enum CommandTypes {
export const Commands: {
command: string;
description: string;
ignore?: boolean;
params: {
name: string;
description: string;
Expand All @@ -50,6 +52,12 @@ export const Commands: {
defaultValue?: any;
}[];
}[] = [
{
command: CommandTypes.CONFIG,
ignore: true,
description: "Config",
params: [],
},
{
command: CommandTypes.LOGIN,
description: "Login",
Expand Down Expand Up @@ -178,15 +186,15 @@ export const Commands: {
{
name: "branch",
description: "Branch Name",
type: 'string',
type: "string",
valueType: "string",
required: false,
params: [],
},
{
name: "workflow",
description: "Workflow Name",
type: 'string',
type: "string",
valueType: "string",
required: false,
params: [],
Expand Down Expand Up @@ -343,15 +351,15 @@ export const Commands: {
type: CommandParameterTypes.STRING,
valueType: "string",
required: false,
paramType: 'text'
paramType: "text",
},
{
name: "filePath",
description: `File Path`,
type: CommandParameterTypes.STRING,
valueType: "string",
required: false,
paramType: 'file'
paramType: "file",
},
],
},
Expand Down
Loading

0 comments on commit 54b3adc

Please sign in to comment.