Skip to content

Commit

Permalink
Merge pull request #71 from AElfProject/feature/ts
Browse files Browse the repository at this point in the history
Feature/ts
  • Loading branch information
hzz780 authored Jul 2, 2024
2 parents 2b4e1be + 99e709f commit 2995bed
Show file tree
Hide file tree
Showing 67 changed files with 1,720 additions and 373 deletions.
2 changes: 2 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// inquirer-search-list doesn't provide an available types
declare module 'inquirer-search-list';
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"name": "aelf-command",
"version": "0.1.47-beta.4",
"version": "0.1.47-beta.5",
"description": "A CLI tools for AElf",
"main": "src/index.js",
"type": "module",
"types": "types/index.d.ts",
"scripts": {
"commit": "git-cz",
"lint": "eslint src",
Expand All @@ -12,7 +13,8 @@
"test:watch": "jest --config=jest.config.js --watch --detectOpenHandles",
"test:coverage": "jest --config=jest.config.js --coverage --detectOpenHandles",
"prepare": "husky",
"lint-staged": "lint-staged"
"lint-staged": "lint-staged",
"tsc": "tsc"
},
"preferGlobal": true,
"repository": {
Expand Down Expand Up @@ -76,6 +78,7 @@
"@commitlint/config-conventional": "^19.2.2",
"@eslint/compat": "^1.0.3",
"@eslint/eslintrc": "^3.1.0",
"@types/inquirer": "^9.0.7",
"commitizen": "^4.3.0",
"commitlint": "^19.3.0",
"cross-env": "^7.0.3",
Expand All @@ -91,8 +94,9 @@
"jest": "^29.7.0",
"lint-staged": "^15.2.5",
"prettier": "^3.3.2",
"socket.io-client": "^4.7.5",
"standard-version": "^9.5.0"
"standard-version": "^9.5.0",
"typescript": "^5.5.2",
"socket.io-client": "^4.7.5"
},
"keywords": [
"AElf",
Expand Down
74 changes: 62 additions & 12 deletions src/command/baseSubCommand.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/**
* @file base sub command
* @author atom-yang
*/
import { interopImportCJSDefault } from 'node-cjs-interop';
import asyncValidator from 'async-validator';
const Schema = interopImportCJSDefault(asyncValidator);

import inquirer from 'inquirer';
import ora from 'ora';
import { logger } from '../utils/myLogger.js';
Expand All @@ -16,17 +13,25 @@ import { globalOptionsPrompts, strictGlobalOptionValidatorDesc } from '../utils/
const defaultOraOptions = {
text: 'AElf loading...'
};
/**
* @typedef {import('commander').Command} Command
* @typedef {import('ora').Options} OraOptions
* @typedef {import('../../types/rc/index.js').default} Registry
*/

/**
* @class
*/
class BaseSubCommand {
/**
* @param {string} commandName sub command name
* @param {Object[]} parameters sub command parameters
* @param {{ [key: string]: any }[]} parameters sub command parameters
* @param {string} description sub command description
* @param {Object[]} options sub command options
* @param {{ [key: string]: any }[]} options sub command options
* @param {string[]} usage make examples
* @param {Registry} rc instance of Registry
* @param {Object} validatorDesc rules of async-validator
* @param {Object} oraOptions an ora options
* @param {{ [key: string]: any }} validatorDesc rules of async-validator
* @param {{ [key: string]: any }} oraOptions an ora options
*/
constructor(
commandName,
Expand Down Expand Up @@ -54,11 +59,17 @@ class BaseSubCommand {
};
});
}

/**
* Sets custom prompts.
* @param {any} val - The value to set for custom prompts.
*/
setCustomPrompts(val) {
this.customPrompts = val;
}

/**
* Initializes the sub command with commander.
* @param {Command} commander - The commander instance.
*/
init(commander) {
let command = commander.command(`${this.commandName} ${this.getParameters()}`).description(this.description);

Expand All @@ -79,6 +90,10 @@ class BaseSubCommand {
});
}

/**
* Retrieves parameters as a string.
* @returns {string} Parameters string.
*/
getParameters() {
return this.parameters
.map(v => {
Expand All @@ -89,12 +104,23 @@ class BaseSubCommand {
.join(' ');
}

/**
* Handles errors related to universal options.
* @param {any} error - The error to handle.
*/
handleUniOptionsError(error) {
const { errors = [] } = error;
// @ts-ignore
logger.error(errors.reduce((acc, i) => `${acc}${i.message}\n`, ''));
process.exit(1);
}

/**
* Retrieves universal configuration.
* @static
* @param {Command} commander - The commander instance.
* @returns {Record<string, any>} Universal configuration.
*/
static getUniConfig(commander) {
const result = {};
['password', 'endpoint', 'account', 'datadir'].forEach(v => {
Expand All @@ -106,6 +132,12 @@ class BaseSubCommand {
return result;
}

/**
* Parses a boolean value.
* @static
* @param {any} val - The value to parse.
* @returns {any} Parsed boolean value.
*/
static parseBoolean(val) {
if (val === 'true') {
return true;
Expand All @@ -116,6 +148,12 @@ class BaseSubCommand {
return val;
}

/**
* Normalizes configuration object.
* @static
* @param {any} obj - The configuration object to normalize.
* @returns {Record<string, any>} Normalized configuration object.
*/
static normalizeConfig(obj) {
// dash to camel-case
// 'true', 'false' to true, false
Expand All @@ -128,7 +166,16 @@ class BaseSubCommand {
});
return result;
}

/**
* Runs the sub command.
* @param {Command} commander - The commander instance.
* @param {...any} args - Additional arguments.
* @returns {Promise<{
* localOptions: { [key: string]: any },
* options: { [key: string]: any },
* subOptions: { [key: string]: any }
* } | void>} Promise resolving to options or void.
*/
async run(commander, ...args) {
let subCommandOptions = {};
args.slice(0, this.parameters.length).forEach((v, i) => {
Expand Down Expand Up @@ -188,7 +235,10 @@ class BaseSubCommand {
subOptions: subCommandOptions
};
}

/**
* Generates examples for usage.
* @returns {string[]} Array of example strings.
*/
makeExamples() {
return this.usage.map(cmd => `aelf-command ${this.commandName} ${cmd}`);
}
Expand Down
42 changes: 36 additions & 6 deletions src/command/call.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/**
* @file call read-only method on contract
* @author atom-yang
*/
import AElf from 'aelf-sdk';
import inquirer from 'inquirer';
import chalk from 'chalk';
Expand All @@ -18,7 +14,21 @@ import {
import { getWallet } from '../utils/wallet.js';
import { logger } from '../utils/myLogger.js';

/**
* @typedef {import('commander').Command} Command
* @typedef {import('ora').Options} OraOptions
* @typedef {import('../../types/rc/index.js').default} Registry
*/
class CallCommand extends BaseSubCommand {
/**
* Creates an instance of CallCommand.
* @param {Registry} rc The instance of the Registry.
* @param {string} [name] The name of the command.
* @param {string} [description] The description of the command.
* @param {Object[]} [parameters] The parameters for the command.
* @param {string[]} [usage] The usage examples for the command.
* @param {any[]} [options] The options for the command.
*/
constructor(
rc,
name = 'call',
Expand All @@ -29,22 +39,40 @@ class CallCommand extends BaseSubCommand {
) {
super(name, parameters, description, options, usage, rc);
}

/**
* Calls a method with specified parameters.
* @param {any} method The method to call.
* @param {any} params The parameters for the method call.
* @returns {Promise<any>} A promise that resolves with the result of the method call.
*/
async callMethod(method, params) {
this.oraInstance.start('Calling method...');
const result = await method.call(params);
this.oraInstance.succeed('Calling method successfully!');
return result;
}

/**
* Processes address after prompting for input.
* @param {any} aelf The AElf instance.
* @param {any} wallet The wallet instance.
* @param {Object.<string, any>} answerInput The input parameters.
* @returns {Promise<any>} A promise that resolves with the processed result.
*/
async processAddressAfterPrompt(aelf, wallet, answerInput) {
let { contractAddress } = BaseSubCommand.normalizeConfig(answerInput);
contractAddress = await getContractInstance(contractAddress, aelf, wallet, this.oraInstance);
return contractAddress;
}

/**
* Runs the command.
* @param {Command} commander The Commander instance.
* @param {...any[]} args Additional arguments passed to the command.
* @returns {Promise<void>} A promise that resolves when the command execution completes.
*/
async run(commander, ...args) {
this.setCustomPrompts(true);
// @ts-ignore
const { options, subOptions } = await super.run(commander, ...args);
const subOptionsLength = Object.keys(subOptions).length;
const { endpoint, datadir, account, password } = options;
Expand Down Expand Up @@ -102,10 +130,12 @@ class CallCommand extends BaseSubCommand {
params = '';
}
const result = await this.callMethod(method, params);
// @ts-ignore
logger.info(`\nResult:\n${JSON.stringify(result, null, 2)}`);
this.oraInstance.succeed('Succeed!');
} catch (e) {
this.oraInstance.fail('Failed!');
// @ts-ignore
logger.fatal(e);
}
}
Expand Down
36 changes: 30 additions & 6 deletions src/command/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/**
* @file get block height
* @author atom-yang
*/
import { interopImportCJSDefault } from 'node-cjs-interop';
import asyncValidator from 'async-validator';
const Schema = interopImportCJSDefault(asyncValidator);
Expand All @@ -17,7 +13,17 @@ const configCommandValidatorDesc = {
}
};

/**
* @typedef {import('commander').Command} Command
* @typedef {import('async-validator').Rules} Rules
* @typedef {import('async-validator').Values} Values
* @typedef {import('../../types/rc/index.js').default} Registry
*/
class ConfigCommand extends BaseSubCommand {
/**
* Constructs a new ConfigCommand instance.
* @param {Registry} rc - The registry instance.
*/
constructor(rc) {
super(
'config',
Expand All @@ -29,7 +35,12 @@ class ConfigCommand extends BaseSubCommand {
configCommandValidatorDesc
);
}

/**
* Validates parameters based on the provided rules.
* @param {Rules} rule - The validation rules.
* @param {Values} parameters - The parameters to validate.
* @returns {Promise<void>} A promise that resolves when the validation is complete.
*/
async validateParameters(rule, parameters) {
const validator = new Schema(rule);
try {
Expand All @@ -39,6 +50,11 @@ class ConfigCommand extends BaseSubCommand {
}
}

/**
* Handles the list operation and returns the processed content as a string.
* @param {any} content - The content to process.
* @returns {string} The processed content.
*/
handleList(content) {
return Object.entries(content)
.filter(([, value]) => {
Expand All @@ -50,9 +66,15 @@ class ConfigCommand extends BaseSubCommand {
.map(([key, value]) => `${key}=${value}\n`)
.join('');
}

/**
* Executes the command.
* @param {Command} commander - The commander instance.
* @param {...any} args - Additional arguments.
* @returns {Promise<void>} A promise that resolves when the command execution is complete.
*/
async run(commander, ...args) {
this.setCustomPrompts(true);
// @ts-ignore
const { subOptions } = await super.run(commander, ...args);
// todo: specified which .aelfrc file to read or write
const { flag, key, value } = subOptions;
Expand Down Expand Up @@ -85,6 +107,7 @@ class ConfigCommand extends BaseSubCommand {
switch (flag) {
case 'get':
result = this.rc.getOption(key);
// @ts-ignore
logger.info(result);
break;
case 'set':
Expand All @@ -102,6 +125,7 @@ class ConfigCommand extends BaseSubCommand {
}
} catch (e) {
this.oraInstance.fail('Failed!');
// @ts-ignore
logger.error(e);
}
}
Expand Down
Loading

0 comments on commit 2995bed

Please sign in to comment.