diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..dc5cbf1 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,2 @@ +// inquirer-search-list doesn't provide an available types +declare module 'inquirer-search-list'; diff --git a/package.json b/package.json index ed3e9e9..eba6908 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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": { @@ -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", @@ -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", diff --git a/src/command/baseSubCommand.js b/src/command/baseSubCommand.js index d060cae..20752af 100644 --- a/src/command/baseSubCommand.js +++ b/src/command/baseSubCommand.js @@ -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'; @@ -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, @@ -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); @@ -79,6 +90,10 @@ class BaseSubCommand { }); } + /** + * Retrieves parameters as a string. + * @returns {string} Parameters string. + */ getParameters() { return this.parameters .map(v => { @@ -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} Universal configuration. + */ static getUniConfig(commander) { const result = {}; ['password', 'endpoint', 'account', 'datadir'].forEach(v => { @@ -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; @@ -116,6 +148,12 @@ class BaseSubCommand { return val; } + /** + * Normalizes configuration object. + * @static + * @param {any} obj - The configuration object to normalize. + * @returns {Record} Normalized configuration object. + */ static normalizeConfig(obj) { // dash to camel-case // 'true', 'false' to true, false @@ -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) => { @@ -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}`); } diff --git a/src/command/call.js b/src/command/call.js index 830cdd2..3779bdb 100644 --- a/src/command/call.js +++ b/src/command/call.js @@ -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'; @@ -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', @@ -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} 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.} answerInput The input parameters. + * @returns {Promise} 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} 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; @@ -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); } } diff --git a/src/command/config.js b/src/command/config.js index 08d94d4..b002d7d 100644 --- a/src/command/config.js +++ b/src/command/config.js @@ -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); @@ -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', @@ -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} A promise that resolves when the validation is complete. + */ async validateParameters(rule, parameters) { const validator = new Schema(rule); try { @@ -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]) => { @@ -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} 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; @@ -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': @@ -102,6 +125,7 @@ class ConfigCommand extends BaseSubCommand { } } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/console.js b/src/command/console.js index af8bd2b..d4e1fee 100644 --- a/src/command/console.js +++ b/src/command/console.js @@ -1,7 +1,3 @@ -/** - * @file console command - * @author atom-yang - */ import repl from 'repl'; import AElf from 'aelf-sdk'; import columnify from 'columnify'; @@ -10,12 +6,29 @@ import BaseSubCommand from './baseSubCommand.js'; import { getWallet } from '../utils/wallet.js'; import { logger } from '../utils/myLogger.js'; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class ConsoleCommand extends BaseSubCommand { + /** + * Constructs a new ConsoleCommand instance. + * @param {Registry} rc - The registry instance. + * @param {string} [name] - The name of the command. + * @param {string} [description] - The description of the command. + */ constructor(rc, name = 'console', description = 'Open a node REPL') { super(name, [], description, [], [''], rc); } + /** + * Executes the command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options } = await super.run(commander, ...args); const { datadir, account, password, endpoint } = options; try { @@ -45,7 +58,9 @@ class ConsoleCommand extends BaseSubCommand { } } ); + // @ts-ignore logger.info('Welcome to aelf interactive console. Ctrl + C to terminate the program. Double tap Tab to list objects'); + // @ts-ignore logger.info( boxen(columns, { padding: 1, @@ -61,6 +76,7 @@ class ConsoleCommand extends BaseSubCommand { r.context._account = wallet; } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/create.js b/src/command/create.js index 6eeefe2..b1f09e0 100644 --- a/src/command/create.js +++ b/src/command/create.js @@ -1,7 +1,3 @@ -/** - * @file create command - * @author atom-yang - */ import AElf from 'aelf-sdk'; import chalk from 'chalk'; import BaseSubCommand from './baseSubCommand.js'; @@ -16,8 +12,16 @@ const createCommandValidatorDesc = { required: false } }; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class CreateCommand extends BaseSubCommand { + /** + * Constructs a new CreateCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super( 'create', @@ -35,15 +39,26 @@ class CreateCommand extends BaseSubCommand { createCommandValidatorDesc ); } - + /** + * Executes the create command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { const wallet = AElf.wallet.createNewWallet(); wallet.publicKey = wallet.keyPair.getPublic().encode('hex'); + // @ts-ignore logger.info('Your wallet info is :'); + // @ts-ignore logger.info(`Mnemonic : ${wallet.mnemonic}`); + // @ts-ignore logger.info(`Private Key : ${wallet.privateKey}`); + // @ts-ignore logger.info(`Public Key : ${wallet.publicKey}`); + // @ts-ignore logger.info(`Address : ${wallet.address}`); + // @ts-ignore const { localOptions, options, subOptions } = await super.run(commander, ...args); const { datadir } = options; const { saveToFile } = subOptions; @@ -57,6 +72,7 @@ class CreateCommand extends BaseSubCommand { } } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/dappServer/HKDF.js b/src/command/dappServer/HKDF.js index 124ac3a..11dc6b9 100644 --- a/src/command/dappServer/HKDF.js +++ b/src/command/dappServer/HKDF.js @@ -1,8 +1,3 @@ -/** - * @file hkdf - * @author atom-yang - * @link https://asecuritysite.com/encryption/HKDF - */ import { createHmac } from 'crypto'; class HKDF { @@ -24,7 +19,14 @@ class HKDF { this.prk = hmac.digest(); } + /** + * Expands the pseudorandom key to the desired length. + * @param {string} [info] - Optional context and application-specific information. + * @param {number} [size] - The length of the output keying material in bytes. + * @returns {Buffer} - The expanded keying material. + */ expand(info = '', size = 32) { + /** @type {string | Buffer} */ let pre = ''; const output = []; const numBlocks = Math.ceil(size / this.hashLength); @@ -39,7 +41,10 @@ class HKDF { return Buffer.concat(output, size); } } - +/** + * A static property that maps hash algorithm names to their output lengths in bytes. + * @type {{ [key: string]: number }} + */ HKDF.hashList = { sha256: 32, sha224: 54, diff --git a/src/command/dappServer/constants.js b/src/command/dappServer/constants.js index 0e41c9d..b48994b 100644 --- a/src/command/dappServer/constants.js +++ b/src/command/dappServer/constants.js @@ -1,8 +1,3 @@ -/** - * @file constants - * @author atom-yang - */ - const CHAIN_APIS = { '/api/blockChain/chainStatus': 'getChainStatus', '/api/blockChain/blockState': 'getChainState', diff --git a/src/command/dappServer/encrypt.js b/src/command/dappServer/encrypt.js index 1bc80a6..ea2401d 100644 --- a/src/command/dappServer/encrypt.js +++ b/src/command/dappServer/encrypt.js @@ -1,7 +1,3 @@ -/** - * @file encrypt channel - * @author atom-yang - */ import Crypto from 'crypto'; import elliptic from 'elliptic'; import { randomId } from '../../utils/utils.js'; @@ -16,6 +12,13 @@ const keyPairs = { }; class Encrypt { + /** + * Creates an instance of Encrypt. + * @param {string} algorithm - The algorithm to use for encryption. + * @param {string} remotePublicKey - The public key of the remote party. + * @param {string} random - A random string used for key generation. + * @param {string} [cipher] - The cipher to use for encryption (optional). + */ constructor(algorithm, remotePublicKey, random, cipher = defaultCipher) { if (!keyPairs[algorithm]) { keyPairs[algorithm] = elliptic.ec(algorithm).genKeyPair(); @@ -29,14 +32,14 @@ class Encrypt { } /** - * encrypt data - * @param {WindowBase64} data - * @return {{encryptedResult: string, iv: string}} + * Encrypts data using the specified algorithm and shared key. + * @param {string} data - The data to encrypt. + * @returns {{ encryptedResult: string, iv: string }} - The encrypted data and initialization vector. */ encrypt(data) { const iv = randomId(); const cipher = Crypto.createCipheriv(this.cipher, this.derivedKey, Buffer.from(iv, 'hex')); - let encrypted = cipher.update(Buffer.from(data, 'base64'), null, 'base64'); + let encrypted = cipher.update(Buffer.from(data, 'base64'), undefined, 'base64'); encrypted += cipher.final('base64'); return { encryptedResult: encrypted, @@ -45,10 +48,10 @@ class Encrypt { } /** - * decrypt data - * @param {WindowBase64} encrypted - * @param {string} iv initial vector, hex string - * @return {string} result, base64 string + * Decrypts data using the specified algorithm and shared key. + * @param {string} encrypted - The encrypted data to decrypt. + * @param {string} iv - The initialization vector used during encryption. + * @returns {string} - The decrypted data. */ decrypt(encrypted, iv) { const decipher = Crypto.createDecipheriv(this.cipher, this.derivedKey, Buffer.from(iv, 'hex')); @@ -57,7 +60,8 @@ class Encrypt { } /** - * @return {string} hex string, public key + * Gets the public key of the key pair. + * @returns {string} - The public key in hexadecimal format. */ getPublicKey() { return this.keyPair.getPublic('hex'); diff --git a/src/command/dappServer/index.js b/src/command/dappServer/index.js index c3bac43..4d89053 100644 --- a/src/command/dappServer/index.js +++ b/src/command/dappServer/index.js @@ -1,7 +1,3 @@ -/** - * @file start a dapp server - * @author atom-yang - */ import AElf from 'aelf-sdk'; import BaseSubCommand from '../baseSubCommand.js'; import { getWallet } from '../../utils/wallet.js'; @@ -17,20 +13,32 @@ const commandOptions = [ ]; const commandUsage = ['-port port', '']; - +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../../types/rc/index.js').default} Registry + */ class DeployCommand extends BaseSubCommand { + /** + * Creates an instance of DeployCommand. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super('dapp-server', [], 'Start a dAPP SOCKET.IO server', commandOptions, commandUsage, rc); } - + /** + * Runs the dappServer command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, localOptions } = await super.run(commander, ...args); const { endpoint, datadir, account, password } = options; const { port = 35443 } = localOptions; try { const aelf = new AElf(new AElf.providers.HttpProvider(endpoint)); const wallet = getWallet(datadir, account, password); - const socket = new Socket({ port, endpoint, @@ -38,9 +46,11 @@ class DeployCommand extends BaseSubCommand { wallet, address: account }); + // @ts-ignore logger.info(`DApp server is listening on port ${port}`); } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/dappServer/sign.js b/src/command/dappServer/sign.js index ad9288f..1a4140b 100644 --- a/src/command/dappServer/sign.js +++ b/src/command/dappServer/sign.js @@ -1,7 +1,3 @@ -/** - * @file message signed and verified - * @author atom-yang - */ import elliptic from 'elliptic'; const defaultEncryptAlgorithm = 'secp256k1'; @@ -79,6 +75,10 @@ class Sign { } } + /** + * Gets the public key. + * @returns {string} The public key. + */ getPublicKey() { return this.keyPair.getPublic().encode('hex'); } diff --git a/src/command/dappServer/socket.js b/src/command/dappServer/socket.js index cf0d64c..8fe9416 100644 --- a/src/command/dappServer/socket.js +++ b/src/command/dappServer/socket.js @@ -1,7 +1,3 @@ -/** - * @file socket server - * @author atom-yang - */ import { Server } from 'socket.io'; import AElf from 'aelf-sdk'; import { interopImportCJSDefault } from 'node-cjs-interop'; @@ -14,6 +10,10 @@ import { randomId } from '../../utils/utils.js'; import { serializeMessage, deserializeMessage, checkTimestamp } from './utils.js'; import { CHAIN_APIS } from './constants.js'; +/** + * @typedef {import ('async-validator').Rules} Rules + */ +/** @type {Rules} */ const signRequestRules = { id: { required: true, @@ -46,7 +46,7 @@ const signRequestRules = { } } }; - +/** @type {Rules} */ const encryptRequestRules = { ...signRequestRules, params: { @@ -64,7 +64,7 @@ const encryptRequestRules = { } } }; - +/** @type {Rules} */ const connectSignRules = { ...signRequestRules, params: { @@ -93,7 +93,7 @@ const connectSignRules = { } } }; - +/** @type {Rules} */ const connectEncryptRules = { ...signRequestRules, params: { @@ -121,7 +121,41 @@ const encryptRequestValidator = new Schema(encryptRequestRules); const connectSignValidator = new Schema(connectSignRules); const connectEncryptValidator = new Schema(connectEncryptRules); +/** + * Represents the result of an operation. + * @typedef {Object} Result + * @property {number} code - The status code of the result. + * @property {string} msg - The message associated with the result. + * @property {any[]} error - An array of errors, if any. + * @property {any} data - The data returned by the operation. + */ + +/** + * Represents a client connected to the server. + * @typedef {Object} Client + * @property {function(string, any): void} emit - Sends an event to the client. + * @property {function(boolean=): void} disconnect - Disconnects the client. + * @property {function(string, function): void} on - Sends an event to the client. + */ + +/** + * Represents a message sent to the server. + * @typedef {Object} Message + * @property {string} id - The unique identifier for the message. + * @property {string} appId - The application ID sending the message. + * @property {string} action - The action to be performed. + * @property {any} params - The parameters for the action. + */ class Socket { + /** + * Creates an instance of Socket. + * @param {Object} options - The socket options. + * @param {number} options.port - The port to run the socket server. + * @param {string} options.endpoint - The default endpoint for the socket server. + * @param {any} options.aelf - The AElf instance. + * @param {any} options.wallet - The wallet instance. + * @param {string} options.address - The address associated with the wallet. + */ constructor(options) { const { port, endpoint, aelf, wallet, address } = options; this.aelf = aelf; @@ -132,6 +166,7 @@ class Socket { this.socket = new Server(port, { transports: ['websocket'] }); + // @ts-ignore this.socket.on('connection', this.handleConnection); this.clientConfig = { // default: { @@ -140,7 +175,13 @@ class Socket { // } }; } - + /** + * Formats the response. + * @param {string} id - The request ID. + * @param {any} [result] - The result data. + * @param {any} [errors] - The errors array. + * @returns {{id: string, result: Result}} The formatted result. + */ responseFormat(id, result, errors) { if (errors && (errors instanceof Error || (Array.isArray(errors) && errors.length > 0) || errors.Error)) { return { @@ -163,7 +204,13 @@ class Socket { } }; } - + /** + * Sends a response to the client. + * @param {Client} client - The client instance. + * @param {Result} result - The result object. + * @param {string} action - The action type. + * @param {string} appId - The application ID. + */ send(client, result, action, appId) { client.emit('bridge', result); if (action === 'disconnect') { @@ -171,10 +218,14 @@ class Socket { client.disconnect(true); } } - + /** + * Handles new client connections. + * @param {Client} client - The client instance. + */ handleConnection(client) { client.on('bridge', async data => { logger.info('Message received'); + /**@type {any} */ let result = {}; const { action, id, appId } = data; try { @@ -211,7 +262,9 @@ class Socket { } this.send(client, result, action, appId); } catch (e) { + // @ts-ignore logger.error('error happened'); + // @ts-ignore logger.error(e); result = this.responseFormat(id, {}, e.errors ? e.errors : e); if (action !== 'connect') { @@ -221,7 +274,11 @@ class Socket { } }); } - + /** + * Deserializes request parameters. + * @param {Message} request - The request message. + * @returns {Promise} The deserialized parameters. + */ async deserializeParams(request) { const { appId, params } = request; if (!this.clientConfig[appId]) { @@ -266,7 +323,11 @@ class Socket { const originalResult = serializeMessage(result); return this.clientConfig[appId]?.encrypt.encrypt(originalResult); } - + /** + * Handles connect actions. + * @param {Message} message - The message object. + * @returns {Promise} The result of the connect action. + */ async handleConnect(message) { const { appId, params } = message; const { encryptAlgorithm, publicKey } = params; @@ -315,10 +376,15 @@ class Socket { signature: responseSignature }; } + // @ts-ignore logger.error('Not support encrypt method or not enough params'); throw new Error('Not support encrypt method or not enough params'); } - + /** + * Handles method list requests. + * @param {Message} message - The message object. + * @returns {Promise} The list of methods. + */ async handleMethodList(message) { const params = await this.deserializeParams(message); const { endpoint = this.defaultEndpoint, address } = params; @@ -328,7 +394,11 @@ class Socket { .filter(v => /^[A-Z]/.test(v)) .sort(); } - + /** + * Handles API requests. + * @param {Message} message - The message object. + * @returns {Promise} The API result. + */ async handleApi(message) { const params = await this.deserializeParams(message); const { endpoint = this.defaultEndpoint, apiPath, arguments: apiArgs, methodName } = params; @@ -340,7 +410,11 @@ class Socket { const result = await this.aelf.chain[methodName](...apiArgs.map(v => v.value)); return result; } - + /** + * Handles account actions. + * @param {Message} message - The message object. + * @returns {Promise} The account result. + */ async handleAccount(message) { logger.info('Querying account information'); await this.deserializeParams(message); @@ -362,7 +436,12 @@ class Socket { ] }; } - + /** + * Handles invoke actions. + * @param {Message} message - The message object. + * @param {boolean} isReadOnly - If the invoke action is read-only. + * @returns {Promise} The invoke result. + */ async handleInvoke(message, isReadOnly) { const params = await this.deserializeParams(message); const { endpoint = this.defaultEndpoint, contractAddress, contractMethod, arguments: contractArgs } = params; @@ -381,6 +460,11 @@ class Socket { return result; } + /** + * Handles disconnect actions. + * @param {Message} message - The message object. + * @returns {Promise<{}>} The result of the disconnect action. + */ async handleDisconnect(message) { // just to verify client await this.deserializeParams(message); diff --git a/src/command/dappServer/utils.js b/src/command/dappServer/utils.js index 812a96e..b642029 100644 --- a/src/command/dappServer/utils.js +++ b/src/command/dappServer/utils.js @@ -1,8 +1,8 @@ /** - * @file utils - * @author atom-yang + * Serializes a message object to a string. + * @param {any} data - The message object to serialize. + * @returns {string} The serialized message as a string. */ - const serializeMessage = data => { let result = JSON.stringify(data); if (data === null || data === undefined) { @@ -11,6 +11,11 @@ const serializeMessage = data => { return Buffer.from(encodeURIComponent(result)).toString('base64'); }; +/** + * Deserializes a string to a message object. + * @param {string} str - The string to deserialize. + * @returns {any} The deserialized message object. + */ const deserializeMessage = str => { let result = decodeURIComponent(Buffer.from(str, 'base64').toString()); try { @@ -18,7 +23,12 @@ const deserializeMessage = str => { } catch (e) {} return result; }; - +/** + * Checks if the given timestamp is within the specified time buffer from the current time. + * @param {string} time - The timestamp to check, either as a number or a string. + * @param {number} [timeBuffer=300] - The time buffer in seconds. Default is 300 seconds. + * @returns {boolean} True if the timestamp is within the time buffer, false otherwise. + */ const checkTimestamp = (time, timeBuffer = 4 * 60) => { const checkTime = parseInt(time, 10); if (!checkTime) { diff --git a/src/command/deploy.js b/src/command/deploy.js index af85d83..39311dd 100644 --- a/src/command/deploy.js +++ b/src/command/deploy.js @@ -1,7 +1,3 @@ -/** - * @file deploy contract - * @author atom-yang - */ import chalk from 'chalk'; import BaseSubCommand from './baseSubCommand.js'; import { deployCommandParameters, deployCommandUsage } from '../utils/constants.js'; @@ -11,12 +7,24 @@ const tips = chalk.redBright( chalk.yellowBright('`aelf-command send`'), ', check details in aelf-command `README.md`' ); - +/** + * @typedef {import('../../types/rc/index.js').default} Registry + */ class DeployCommand extends BaseSubCommand { + /** + * Constructs a new DeployCommand instance. + * @param {Registry} rc - The registry instance. + * @param {string} [name] - The name of the command. + * @param {string} [description] - The description of the command. + * @param {string[]} [usage] - The usage information for the command. + */ constructor(rc, name = 'deploy', description = tips, usage = deployCommandUsage) { super(name, deployCommandParameters, description, [], usage, rc); } - + /** + * Executes the deploy command. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run() { console.log(tips); } diff --git a/src/command/event.js b/src/command/event.js index 1d7cd0d..4790ec3 100644 --- a/src/command/event.js +++ b/src/command/event.js @@ -1,13 +1,18 @@ -/** - * @file Deserialize transactions result Logs - * @author atom-yang - */ import AElf from 'aelf-sdk'; import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc, eventCommandParameters, eventCommandUsage } from '../utils/constants.js'; import { deserializeLogs } from '../utils/utils.js'; import { logger, plainLogger } from '../utils/myLogger.js'; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class EventCommand extends BaseSubCommand { + /** + * Constructs a new EventCommand instance. + * @param {Registry} rc - The registry instance. + */ + constructor(rc) { super( 'event', @@ -19,8 +24,14 @@ class EventCommand extends BaseSubCommand { commonGlobalOptionValidatorDesc ); } - + /** + * Executes the event command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, subOptions } = await super.run(commander, ...args); const { endpoint } = options; try { @@ -29,8 +40,10 @@ class EventCommand extends BaseSubCommand { const txResult = await aelf.chain.getTxResult(txId); // console.log(plainLogger.info(`Transaction ${txId}'s Logs: \n ${JSON.stringify(txResult.Logs, null, 2)}`)); if (!txResult.Status || txResult.Status.toUpperCase() !== 'MINED') { + // @ts-ignore console.log(plainLogger.info(`Transaction ${txId} is not mined`)); } else if (!txResult.Logs) { + // @ts-ignore console.log(plainLogger.info(`Transaction ${txId} returns void`)); } else { this.oraInstance.start('Deserialize Transaction Logs...'); @@ -43,12 +56,14 @@ class EventCommand extends BaseSubCommand { this.oraInstance.clear(); console.log( + // @ts-ignore `\n${plainLogger.info(`\nThe results returned by \nTransaction: ${txId} is: \n${JSON.stringify(logs, null, 2)}`)}` ); this.oraInstance.succeed('Succeed!'); } } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/getBlkHeight.js b/src/command/getBlkHeight.js index 5ebca3f..73ad191 100644 --- a/src/command/getBlkHeight.js +++ b/src/command/getBlkHeight.js @@ -1,18 +1,29 @@ -/** - * @file get block height - * @author atom-yang - */ import AElf from 'aelf-sdk'; import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc } from '../utils/constants.js'; import { logger } from '../utils/myLogger.js'; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class GetBlkHeightCommand extends BaseSubCommand { + /** + * Constructs a new GetBlkHeightCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super('get-blk-height', [], 'Get the current block height of specified chain', [], [''], rc, commonGlobalOptionValidatorDesc); } + /** + * Executes the get block height command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options } = await super.run(commander, ...args); const aelf = new AElf(new AElf.providers.HttpProvider(options.endpoint)); try { @@ -22,6 +33,7 @@ class GetBlkHeightCommand extends BaseSubCommand { // todo: chalk or a custom reporter } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/getBlkInfo.js b/src/command/getBlkInfo.js index 6a5b6a6..2b4e13e 100644 --- a/src/command/getBlkInfo.js +++ b/src/command/getBlkInfo.js @@ -1,7 +1,3 @@ -/** - * @file get block info - * @author atom-yang - */ import AElf from 'aelf-sdk'; import { interopImportCJSDefault } from 'node-cjs-interop'; import asyncValidator from 'async-validator'; @@ -10,7 +6,17 @@ import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc, blkInfoCommandParameters, blkInfoCommandUsage } from '../utils/constants.js'; import { logger } from '../utils/myLogger.js'; +/** + * @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 GetBlkInfoCommand extends BaseSubCommand { + /** + * Constructs a new GetBlkInfoCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super( 'get-blk-info', @@ -22,7 +28,12 @@ class GetBlkInfoCommand extends BaseSubCommand { commonGlobalOptionValidatorDesc ); } - + /** + * Validates the provided parameters against the given rules. + * @param {Rules} rule - The validation rules. + * @param {Values} parameters - The parameters to validate. + * @returns {Promise} A promise that resolves when validation is complete. + */ async validateParameters(rule, parameters) { const validator = new Schema(rule); try { @@ -31,8 +42,14 @@ class GetBlkInfoCommand extends BaseSubCommand { this.handleUniOptionsError(e); } } - + /** + * Executes the get block info command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, subOptions } = await super.run(commander, ...args); await this.validateParameters( { @@ -60,9 +77,11 @@ class GetBlkInfoCommand extends BaseSubCommand { blockInfo = await aelf.chain.getBlockByHeight(height, includeTxs); } this.oraInstance.succeed('Succeed!'); + // @ts-ignore logger.info(blockInfo); } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/getChainStatus.js b/src/command/getChainStatus.js index 3218038..e109c7d 100644 --- a/src/command/getChainStatus.js +++ b/src/command/getChainStatus.js @@ -1,18 +1,29 @@ -/** - * @file get block height - * @author atom-yang - */ import AElf from 'aelf-sdk'; import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc } from '../utils/constants.js'; import { logger } from '../utils/myLogger.js'; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class GetChainStatusCommand extends BaseSubCommand { + /** + * Constructs a new GetChainStatusCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super('get-chain-status', [], 'Get the current chain status', [], [], rc, commonGlobalOptionValidatorDesc); } + /** + * Executes the get chain status command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options } = await super.run(commander, ...args); const aelf = new AElf(new AElf.providers.HttpProvider(options.endpoint)); try { @@ -21,6 +32,7 @@ class GetChainStatusCommand extends BaseSubCommand { this.oraInstance.succeed(`Succeed\n${JSON.stringify(status, null, 2)}`); } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/getTxResult.js b/src/command/getTxResult.js index 8342f0c..28870e2 100644 --- a/src/command/getTxResult.js +++ b/src/command/getTxResult.js @@ -1,7 +1,3 @@ -/** - * @file get block height - * @author atom-yang - */ import AElf from 'aelf-sdk'; import { interopImportCJSDefault } from 'node-cjs-interop'; import asyncValidator from 'async-validator'; @@ -10,7 +6,17 @@ import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc, txResultCommandParameters, txResultCommandUsage } from '../utils/constants.js'; import { logger } from '../utils/myLogger.js'; +/** + * @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 GetTxResultCommand extends BaseSubCommand { + /** + * Constructs a new GetTxResultCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super( 'get-tx-result', @@ -23,6 +29,12 @@ class GetTxResultCommand extends BaseSubCommand { ); } + /** + * Validates the parameters against given rules. + * @param {Rules} rule - The validation rules. + * @param {Values} parameters - The parameters to validate. + * @returns {Promise} A promise that resolves when validation is complete. + */ async validateParameters(rule, parameters) { const validator = new Schema(rule); try { @@ -32,7 +44,14 @@ class GetTxResultCommand extends BaseSubCommand { } } + /** + * Executes the get transaction result command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, subOptions } = await super.run(commander, ...args); try { await this.validateParameters( @@ -50,9 +69,11 @@ class GetTxResultCommand extends BaseSubCommand { this.oraInstance.start(); const txResult = await aelf.chain.getTxResult(txId); this.oraInstance.succeed('Succeed!'); + // @ts-ignore logger.info(JSON.stringify(txResult, null, 2)); } catch (e) { this.oraInstance.fail('Failed to run this command'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/load.js b/src/command/load.js index 8129b0c..12e4d5d 100644 --- a/src/command/load.js +++ b/src/command/load.js @@ -1,7 +1,3 @@ -/** - * @file load wallet from command argv - * @author atom-yang - */ import AElf from 'aelf-sdk'; import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc, loadCommandParameters, loadCommandUsage } from '../utils/constants.js'; @@ -16,7 +12,15 @@ const loadCommandValidatorDesc = { } }; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class LoadCommand extends BaseSubCommand { + /** + * Constructs a new LoadCommand instance. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super( 'load', @@ -29,12 +33,20 @@ class LoadCommand extends BaseSubCommand { ); } + /** + * Executes the load command. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, subOptions } = await super.run(commander, ...args); const { datadir } = options; const { privateKey, saveToFile, createdByOld } = subOptions; try { let wallet = null; + // @ts-ignore logger.info('Your wallet info is :'); if (privateKey.trim().split(' ').length > 1) { if (createdByOld) { @@ -43,13 +55,17 @@ class LoadCommand extends BaseSubCommand { return; } wallet = AElf.wallet.getWalletByMnemonic(privateKey.trim()); + // @ts-ignore logger.info(`Mnemonic : ${wallet.mnemonic}`); } else { wallet = AElf.wallet.getWalletByPrivateKey(privateKey.trim()); } wallet.publicKey = wallet.keyPair.getPublic().encode('hex'); + // @ts-ignore logger.info(`Private Key : ${wallet.privateKey}`); + // @ts-ignore logger.info(`Public Key : ${wallet.publicKey}`); + // @ts-ignore logger.info(`Address : ${wallet.address}`); if (saveToFile === true || saveToFile === 'true') { const keyStorePath = await saveKeyStore(wallet, datadir); @@ -59,6 +75,7 @@ class LoadCommand extends BaseSubCommand { } } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/command/proposal.js b/src/command/proposal.js index 9b55777..0015f63 100644 --- a/src/command/proposal.js +++ b/src/command/proposal.js @@ -1,7 +1,3 @@ -/** - * @file call read-only method on contract - * @author atom-yang - */ import assert from 'assert'; import AElf from 'aelf-sdk'; import moment from 'moment'; @@ -22,10 +18,22 @@ import { import { getWallet } from '../utils/wallet.js'; import { logger } from '../utils/myLogger.js'; +/** + * @typedef {import('commander').Command} Command + * @typedef {import('async-validator').Rules} Rules + * @typedef {import('async-validator').Values} Values + * @typedef {import ('inquirer').InputQuestion } InputQuestion + * @typedef {import ('inquirer').ListQuestion } ListQuestion + * @typedef {import('../../types/rc/index.js').default} Registry + */ +/** + * @type {Array} + */ const toContractPrompts = [ { type: 'input', name: 'contract-address', + // @ts-ignore extraName: ['contract-name'], message: 'Enter a contract address or name', suffix: ':' @@ -55,6 +63,15 @@ async function getContractAddress(aelf, wallet, address) { } class ProposalCommand extends BaseSubCommand { + /** + * Constructs a new ProposalCommand instance. + * @param {Registry} rc - The registry instance. + * @param {string} [name] - Optional name of the command. + * @param {string} [description] - Optional description of the command. + * @param {Array} [parameters] - Optional array of parameter objects. + * @param {string[]} [usage] - Optional array of usage strings. + * @param {any[]} [options] - Optional array of options. + */ constructor( rc, name = 'proposal', @@ -67,6 +84,13 @@ class ProposalCommand extends BaseSubCommand { this.aelfMock = {}; } + /** + * Processes address after prompting. + * @param {any} aelf - The AElf instance. + * @param {any} wallet - The wallet instance. + * @param {{ [key: string]: any }} answerInput - Input from the user. + * @returns {Promise} A promise that resolves with the processed address. + */ async processAddressAfterPrompt(aelf, wallet, answerInput) { this.toContractAddress = await getContractAddress(aelf, wallet, answerInput['contract-address']); let { contractAddress } = BaseSubCommand.normalizeConfig(answerInput); @@ -74,12 +98,19 @@ class ProposalCommand extends BaseSubCommand { return contractAddress; } + /** + * Runs the ProposalCommand. + * @param {Command} commander - The commander instance. + * @param {...any} args - Additional arguments. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options, subOptions } = await super.run(commander, ...args); const { endpoint, datadir, account, password } = options; const { descriptionUrl, proposalContract, organization, expiredTime } = subOptions; try { - if (!proposalCommandParameters[0].choices.includes(proposalContract)) { + if (!proposalCommandParameters[0].choices?.includes(proposalContract)) { throw new Error( // eslint-disable-next-line max-len `${proposalContract} is not in the list of proposal contracts, choice one of \`AElf.ContractNames.Parliament\`, \`AElf.ContractNames.Referendum\` and \`AElf.ContractNames.Association\`` @@ -144,11 +175,13 @@ class ProposalCommand extends BaseSubCommand { proposalDescriptionUrl: descriptionUrl }) ); + // @ts-ignore logger.info(txId); this.oraInstance.start('loading proposal id...'); const tx = await getTxResult(aelf, txId.TransactionId); this.oraInstance.succeed(); if (tx.Status === 'PENDING') { + // @ts-ignore logger.info( `Transaction is still pending, you can get proposal id later by running ${chalk.yellow( `aelf-command event ${txId.TransactionId}` @@ -161,11 +194,13 @@ class ProposalCommand extends BaseSubCommand { (Logs || []).filter(v => v.Name === 'ProposalCreated') ); assert.strictEqual(results.length, 1, 'No related log'); + // @ts-ignore logger.info(`Proposal id: ${results[0].proposalId}.`); this.oraInstance.succeed('Succeed!'); } } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.fatal(e); } } diff --git a/src/command/send.js b/src/command/send.js index b1693fb..02c4f62 100644 --- a/src/command/send.js +++ b/src/command/send.js @@ -1,14 +1,23 @@ -/** - * @file call read-only method on contract - * @author atom-yang - */ import CallCommand from './call.js'; +/** + * @typedef {import('../../types/rc/index.js').default} Registry + */ class SendCommand extends CallCommand { + /** + * Creates an instance of SendCommand. + * @param {Registry} rc - The registry instance. + */ constructor(rc) { super(rc, 'send', 'Execute a method on a contract.'); } + /** + * Asynchronously calls a method and handles transaction progress. + * @param {any} method - The method to call. + * @param {any} params - The parameters for the method. + * @returns {Promise} A promise that resolves to the result of the method call. + */ async callMethod(method, params) { this.oraInstance.start('sending the transaction'); const result = await method(params); diff --git a/src/command/wallet.js b/src/command/wallet.js index 1d773d6..05f9bb1 100644 --- a/src/command/wallet.js +++ b/src/command/wallet.js @@ -1,7 +1,3 @@ -/** - * @file show wallet info - * @author atom-yang - */ import BaseSubCommand from './baseSubCommand.js'; import { commonGlobalOptionValidatorDesc } from '../utils/constants.js'; import { getWallet } from '../utils/wallet.js'; @@ -22,8 +18,15 @@ const walletCommandValidatorDesc = { required: true } }; - +/** + * @typedef {import('commander').Command} Command + * @typedef {import('../../types/rc/index.js').default} Registry + */ class WalletCommand extends BaseSubCommand { + /** + * Constructs a new WalletCommand instance. + * @param {Registry} rc - The Registry instance for configuration. + */ constructor(rc) { super( 'wallet', @@ -36,21 +39,33 @@ class WalletCommand extends BaseSubCommand { ); } + /** + * Runs the wallet command logic. + * @param {Command} commander - The Commander instance for command handling. + * @param {...any} args - Additional arguments for command execution. + * @returns {Promise} A promise that resolves when the command execution is complete. + */ async run(commander, ...args) { + // @ts-ignore const { options } = await super.run(commander, ...args); const { datadir, account, password } = options; try { const wallet = getWallet(datadir, account, password); if (wallet.mnemonic) { + // @ts-ignore logger.info(`Mnemonic : ${wallet.mnemonic}`); } wallet.publicKey = wallet.keyPair.getPublic().encode('hex'); + // @ts-ignore logger.info(`Private Key : ${wallet.privateKey}`); + // @ts-ignore logger.info(`Public Key : ${wallet.publicKey}`); + // @ts-ignore logger.info(`Address : ${wallet.address}`); this.oraInstance.succeed('Succeed!'); } catch (e) { this.oraInstance.fail('Failed!'); + // @ts-ignore logger.error(e); } } diff --git a/src/rc/index.js b/src/rc/index.js index a98a461..3111902 100644 --- a/src/rc/index.js +++ b/src/rc/index.js @@ -1,7 +1,3 @@ -/** - * @file command config operations - * @author atom-yang - */ import path from 'path'; import fs from 'fs'; import { mkdirpSync } from 'mkdirp'; @@ -28,10 +24,20 @@ class Registry { if (!fs.existsSync(path.resolve(userHomeDir, 'aelf'))) { mkdirpSync(path.resolve(userHomeDir, 'aelf')); } + /** + * AELF configuration object. + * @type {Object.} + */ this.aelfConfig = {}; this.init(); } + /** + * Retrieves file content or default content if file doesn't exist. + * @param {string} file - The file path. + * @param {string} [defaultContent] - Optional default content if file doesn't exist. + * @returns {*} The content of the file or default content. + */ static getFileOrNot(file, defaultContent = '') { if (fs.existsSync(file)) { return fs.readFileSync(file).toString(); @@ -39,6 +45,11 @@ class Registry { return defaultContent; } + /** + * Retrieves file content or creates the file if it doesn't exist. + * @param {string} file - The file path. + * @returns {string} The file content or an empty string if the file is created. + */ static getFileOrCreate(file) { if (fs.existsSync(file)) { return fs.readFileSync(file).toString(); @@ -46,7 +57,11 @@ class Registry { fs.writeFileSync(file, rcHeader); return ''; } - + /** + * Loads configuration from provided content. + * @param {string} [content] - Optional content to load configuration from. + * @returns {Object.} The loaded configuration object. + */ static loadConfig(content = '') { const result = {}; content @@ -58,7 +73,10 @@ class Registry { }); return result; } - + /** + * Retrieves configuration from environment variables. + * @returns {Object.} The configuration object retrieved from environment variables. + */ static getConfigFromEnv() { const result = {}; Object.entries(ENV_RC_KEYS).forEach(([key, value]) => { @@ -70,16 +88,19 @@ class Registry { } /** - * obj only contains one level field - * @param {Object} obj - * @return {string[]} the array of content + * Converts a one-level object into an array of content. + * @param {Object.} [obj] - The object to stringify. + * @returns {string[]} Array of content from the object's fields. */ static stringify(obj = {}) { let result = Object.entries(obj).map(([key, value]) => `${key} ${value}`); result = rcHeader.split('\n').concat(result); return result; } - + /** + * Initializes and retrieves initial configuration options. + * @returns {{ endpoint: string, datadir: string, password: string, account: string }} Initial configuration values. + */ init() { const pwdRc = Registry.loadConfig(Registry.getFileOrNot(path.resolve(process.cwd(), '.aelfrc'))); const globalRc = Registry.loadConfig(Registry.getFileOrCreate(this.globalConfigLoc)); @@ -94,14 +115,31 @@ class Registry { return rc; } + /** + * Retrieves a configuration option by key. + * @param {string} key - The option key. + * @returns {*} The value of the option. + */ getOption(key) { return this.aelfConfig[key]; } + /** + * Sets a configuration option. + * @param {string} key - The option key. + * @param {*} value - The value to set. + */ setOption(key, value) { this.aelfConfig[key] = value; } + /** + * Saves an option to configuration file. + * @param {string} key - The option key. + * @param {*} value - The value to save. + * @param {*} [filePath] - Optional file path to save configuration. + * @returns {*} Result of saving operation. + */ saveOption(key, value, filePath = this.globalConfigLoc) { this.aelfConfig[key] = value; const rc = Registry.loadConfig(Registry.getFileOrCreate(filePath)); @@ -109,16 +147,30 @@ class Registry { return fs.writeFileSync(filePath, `${Registry.stringify(rc).join('\n')}\n`); } + /** + * Deletes a configuration key from file. + * @param {string} key - The option key to delete. + * @param {*} [filePath] - Optional file path to delete from. + * @returns {*} Result of deletion operation. + */ deleteConfig(key, filePath = this.globalConfigLoc) { const rc = Registry.loadConfig(Registry.getFileOrCreate(filePath)); delete rc[key]; return fs.writeFileSync(filePath, `${Registry.stringify(rc).join('\n')}\n`); } + /** + * Retrieves configurations from file. + * @param {string} [filePath] - Optional file path to retrieve configurations. + * @returns {Object.} The configurations retrieved from file. + */ getFileConfigs(filePath = this.globalConfigLoc) { return Registry.loadConfig(Registry.getFileOrCreate(filePath)); } - + /** + * Retrieves all configurations. + * @returns {Object.} All configurations. + */ getConfigs() { return this.aelfConfig; } diff --git a/src/utils/Logger.js b/src/utils/Logger.js index 9c68846..2c2fa1b 100644 --- a/src/utils/Logger.js +++ b/src/utils/Logger.js @@ -34,9 +34,25 @@ const levels = [ ]; class Logger { + /** + * Constructs a new Logger instance. + * @param {Object.} props - Logger properties. + */ constructor(props) { + /** + * Symbol for the logger. + * @type {string} + */ this.symbol = ''; + /** + * Name of the logger. + * @type {string} + */ this.name = ''; + /** + * Determines whether to log messages. + * @type {boolean} + */ this.log = props.log !== undefined ? props.log : true; // determin whether console.log or not if (!props.onlyWords) { this.symbol = ''; @@ -50,6 +66,15 @@ class Logger { levels.forEach(item => { const { level, color } = item; const fnName = level.toLocaleLowerCase(); + + /** + * Logs an error message. + * @function + * @memberof Logger.prototype + * @param {string} firstParam - The first parameter to log. + * @param {...any} rest - Additional parameters to log. + * @returns {string} - The formatted log message. + */ Logger.prototype[fnName] = function fn(firstParam, ...rest) { // if (typeof params === 'obejct') params = JSON.stringify(params); diff --git a/src/utils/constants.js b/src/utils/constants.js index 4cc695c..1448bb4 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -1,7 +1,3 @@ -/** - * @file constants - * @author atom-yang - */ import path from 'path'; import moment from 'moment'; import inquirer from 'inquirer'; @@ -9,6 +5,30 @@ import { logger } from './myLogger.js'; import DatePrompt from 'inquirer-date-prompt'; import SearchList from 'inquirer-search-list'; +/** + * @typedef {import('../../types/utils/constants.js').CallCommandParameter} CallCommandParameter + * @typedef {import('../../types/utils/constants.js').PasswordValidatorDesc} PasswordValidatorDesc + * @typedef {import('../../types/utils/constants.js').EndpointValidatorDesc} EndpointValidatorDesc + * @typedef {import('../../types/utils/constants.js').DatadirValidatorDesc} DatadirValidatorDesc + * @typedef {import('../../types/utils/constants.js').AccountValidatorDesc} AccountValidatorDesc + * @typedef {import('../../types/utils/constants.js').CommonGlobalOptionValidatorDesc} CommonGlobalOptionValidatorDesc + * @typedef {import('../../types/utils/constants.js').BlkInfoCommandParameter} BlkInfoCommandParameter + * @typedef {import('../../types/utils/constants.js').TxResultCommandParameter} TxResultCommandParameter + * @typedef {import('../../types/utils/constants.js').GlobalOptionPrompt} GlobalOptionPrompt + * @typedef {import('../../types/utils/constants.js').CreateCommandParameter} CreateCommandParameter + * @typedef {import('../../types/utils/constants.js').LoadCommandParameter} LoadCommandParameter + * @typedef {import('../../types/utils/constants.js').PasswordPrompt} PasswordPrompt + * @typedef {import('../../types/utils/constants.js').DeployCommandParameter} DeployCommandParameter + * @typedef {import('../../types/utils/constants.js').ConfigCommandParameter} ConfigCommandParameter + * @typedef {import('../../types/utils/constants.js').ProposalCommandParameter} ProposalCommandParameter + * @typedef {import('../../types/utils/constants.js').EventCommandParameter} EventCommandParameter + * @typedef {'password' | 'endpoint' | 'datadir' | 'account'} CommonGlobalOptionKey + */ + +/** + * Array of usage strings for the call command. + * @type {string[]} + */ const callCommandUsages = [ ' ', ' ', @@ -16,6 +36,10 @@ const callCommandUsages = [ '' ]; +/** + * Parameters for the call command. + * @type {CallCommandParameter[]} + */ const callCommandParameters = [ { type: 'input', @@ -53,6 +77,10 @@ const callCommandParameters = [ } ]; +/** + * Parameters for the blkInfo command. + * @type {BlkInfoCommandParameter[]} + */ const blkInfoCommandParameters = [ { type: 'input', @@ -73,11 +101,20 @@ const blkInfoCommandParameters = [ } ]; +/** + * Array of usage strings for the blkInfo command. + * @type {string[]} + */ const blkInfoCommandUsage = [' ', '', '']; +// @ts-ignore inquirer.registerPrompt('datetime', DatePrompt); inquirer.registerPrompt('search-list', SearchList); +/** + * Parameters for the proposal command. + * @type {ProposalCommandParameter[]} + */ const proposalCommandParameters = [ { type: 'list', @@ -113,6 +150,10 @@ const proposalCommandParameters = [ } ]; +/** + * Array of usage strings for the proposal command. + * @type {string[]} + */ const proposalCommandUsage = [ ' ', ' ', @@ -120,6 +161,10 @@ const proposalCommandUsage = [ '' ]; +/** + * Parameters for the txResult command. + * @type {TxResultCommandParameter[]} + */ const txResultCommandParameters = [ { type: 'input', @@ -129,8 +174,16 @@ const txResultCommandParameters = [ } ]; +/** + * Array of usage strings for the txResult command. + * @type {string[]} + */ const txResultCommandUsage = ['', '']; +/** + * Parameters for the create command. + * @type {CreateCommandParameter[]} + */ const createCommandParameters = [ { type: 'confirm', @@ -144,8 +197,16 @@ const createCommandParameters = [ } ]; +/** + * Array of usage strings for the create command. + * @type {string[]} + */ const createCommandUsage = [' -c, cipher', '-c, cipher', '']; +/** + * Parameters for the config command. + * @type {ConfigCommandParameter[]} + */ const configCommandParameters = [ { type: 'input', @@ -170,8 +231,16 @@ const configCommandParameters = [ } ]; +/** + * Array of usage strings for the config command. + * @type {string[]} + */ const configCommandUsage = ['get ', 'set ', 'delete ', 'list']; +/** + * Parameters for the load command. + * @type {LoadCommandParameter[]} + */ const loadCommandParameters = [ { type: 'input', @@ -208,6 +277,10 @@ const loadCommandParameters = [ } ]; +/** + * Array of usage strings for the load command. + * @type {string[]} + */ const loadCommandUsage = [ ' ', ' ', @@ -215,6 +288,10 @@ const loadCommandUsage = [ '' ]; +/** + * Parameters for the deploy command. + * @type {DeployCommandParameter[]} + */ const deployCommandParameters = [ { type: 'input', @@ -233,8 +310,16 @@ const deployCommandParameters = [ } ]; +/** + * Array of usage strings for the deploy command. + * @type {string[]} + */ const deployCommandUsage = [' ', '', '']; +/** + * Parameters for the event command. + * @type {EventCommandParameter[]} + */ const eventCommandParameters = [ { type: 'input', @@ -244,8 +329,16 @@ const eventCommandParameters = [ } ]; +/** + * Array of usage strings for the event command. + * @type {string[]} + */ const eventCommandUsage = ['', '']; +/** + * Validator description for common global options. + * @type {CommonGlobalOptionValidatorDesc} + */ const commonGlobalOptionValidatorDesc = { password: { type: 'string', @@ -276,9 +369,10 @@ const commonGlobalOptionValidatorDesc = { } }; -const strictGlobalOptionValidatorDesc = {}; +const strictGlobalOptionValidatorDesc = /**@type {CommonGlobalOptionValidatorDesc}*/ ({}); -Object.entries(commonGlobalOptionValidatorDesc).forEach(([key, value]) => { +// @ts-ignore +Object.entries(commonGlobalOptionValidatorDesc).forEach((/** @type {[CommonGlobalOptionKey, any]} */ [key, value]) => { strictGlobalOptionValidatorDesc[key] = { ...value, required: true @@ -286,8 +380,8 @@ Object.entries(commonGlobalOptionValidatorDesc).forEach(([key, value]) => { }); /** - * specified the prompts options for CLI global options - * @type {*[]} + * Array of global option prompts. + * @type {GlobalOptionPrompt[]} */ const globalOptionsPrompts = [ { @@ -311,6 +405,10 @@ const globalOptionsPrompts = [ } ]; +/** + * Array of password prompts. + * @type {PasswordPrompt[]} + */ const passwordPrompts = [ { type: 'password', @@ -319,6 +417,7 @@ const passwordPrompts = [ message: 'Enter a password', validate(val) { if (!val || val.length <= 6) { + // @ts-ignore logger.error('\npassword is too short'); process.exit(1); } diff --git a/src/utils/fs.js b/src/utils/fs.js index f0738b0..c4f7b8a 100644 --- a/src/utils/fs.js +++ b/src/utils/fs.js @@ -1,7 +1,3 @@ -/** - * @file fs operator - * @author atom-yang - */ import fs from 'fs'; import os from 'os'; @@ -10,9 +6,22 @@ import { promisify } from './utils.js'; const readFile = promisify(fs.readFile); const writeFile = promisify(fs.writeFile); +/** + * Carriage return character code. + * @type {number} + */ const cr = '\r'.charCodeAt(0); +/** + * Line feed character code. + * @type {number} + */ const lf = '\n'.charCodeAt(0); +/** + * Retrieves the end-of-line (EOL) sequence from a file. + * @param {string} path - The path to the file. + * @returns {Promise} A promise that resolves with the EOL sequence found in the file, or undefined. + */ async function getEolFromFile(path) { if (!fs.existsSync(path)) { return undefined; @@ -31,6 +40,12 @@ async function getEolFromFile(path) { return undefined; } +/** + * Writes data to a file while preserving the original end-of-line (EOL) sequence. + * @param {string} path - The path to the file. + * @param {string} data - The data to write. + * @returns {Promise} A promise that resolves when the file is successfully written. + */ async function writeFilePreservingEol(path, data) { const eol = (await getEolFromFile(path)) || os.EOL; let result = data; diff --git a/src/utils/myLogger.js b/src/utils/myLogger.js index 3a96e05..35d0152 100644 --- a/src/utils/myLogger.js +++ b/src/utils/myLogger.js @@ -1,10 +1,17 @@ import Logger from './Logger.js'; +/** + * Instance of Logger with full logging enabled. + * @type {Logger} + */ const logger = new Logger({ name: 'AElf', log: true }); - +/** + * Instance of Logger that logs only words. + * @type {Logger} + */ const plainLogger = new Logger({ onlyWords: true, log: false diff --git a/src/utils/userHomeDir.js b/src/utils/userHomeDir.js index bbaad38..d4e5da0 100644 --- a/src/utils/userHomeDir.js +++ b/src/utils/userHomeDir.js @@ -1,12 +1,16 @@ -/** - * @file find user home dir - * @author atom-yang - */ import path from 'path'; import { homedir } from 'os'; +/** + * Path to the home directory. + * @type {string} + */ const home = homedir(); +/** + * Retrieves the user ID (UID) of the current process. + * @returns {number | null} The UID of the current process if available, otherwise null. + */ function getUid() { if (process.platform !== 'win32' && process.getuid) { return process.getuid(); @@ -14,20 +18,41 @@ function getUid() { return null; } +/** + * Checks if the current environment is a fake root environment. + * @returns {boolean} True if the environment is a fake root, false otherwise. + */ function isFakeRoot() { return Boolean(process.env.FAKEROOTKEY); } +/** + * Checks if a given user ID belongs to the root user. + * @param {number | null} uid - The user ID to check. + * @returns {boolean} True if the user ID belongs to the root user, false otherwise. + */ function isRootUser(uid) { return uid === 0; } +/** + * Checks if the current operating system is Windows. + * @returns {boolean} True if the operating system is Windows, false otherwise. + */ function isWindows() { return process.platform === 'win32'; } +/** + * Indicates whether the current environment is running as the root user. + * @type {boolean} + */ const ROOT_USER = isRootUser(getUid()) && !isFakeRoot(); +/** + * User's home directory path. + * @type {any} + */ let userHomeDir; if (isWindows()) { userHomeDir = path.resolve(home, './AppData/Local'); diff --git a/src/utils/utils.js b/src/utils/utils.js index 969aaf9..4fa9256 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,7 +1,3 @@ -/** - * @file utils - * @author atom-yang - */ import AElf from 'aelf-sdk'; import moment from 'moment'; import chalk from 'chalk'; @@ -13,6 +9,16 @@ import inquirer from 'inquirer'; import { plainLogger } from './myLogger.js'; import * as protobuf from '@aelfqueen/protobufjs'; +/** + * @typedef {import('ora').Ora} Ora + * @typedef {import('inquirer').DistinctQuestion} DistinctQuestion + */ +/** + * Promisifies a function. + * @param {Function} fn - The function to promisify. + * @param {boolean} [firstData] - Whether to pass first data. + * @returns {Function} A promisified function. + */ function promisify(fn, firstData) { return (...args) => new Promise((resolve, reject) => { @@ -40,6 +46,11 @@ function promisify(fn, firstData) { }); } +/** + * Converts a string to camelCase. + * @param {string} str - The input string. + * @returns {string} The camelCase version of the string. + */ function camelCase(str) { return _camelCase(str); } @@ -60,12 +71,13 @@ function isRegExp(o) { } /** - * get contract methods' keys - * @param {Object} contract contract instance - * @return {string[]} + * Retrieves the list of methods of a contract. + * @param {Object.} [contract] - The contract object. + * @returns {string[]} An array of method names. */ function getContractMethods(contract = {}) { if (!contract) { + // @ts-ignore plainLogger.fatal('There is no such contract'); process.exit(1); } @@ -74,6 +86,14 @@ function getContractMethods(contract = {}) { .sort(); } +/** + * Retrieves an instance of a contract. + * @param {string} contractAddress - The address of the contract. + * @param {any} aelf - The AElf instance. + * @param {any} wallet - The wallet instance. + * @param {Ora} oraInstance - The ora instance for logging. + * @returns {Promise} A promise that resolves to the contract instance. + */ async function getContractInstance(contractAddress, aelf, wallet, oraInstance) { if (typeof contractAddress !== 'string') { return contractAddress; @@ -90,6 +110,7 @@ async function getContractInstance(contractAddress, aelf, wallet, oraInstance) { contract = await aelf.chain.contractAt(address, wallet); } } catch (e) { + // @ts-ignore oraInstance.fail(plainLogger.error('Failed to find the contract, please enter the correct contract name!')); process.exit(1); } @@ -108,15 +129,14 @@ function getMethod(method, contract) { } /** - * @description prompt contract address three times at most - * @param {*} { - * times, - * prompt, - * processAfterPrompt, // a function that will process user's input with first param as the raw input value of user - * pattern // the regular expression to validate the user's input - * } - * @param {Object} oraInstance the instance of ora library - * @return {Object} the correct input value, if no correct was inputted, it will throw an error then exit the process + * Prompts with tolerance for multiple attempts. + * @param {Object} options - Prompt options. + * @param {Function} options.processAfterPrompt - Function to process after prompt. + * @param {string | RegExp} options.pattern - Pattern for the prompt. + * @param {number} options.times - Number of times to prompt. + * @param {DistinctQuestion} options.prompt - prompt. + * @param {Ora} oraInstance - The ora instance for logging. + * @returns {Promise>} The result of the prompt. */ async function promptTolerateSeveralTimes({ processAfterPrompt = () => {}, pattern, times = 3, prompt = [] }, oraInstance) { if (pattern && !isRegExp(pattern)) { @@ -130,8 +150,8 @@ async function promptTolerateSeveralTimes({ processAfterPrompt = () => {}, patte while (askTimes < times) { try { answerInput = await inquirer.prompt(prompt); - answerInput = await processAfterPrompt(answerInput); + // @ts-ignore if (!pattern || pattern.test(answerInput)) { break; } @@ -142,6 +162,7 @@ async function promptTolerateSeveralTimes({ processAfterPrompt = () => {}, patte } } if (askTimes >= times && answerInput === null) { + // @ts-ignore oraInstance.fail(plainLogger.fatal(`You has entered wrong message ${times} times!`)); process.exit(1); } @@ -161,13 +182,24 @@ function isFilePath(val) { } } +/** + * Retrieves the result of a transaction. + * @param {*} aelf - The AElf instance. + * @param {string} txId - The transaction ID. + * @param {number} [times] - Number of times to retry. + * @param {number} [delay] - Delay between retries. + * @param {number} [timeLimit] - Time limit for retries. + * @returns {Promise} The transaction result. + */ async function getTxResult(aelf, txId, times = 0, delay = 3000, timeLimit = 3) { const currentTime = times + 1; - await new Promise(resolve => { - setTimeout(() => { - resolve(); - }, delay); - }); + await /** @type {Promise} */ ( + new Promise(resolve => { + setTimeout(() => { + resolve(); + }, delay); + }) + ); const tx = await aelf.chain.getTxResult(txId); if (tx.Status === 'PENDING' && currentTime <= timeLimit) { const result = await getTxResult(aelf, txId, currentTime, delay, timeLimit); @@ -182,6 +214,11 @@ async function getTxResult(aelf, txId, times = 0, delay = 3000, timeLimit = 3) { throw tx; } +/** + * Parses a JSON string. + * @param {string} [str] - The JSON string to parse. + * @returns {*} The parsed JSON object. + */ function parseJSON(str = '') { let result = null; try { @@ -192,6 +229,10 @@ function parseJSON(str = '') { return result; } +/** + * Generates a random ID. + * @returns {string} The random ID. + */ function randomId() { return uuid().replace(/-/g, ''); } @@ -261,6 +302,11 @@ async function getParamValue(type, fieldName) { return value; } +/** + * Retrieves parameters of a method. + * @param {*} method - The method. + * @returns {Promise>} A promise that resolves to the parameters object. + */ async function getParams(method) { const fields = Object.entries(method.inputTypeInfo.fields || {}); let result = {}; @@ -272,6 +318,9 @@ async function getParams(method) { ); console.log('Enter the params one by one, type `Enter` to skip optional param:'); if (isSpecialParameters(method.inputType)) { + /** + * @type {Object.} + */ let prompts = PROTO_TYPE_PROMPT_TYPE.default; prompts = { ...prompts, @@ -300,6 +349,9 @@ async function getParams(method) { const innerInputTypeInfo = innerType.toJSON(); const innerFields = Object.entries(innerInputTypeInfo.fields || {}); if (isSpecialParameters(innerFields)) { + /** + * @type {Object.} + */ let prompts = PROTO_TYPE_PROMPT_TYPE.default; prompts = { ...prompts, @@ -357,7 +409,12 @@ function getDeserializeLogResult(serializedData, dataType) { deserializeLogResult = AElf.utils.transform.transformArrayToMap(dataType, deserializeLogResult); return deserializeLogResult; } - +/** + * Deserializes logs from AElf. + * @param {*} aelf - The AElf instance. + * @param {Array} [logs] - The logs array to deserialize. + * @returns {Promise} A promise that resolves to the deserialized logs. + */ async function deserializeLogs(aelf, logs = []) { if (!logs || logs.length === 0) { return null; @@ -373,6 +430,7 @@ async function deserializeLogs(aelf, logs = []) { if (Name === 'VirtualTransactionCreated') { // VirtualTransactionCreated is system-default try { + // @ts-ignore const dataType = Root.VirtualTransactionCreated; return getDeserializeLogResult(serializedData, dataType); } catch (e) { diff --git a/src/utils/wallet.js b/src/utils/wallet.js index 7ebd37e..9aba7f8 100644 --- a/src/utils/wallet.js +++ b/src/utils/wallet.js @@ -1,7 +1,3 @@ -/** - * @file get wallet instance - * @author atom-yang - */ import AElf from 'aelf-sdk'; import fs from 'fs'; import path from 'path'; @@ -11,6 +7,13 @@ import Registry from '../rc/index.js'; import { passwordPrompts } from './constants.js'; import BaseSubCommand from '../command/baseSubCommand.js'; +/** + * Retrieves a wallet based on the provided command root, address, and password. + * @param {string} commandRoot - The root directory of the command. + * @param {string} address - The address of the wallet. + * @param {string} password - The password for the wallet. + * @returns {any} - The wallet instance. + */ function getWallet(commandRoot, address, password) { const keyStoreFile = path.resolve(commandRoot, `keys/${address}.json`); const keyStore = JSON.parse(Registry.getFileOrNot(keyStoreFile, '{}').toString()); @@ -25,6 +28,13 @@ function getWallet(commandRoot, address, password) { } } +/** + * Saves the wallet keystore to the specified directory. + * @param {any} wallet - The wallet instance to be saved. + * @param {string} datadir - The directory to save the wallet keystore. + * @param {string} [cipher] - Optional cipher to be used for encryption. + * @returns {Promise} - A promise that resolves to the path of the saved keystore file. + */ async function saveKeyStore(wallet, datadir, cipher = 'aes-128-ctr') { const { password, confirmPassword } = BaseSubCommand.normalizeConfig(await inquirer.prompt(passwordPrompts)); if (password !== confirmPassword) { diff --git a/test/index.test.js b/test/index.test.js index 995652a..6d55c16 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -5,68 +5,70 @@ import updateNotifier from 'update-notifier'; import { logger } from '../src/utils/myLogger.js'; import pkg from '../package.json' assert { type: 'json' }; -const commandBin = path.resolve(__dirname,'../bin/aelf-command.js'); +const commandBin = path.resolve(__dirname, '../bin/aelf-command.js'); jest.mock('check-node-version'); jest.mock('update-notifier'); -jest.mock('child_process',() => { +jest.mock('child_process', () => { return { - execSync: (str) => str - } + execSync: str => str + }; }); jest.mock('../src/utils/myLogger.js'); -describe('test index',() => { +describe('test index', () => { afterEach(() => { // Restore any mocks jest.restoreAllMocks(); }); - test('should check node version and run init if satisfied in test environment',() => { + test('should check node version and run init if satisfied in test environment', () => { process.env.NODE_ENV = 'test'; - check.mockImplementation((options,callback) => { - callback(null,{ isSatisfied: true }); + check.mockImplementation((options, callback) => { + callback(null, { isSatisfied: true }); }); try { - aelfCommandRun([process.argv[0],commandBin,'-v'],{ + aelfCommandRun([process.argv[0], commandBin, '-v'], { exitOverride: true, - suppressOutput: true, - }) + suppressOutput: true + }); } catch (e) { - expect(check).toHaveBeenCalledWith({ node: '>= 10.9.0' },expect.any(Function)); + expect(check).toHaveBeenCalledWith({ node: '>= 10.9.0' }, expect.any(Function)); } - expect(() => aelfCommandRun([process.argv[0],commandBin,'-v'],{ - exitOverride: true, - suppressOutput: true, - })).toThrow(pkg.version) + expect(() => + aelfCommandRun([process.argv[0], commandBin, '-v'], { + exitOverride: true, + suppressOutput: true + }) + ).toThrow(pkg.version); }); - test('should log error if node version is not satisfied in test environment',() => { + test('should log error if node version is not satisfied in test environment', () => { // no notifier process.env.NODE_ENV = 'test'; - check.mockImplementation((options,callback) => { - callback(null,{ isSatisfied: false }); + check.mockImplementation((options, callback) => { + callback(null, { isSatisfied: false }); }); - aelfCommandRun([process.argv[0],commandBin,'-v'],{ + aelfCommandRun([process.argv[0], commandBin, '-v'], { exitOverride: true, - suppressOutput: true, - }) - expect(check).toHaveBeenCalledWith({ node: '>= 10.9.0' },expect.any(Function)); - expect(logger.error).toHaveBeenCalledWith('Your Node.js version is needed to >= %s','10.9.0'); + suppressOutput: true + }); + expect(check).toHaveBeenCalledWith({ node: '>= 10.9.0' }, expect.any(Function)); + expect(logger.error).toHaveBeenCalledWith('Your Node.js version is needed to >= %s', '10.9.0'); }); - test('should notify update if update is available',() => { + test('should notify update if update is available', () => { // no need in test environment because it will not check if update in this environment process.env.NODE_ENV = 'development'; - check.mockImplementation((options,callback) => { - callback(null,{ isSatisfied: true }); + check.mockImplementation((options, callback) => { + callback(null, { isSatisfied: true }); }); const mockNotifier = { update: { latest: '1.1.0' }, notify: jest.fn() }; updateNotifier.mockReturnValue(mockNotifier); - aelfCommandRun([process.argv[0],commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'],{ + aelfCommandRun([process.argv[0], commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'], { exitOverride: true, - suppressOutput: true, - }) + suppressOutput: true + }); expect(updateNotifier).toHaveBeenCalledWith({ pkg, distTag: 'latest', @@ -74,46 +76,46 @@ describe('test index',() => { }); expect(mockNotifier.notify).toHaveBeenCalled(); }); - test('should notify update if update is unavailable',() => { + test('should notify update if update is unavailable', () => { // no need in test environment because it will not check if update in this environment process.env.NODE_ENV = 'development'; - check.mockImplementation((options,callback) => { - callback(null,{ isSatisfied: true }); + check.mockImplementation((options, callback) => { + callback(null, { isSatisfied: true }); }); const mockNotifier = { // no update }; updateNotifier.mockReturnValue(mockNotifier); - aelfCommandRun([process.argv[0],commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'],{ + aelfCommandRun([process.argv[0], commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'], { exitOverride: true, - suppressOutput: true, - }) + suppressOutput: true + }); expect(updateNotifier).toHaveBeenCalledWith({ pkg, distTag: 'latest', updateCheckInterval: 1000 * 60 * 60 * 1 // one hour }); }); - test('should log error on check version failure',() => { + test('should log error on check version failure', () => { process.env.NODE_ENV = 'development'; const error = new Error('Failed to check version'); check.mockImplementation((options, callback) => { callback(error, null); }); - aelfCommandRun([process.argv[0],commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'],{ + aelfCommandRun([process.argv[0], commandBin, 'get-chain-status', '-e', 'https://aelf-test-node.aelf.io/'], { exitOverride: true, - suppressOutput: true, - }) + suppressOutput: true + }); expect(logger.error).toHaveBeenCalledWith(error); }); - test('handle invalid command',() => { + test('handle invalid command', () => { const warnSpy = jest.spyOn(logger, 'warn'); - const infoSpy = jest.spyOn(logger,'info'); - check.mockImplementation((options,callback) => { - callback(null,{ isSatisfied: true }); + const infoSpy = jest.spyOn(logger, 'info'); + check.mockImplementation((options, callback) => { + callback(null, { isSatisfied: true }); }); - aelfCommandRun([process.argv[0],commandBin, 'test-command']); + aelfCommandRun([process.argv[0], commandBin, 'test-command']); expect(warnSpy).toHaveBeenCalledWith('not a valid command\n'); expect(infoSpy).toHaveBeenCalledWith('aelf-command -h'); - }) + }); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1744afa --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "include": ["src/**/*.js", "*.ts"], + "exclude": ["node_modules", "src/protobuf"], + "compilerOptions": { + "module": "esnext", + "esModuleInterop": true, + "declaration": true, + "declarationMap": true, + "moduleResolution": "node", + "noImplicitAny": false, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "allowJs": true, + "checkJs": true, + "allowSyntheticDefaultImports": true, + "noEmit": true + } +} diff --git a/types/command/baseSubCommand.d.ts b/types/command/baseSubCommand.d.ts new file mode 100644 index 0000000..b414a65 --- /dev/null +++ b/types/command/baseSubCommand.d.ts @@ -0,0 +1,46 @@ +import asyncValidator from 'async-validator'; +import { Ora } from 'ora'; +import { Command } from 'commander'; +import type { Options as OraOptions } from 'ora'; +import Registry from '../rc/index'; + +declare class BaseSubCommand { + static getUniConfig(commander: Command): { [key: string]: any }; + static parseBoolean(val: any): any; + static normalizeConfig(obj: any): { [key: string]: any }; + constructor( + commandName: string, + parameters: { [key: string]: any }[] | undefined, + description: string, + options: { [key: string]: any }[] | undefined, + usage: string[] | undefined, + rc: Registry, + validatorDesc?: { [key: string]: any }, + oraOptions?: OraOptions + ); + commandName: string; + parameters: { [key: string]: any }[]; + description: string; + options: { [key: string]: any }[]; + validatorDesc: { [key: string]: any }; + usage: string[]; + rc: Registry; + oraInstance: Ora; + customPrompts: boolean; + setCustomPrompts(val: any): void; + init(commander: Command): void; + getParameters(): string; + handleUniOptionsError(error: any): void; + run( + commander: Command, + ...args: any[] + ): Promise<{ + localOptions: { [key: string]: any }; + options: { [key: string]: any }; + subOptions: { [key: string]: any }; + } | void>; + validator: asyncValidator | undefined; + makeExamples(): string[]; +} + +export default BaseSubCommand; diff --git a/types/command/call.d.ts b/types/command/call.d.ts new file mode 100644 index 0000000..d754dce --- /dev/null +++ b/types/command/call.d.ts @@ -0,0 +1,18 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; +import { CallCommandParameter } from '../utils/constants'; +declare class CallCommand extends BaseSubCommand { + constructor( + rc: Registry, + name?: string, + description?: string, + parameters?: CallCommandParameter[], + usage?: string[], + options?: any[] + ); + callMethod(method: any, params: any): Promise; + processAddressAfterPrompt(aelf: any, wallet: any, answerInput: { [key: string]: any }): Promise; + run(commander: Command, ...args: any[]): Promise; +} +export default CallCommand; diff --git a/types/command/config.d.ts b/types/command/config.d.ts new file mode 100644 index 0000000..85bb2a2 --- /dev/null +++ b/types/command/config.d.ts @@ -0,0 +1,11 @@ +import { Command } from 'commander'; +import type { Rules, Values } from 'async-validator'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; +declare class ConfigCommand extends BaseSubCommand { + constructor(rc: Registry); + validateParameters(rule: Rules, parameters: Values): Promise; + handleList(content: any): string; + run(commander: Command, ...args: any[]): Promise; +} +export default ConfigCommand; diff --git a/types/command/console.d.ts b/types/command/console.d.ts new file mode 100644 index 0000000..057796f --- /dev/null +++ b/types/command/console.d.ts @@ -0,0 +1,8 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; +declare class ConsoleCommand extends BaseSubCommand { + constructor(rc: Registry, name?: string, description?: string); + run(commander: Command, ...args: any[]): Promise; +} +export default ConsoleCommand; diff --git a/types/command/create.d.ts b/types/command/create.d.ts new file mode 100644 index 0000000..b65982c --- /dev/null +++ b/types/command/create.d.ts @@ -0,0 +1,8 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; +declare class CreateCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} +export default CreateCommand; diff --git a/types/command/dappServer/HKDF.d.ts b/types/command/dappServer/HKDF.d.ts new file mode 100644 index 0000000..a854ee8 --- /dev/null +++ b/types/command/dappServer/HKDF.d.ts @@ -0,0 +1,11 @@ +declare class HKDF { + constructor(hash: string, salt: Buffer, initialKey: string); + private hashMethod: string; + private hashLength: number; + private salt: Buffer; + private initialKey: string; + private prk: Buffer; + expand(info?: string, size?: number): Buffer; + static hashList: { [key: string]: number }; +} +export default HKDF; diff --git a/types/command/dappServer/constants.d.ts b/types/command/dappServer/constants.d.ts new file mode 100644 index 0000000..6a2593d --- /dev/null +++ b/types/command/dappServer/constants.d.ts @@ -0,0 +1,11 @@ +export const CHAIN_APIS: { + '/api/blockChain/chainStatus': string; + '/api/blockChain/blockState': string; + '/api/blockChain/contractFileDescriptorSet': string; + '/api/blockChain/blockHeight': string; + '/api/blockChain/block': string; + '/api/blockChain/blockByHeight': string; + '/api/blockChain/transactionResult': string; + '/api/blockChain/transactionResults': string; + '/api/blockChain/merklePathByTransactionId': string; +}; diff --git a/types/command/dappServer/encrypt.d.ts b/types/command/dappServer/encrypt.d.ts new file mode 100644 index 0000000..93f10ea --- /dev/null +++ b/types/command/dappServer/encrypt.d.ts @@ -0,0 +1,17 @@ +import { ec } from 'elliptic'; + +declare class Encrypt { + constructor(algorithm: string, remotePublicKey: string, random: string, cipher?: string); + private keyPair: ec.KeyPair; + private cipher: string; + private remoteKeyPair: ec.KeyPair; + private sharedKey: Buffer; + private derivedKey: Buffer; + + encrypt(data: string): { encryptedResult: string; iv: string }; + + decrypt(encrypted: string, iv: string): string; + + getPublicKey(): string; +} +export default Encrypt; diff --git a/types/command/dappServer/index.d.ts b/types/command/dappServer/index.d.ts new file mode 100644 index 0000000..569440a --- /dev/null +++ b/types/command/dappServer/index.d.ts @@ -0,0 +1,10 @@ +import { Command } from 'commander'; +import BaseSubCommand from '../baseSubCommand'; +import Registry from '../../rc/index'; + +declare class DappServerCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} + +export default DappServerCommand; diff --git a/types/command/dappServer/sign.d.ts b/types/command/dappServer/sign.d.ts new file mode 100644 index 0000000..8a6a7ee --- /dev/null +++ b/types/command/dappServer/sign.d.ts @@ -0,0 +1,11 @@ +import { ec } from 'elliptic'; +declare class Sign { + static verify(algorithm: string, publicKey: string, msg: Buffer, signature: string): boolean; + constructor(algorithm: string, publicKey: string); + keyPair: ec.KeyPair; + remoteKeyPair: ec.KeyPair; + sign(msg: Buffer): string; + verify(msg: Buffer, signature: string): boolean; + getPublicKey(): string; +} +export default Sign; diff --git a/types/command/dappServer/socket.d.ts b/types/command/dappServer/socket.d.ts new file mode 100644 index 0000000..6eef934 --- /dev/null +++ b/types/command/dappServer/socket.d.ts @@ -0,0 +1,65 @@ +import { Server } from 'socket.io'; +import type { Rules } from 'async-validator'; +import Schema from 'async-validator'; + +declare const signRequestRules: Rules; +declare const encryptRequestRules: Rules; +declare const connectSignRules: Rules; +declare const connectEncryptRules: Rules; + +declare const signRequestValidator: Schema; +declare const encryptRequestValidator: Schema; +declare const connectSignValidator: Schema; +declare const connectEncryptValidator: Schema; + +interface SocketOptions { + port: number; + endpoint: string; + aelf: any; + wallet: any; + address: string; +} + +interface Message { + id: string; + appId: string; + action: string; + params: any; +} + +interface Result { + code: number; + msg: string; + error: any[]; + data: any; +} + +interface Client { + emit(event: string, data: any): void; + disconnect(close?: boolean): void; + on(event: string, cb: Function): void; +} +declare class Socket { + private aelf: any; + private defaultEndpoint: string; + private wallet: any; + private address: string; + private socket: Server; + private clientConfig: { [key: string]: any }; + + constructor(options: SocketOptions); + + private responseFormat(id: string, result?: any, errors?: any): { id: string; result: Result }; + private send(client: Client, result: Result, action: string, appId: string): void; + private handleConnection(client: Client): void; + private deserializeParams(request: Message): Promise; + private serializeResult(appId: string, result: any): any; + private handleConnect(message: Message): Promise; + private handleMethodList(message: Message): Promise; + private handleApi(message: Message): Promise; + private handleAccount(message: Message): Promise; + private handleInvoke(message: Message, isReadOnly: boolean): Promise; + private handleDisconnect(message: Message): Promise<{}>; +} + +export default Socket; diff --git a/types/command/dappServer/utils.d.ts b/types/command/dappServer/utils.d.ts new file mode 100644 index 0000000..13b2824 --- /dev/null +++ b/types/command/dappServer/utils.d.ts @@ -0,0 +1,3 @@ +export function serializeMessage(data: any): string; +export function deserializeMessage(str: string): any; +export function checkTimestamp(time: string, timeBuffer?: number): boolean; diff --git a/types/command/deploy.d.ts b/types/command/deploy.d.ts new file mode 100644 index 0000000..4e9a4c6 --- /dev/null +++ b/types/command/deploy.d.ts @@ -0,0 +1,8 @@ +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class DeployCommand extends BaseSubCommand { + constructor(rc: Registry, name?: string, description?: string, usage?: string[]); + run(): Promise; +} +export default DeployCommand; diff --git a/types/command/event.d.ts b/types/command/event.d.ts new file mode 100644 index 0000000..4e008ae --- /dev/null +++ b/types/command/event.d.ts @@ -0,0 +1,9 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class EventCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} +export default EventCommand; diff --git a/types/command/getBlkHeight.d.ts b/types/command/getBlkHeight.d.ts new file mode 100644 index 0000000..03d089d --- /dev/null +++ b/types/command/getBlkHeight.d.ts @@ -0,0 +1,9 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; +declare class GetBlkHeightCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} + +export default GetBlkHeightCommand; diff --git a/types/command/getBlkInfo.d.ts b/types/command/getBlkInfo.d.ts new file mode 100644 index 0000000..2dc520d --- /dev/null +++ b/types/command/getBlkInfo.d.ts @@ -0,0 +1,11 @@ +import { Command } from 'commander'; +import type { Rules, Values } from 'async-validator'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class GetBlkInfoCommand extends BaseSubCommand { + constructor(rc: Registry); + validateParameters(rule: Rules, parameters: Values): Promise; + run(commander: Command, ...args: any[]): Promise; +} +export default GetBlkInfoCommand; diff --git a/types/command/getChainStatus.d.ts b/types/command/getChainStatus.d.ts new file mode 100644 index 0000000..e64b73b --- /dev/null +++ b/types/command/getChainStatus.d.ts @@ -0,0 +1,9 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class GetChainStatusCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} +export default GetChainStatusCommand; diff --git a/types/command/getTxResult.d.ts b/types/command/getTxResult.d.ts new file mode 100644 index 0000000..fc80b31 --- /dev/null +++ b/types/command/getTxResult.d.ts @@ -0,0 +1,11 @@ +import { Command } from 'commander'; +import type { Rules, Values } from 'async-validator'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class GetTxResultCommand extends BaseSubCommand { + constructor(rc: Registry); + validateParameters(rule: Rules, parameters: Values): Promise; + run(commander: Command, ...args: any[]): Promise; +} +export default GetTxResultCommand; diff --git a/types/command/index.d.ts b/types/command/index.d.ts new file mode 100644 index 0000000..8449681 --- /dev/null +++ b/types/command/index.d.ts @@ -0,0 +1,51 @@ +import CallCommand from './call'; +import SendCommand from './send'; +import GetBlkHeightCommand from './getBlkHeight'; +import GetChainStatus from './getChainStatus'; +import GetBlkInfoCommand from './getBlkInfo'; +import GetTxResultCommand from './getTxResult'; +import ConsoleCommand from './console'; +import CreateCommand from './create'; +import WalletCommand from './wallet'; +import LoadCommand from './load'; +import ProposalCommand from './proposal'; +import DeployCommand from './deploy'; +import ConfigCommand from './config'; +import EventCommand from './event'; +import DappServerCommand from './dappServer/index'; +namespace _default { + export { CallCommand }; + export { SendCommand }; + export { GetBlkHeightCommand }; + export { GetChainStatus }; + export { GetBlkInfoCommand }; + export { GetTxResultCommand }; + export { ConsoleCommand }; + export { CreateCommand }; + export { WalletCommand }; + export { LoadCommand }; + export { ProposalCommand }; + export { DeployCommand }; + export { ConfigCommand }; + export { EventCommand }; + export { DappServerCommand }; +} +export default _default; + +export { + CallCommand, + SendCommand, + GetBlkHeightCommand, + GetChainStatus, + GetBlkInfoCommand, + GetTxResultCommand, + ConsoleCommand, + CreateCommand, + WalletCommand, + LoadCommand, + ProposalCommand, + DeployCommand, + ConfigCommand, + EventCommand, + DappServerCommand, +}; diff --git a/types/command/load.d.ts b/types/command/load.d.ts new file mode 100644 index 0000000..46aa8fc --- /dev/null +++ b/types/command/load.d.ts @@ -0,0 +1,9 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class LoadCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} +export default LoadCommand; diff --git a/types/command/proposal.d.ts b/types/command/proposal.d.ts new file mode 100644 index 0000000..e714a95 --- /dev/null +++ b/types/command/proposal.d.ts @@ -0,0 +1,26 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class ProposalCommand extends BaseSubCommand { + constructor( + rc: Registry, + name?: string, + description?: string, + parameters?: { + type: string; + name: string; + message: string; + choices?: string[]; + suffix: string; + format?: string[]; + initial?: Date; + }[], + usage?: string[], + options?: any[], + ); + processAddressAfterPrompt(aelf: any, wallet: any, answerInput: { [key: string]: any }): Promise; + toContractAddress: any; + run(commander: Command, ...args: any[]): Promise; +} +export default ProposalCommand; diff --git a/types/command/send.d.ts b/types/command/send.d.ts new file mode 100644 index 0000000..6f3f991 --- /dev/null +++ b/types/command/send.d.ts @@ -0,0 +1,7 @@ +import CallCommand from './call'; +import Registry from '../rc/index'; +export default SendCommand; +declare class SendCommand extends CallCommand { + constructor(rc: Registry); + callMethod(method: any, params: any): Promise; +} diff --git a/types/command/wallet.d.ts b/types/command/wallet.d.ts new file mode 100644 index 0000000..edebe30 --- /dev/null +++ b/types/command/wallet.d.ts @@ -0,0 +1,9 @@ +import { Command } from 'commander'; +import BaseSubCommand from './baseSubCommand'; +import Registry from '../rc/index'; + +declare class WalletCommand extends BaseSubCommand { + constructor(rc: Registry); + run(commander: Command, ...args: any[]): Promise; +} +export default WalletCommand; diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..7266eff --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1 @@ +export declare function run(): void; diff --git a/types/rc/index.d.ts b/types/rc/index.d.ts new file mode 100644 index 0000000..8bb6469 --- /dev/null +++ b/types/rc/index.d.ts @@ -0,0 +1,23 @@ +declare class Registry { + constructor(); + static getFileOrNot(file: string, defaultContent?: string): any; + static getFileOrCreate(file: string): string; + static loadConfig(content?: string): { [key: string]: any }; + static getConfigFromEnv(): { [key: string]: any }; + static stringify(obj?: { [key: string]: any }): string[]; + globalConfigLoc: string; + aelfConfig: { [key: string]: any }; + init(): { + endpoint: string; + datadir: string; + password: string; + account: string; + }; + getOption(key: string): any; + setOption(key: string, value: any): void; + saveOption(key: string, value: any, filePath?: any): any; + deleteConfig(key: string, filePath?: any): any; + getFileConfigs(filePath?: string): { [key: string]: any }; + getConfigs(): { [key: string]: any }; +} +export default Registry; diff --git a/types/utils/Logger.d.ts b/types/utils/Logger.d.ts new file mode 100644 index 0000000..409e80d --- /dev/null +++ b/types/utils/Logger.d.ts @@ -0,0 +1,7 @@ +export default Logger; +declare class Logger { + constructor(props: { [key: string]: any }); + symbol: string; + name: string; + log: boolean; +} diff --git a/types/utils/constants.d.ts b/types/utils/constants.d.ts new file mode 100644 index 0000000..27b245d --- /dev/null +++ b/types/utils/constants.d.ts @@ -0,0 +1,159 @@ +export const callCommandUsages: string[]; +export interface CallCommandParameter { + type: string; + name: string; + message: string; + pageSize?: number; + choices?: string[]; + suffix: string; + extraName?: string[]; + filter?: (input: any) => string; +} +export const callCommandParameters: CallCommandParameter[]; + +export interface PasswordValidatorDesc { + type: string; + required: boolean; + message: string; + validator(rule: any, value: any): boolean; +} + +export interface EndpointValidatorDesc { + type: string; + required: boolean; + pattern: RegExp; + message: string; +} + +export interface DatadirValidatorDesc { + type: string; + required: boolean; + message: string; +} + +export interface AccountValidatorDesc { + type: string; + required: boolean; + message: string; +} +export interface CommonGlobalOptionValidatorDesc { + password: PasswordValidatorDesc; + endpoint: EndpointValidatorDesc; + datadir: DatadirValidatorDesc; + account: AccountValidatorDesc; +} +export const commonGlobalOptionValidatorDesc: CommonGlobalOptionValidatorDesc; + +export const strictGlobalOptionValidatorDesc: CommonGlobalOptionValidatorDesc; + +export interface BlkInfoCommandParameter { + type: 'input' | 'confirm'; + name: string; + extraName?: string[]; + message: string; + suffix: string; + required?: boolean; + initial?: boolean; + active?: string; + inactive?: string; +} +export const blkInfoCommandParameters: BlkInfoCommandParameter[]; +export const blkInfoCommandUsage: string[]; + +export interface TxResultCommandParameter { + type: 'input'; + name: string; + message: string; + suffix: string; +} +export const txResultCommandParameters: TxResultCommandParameter[]; +export const txResultCommandUsage: string[]; + +export interface GlobalOptionPrompt { + type: 'input' | 'password'; + name: string; + message: string; + suffix: string; + mask?: string; +} +export const globalOptionsPrompts: GlobalOptionPrompt[]; + +export interface CreateCommandParameter { + type: 'confirm'; + name: string; + required?: boolean; + initial?: boolean; + default?: boolean; + message: string; + active: string; + inactive: string; +} +export const createCommandParameters: CreateCommandParameter[]; +export const createCommandUsage: string[]; + +export interface LoadCommandParameter { + type: 'input' | 'confirm'; + name: string; + required?: boolean; + initial?: boolean; + default?: boolean; + message: string; + active?: string; + inactive?: string; + suffix: string; + extraName?: string[]; + when?(answers: Record): boolean; +} +export const loadCommandParameters: LoadCommandParameter[]; +export const loadCommandUsage: string[]; + +export interface PasswordPrompt { + type: 'password'; + name: string; + mask: string; + message: string; + validate?(val: string): boolean | string | Promise; + suffix: string; +} +export const passwordPrompts: PasswordPrompt[]; +export const deployCommandUsage: string[]; + +export interface DeployCommandParameter { + type: 'input'; + name: string; + message: string; + suffix: string; + filter?(val: any): any; +} +export const deployCommandParameters: DeployCommandParameter[]; + +export interface ConfigCommandParameter { + type: 'input'; + name: string; + required?: boolean; + message: string; + suffix: string; +} +export const configCommandParameters: ConfigCommandParameter[]; +export const configCommandUsage: string[]; + +export interface ProposalCommandParameter { + type: 'list' | 'input' | 'date'; + name: string; + message: string; + suffix: string; + choices?: string[]; + format?: string[]; + initial?: Date | string | (() => Date | string); +} +export const proposalCommandParameters: ProposalCommandParameter[]; +export const proposalCommandUsage: string[]; + +export interface EventCommandParameter { + type: 'input'; + name: string; + message: string; + suffix: string; +} +export const eventCommandParameters: EventCommandParameter[]; +export const eventCommandUsage: string[]; diff --git a/types/utils/fs.d.ts b/types/utils/fs.d.ts new file mode 100644 index 0000000..b7680ed --- /dev/null +++ b/types/utils/fs.d.ts @@ -0,0 +1,5 @@ +declare const cr: number; +declare const lf: number; + +declare function getEolFromFile(path: string): Promise; +export function writeFilePreservingEol(path: string, data: string): Promise; diff --git a/types/utils/myLogger.d.ts b/types/utils/myLogger.d.ts new file mode 100644 index 0000000..49a7e99 --- /dev/null +++ b/types/utils/myLogger.d.ts @@ -0,0 +1,3 @@ +import Logger from './Logger'; +export const logger: Logger; +export const plainLogger: Logger; diff --git a/types/utils/userHomeDir.d.ts b/types/utils/userHomeDir.d.ts new file mode 100644 index 0000000..ee7dc3d --- /dev/null +++ b/types/utils/userHomeDir.d.ts @@ -0,0 +1,7 @@ +export let userHomeDir: any; +export const home: string; +export function getUid(): number | null; +export function isFakeRoot(): boolean; +export function isWindows(): boolean; +export function isRootUser(uid: number): boolean; +export const ROOT_USER: boolean; diff --git a/types/utils/utils.d.ts b/types/utils/utils.d.ts new file mode 100644 index 0000000..6114817 --- /dev/null +++ b/types/utils/utils.d.ts @@ -0,0 +1,27 @@ +import { Ora } from 'ora'; +import { DistinctQuestion } from 'inquirer'; +export function promisify(fn: (...args: any[]) => void, firstData?: boolean): (...args: any[]) => Promise; +export function camelCase(str: string): string; +export function getContractMethods(contract?: { [key: string]: any }): string[]; +export function getContractInstance(contractAddress: string, aelf: any, wallet: any, oraInstance: Ora): Promise; +export function getMethod(method: any, contract: any): any; +export function promptTolerateSeveralTimes( + { + processAfterPrompt, + pattern, + times, + prompt + }: { + processAfterPrompt: Function; + pattern: string | RegExp; + times: number; + prompt: DistinctQuestion; + }, + oraInstance: Ora +): Promise<{ [key: string]: any }>; +export function isAElfContract(str: string): boolean; +export function getTxResult(aelf: any, txId: string, times?: number, delay?: number, timeLimit?: number): Promise; +export function parseJSON(str?: string): any; +export function randomId(): string; +export function getParams(method: any): Promise<{ [key: string]: any }>; +export function deserializeLogs(aelf: any, logs?: any[]): Promise; diff --git a/types/utils/wallet.d.ts b/types/utils/wallet.d.ts new file mode 100644 index 0000000..3545605 --- /dev/null +++ b/types/utils/wallet.d.ts @@ -0,0 +1,2 @@ +export function getWallet(commandRoot: string, address: string, password: string): any; +export function saveKeyStore(wallet: any, datadir: string, cipher?: string): Promise; diff --git a/yarn.lock b/yarn.lock index 86388a0..b0f0fa0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -48,11 +48,11 @@ tslib "^2.6.2" "@aws-sdk/types@^3.222.0": - version "3.577.0" - resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz#7700784d368ce386745f8c340d9d68cea4716f90" - integrity sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA== + version "3.598.0" + resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.598.0.tgz#b840d2446dee19a2a4731e6166f2327915d846db" + integrity sha512-742uRl6z7u0LFmZwDrFP6r1wlZcgVPw+/TilluDJmCAR8BgRw3IR+743kUXKBGd8QZDRW2n6v/PYsi/AWCDDMQ== dependencies: - "@smithy/types" "^3.0.0" + "@smithy/types" "^3.1.0" tslib "^2.6.2" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": @@ -1214,16 +1214,16 @@ integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== "@eslint/compat@^1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@eslint/compat/-/compat-1.0.3.tgz#6be44cf553a14a2f68fafb304818f7d824a7248f" - integrity sha512-9RaroPQaU2+SDcWav1YfuipwqnHccoiXZdUsicRQsQ/vH2wkEmRVcj344GapG/FnCeZRtqj0n6PshI+s9xkkAQ== + version "1.1.0" + resolved "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz#fdc7d19a66820770bf58ced0342153769d8686f0" + integrity sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ== -"@eslint/config-array@^0.15.1": - version "0.15.1" - resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz#1fa78b422d98f4e7979f2211a1fde137e26c7d61" - integrity sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ== +"@eslint/config-array@^0.16.0": + version "0.16.0" + resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz#bb3364fc39ee84ec3a62abdc4b8d988d99dfd706" + integrity sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg== dependencies: - "@eslint/object-schema" "^2.1.3" + "@eslint/object-schema" "^2.1.4" debug "^4.3.1" minimatch "^3.0.5" @@ -1242,15 +1242,15 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.4.0": - version "9.4.0" - resolved "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz#96a2edd37ec0551ce5f9540705be23951c008a0c" - integrity sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg== +"@eslint/js@9.5.0": + version "9.5.0" + resolved "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz#0e9c24a670b8a5c86bff97b40be13d8d8f238045" + integrity sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w== -"@eslint/object-schema@^2.1.3": - version "2.1.3" - resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz#e65ae80ee2927b4fd8c5c26b15ecacc2b2a6cc2a" - integrity sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw== +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" @@ -1512,13 +1512,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@ljharb/through@^2.3.13": - version "2.3.13" - resolved "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz#b7e4766e0b65aa82e529be945ab078de79874edc" - integrity sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ== - dependencies: - call-bind "^1.0.7" - "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -1662,10 +1655,10 @@ dependencies: tslib "^2.6.2" -"@smithy/types@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz#00231052945159c64ffd8b91e8909d8d3006cb7e" - integrity sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw== +"@smithy/types@^3.1.0": + version "3.3.0" + resolved "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== dependencies: tslib "^2.6.2" @@ -1761,6 +1754,14 @@ resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== +"@types/inquirer@^9.0.7": + version "9.0.7" + resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz#61bb8d0e42f038b9a1738b08fba7fa98ad9b4b24" + integrity sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g== + dependencies: + "@types/through" "*" + rxjs "^7.2.0" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" @@ -1796,9 +1797,9 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/node@*", "@types/node@>=10.0.0": - version "20.14.2" - resolved "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18" - integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q== + version "20.14.9" + resolved "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== dependencies: undici-types "~5.26.4" @@ -1817,6 +1818,13 @@ resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/through@*": + version "0.0.33" + resolved "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56" + integrity sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1829,26 +1837,26 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/scope-manager@7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.0.tgz#6927d6451537ce648c6af67a2327378d4cc18462" - integrity sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng== +"@typescript-eslint/scope-manager@7.14.1": + version "7.14.1" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz#63de7a577bc6fe8ee6e412a5b85499f654b93ee5" + integrity sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA== dependencies: - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/visitor-keys" "7.13.0" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" -"@typescript-eslint/types@7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz#0cca95edf1f1fdb0cfe1bb875e121b49617477c5" - integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== +"@typescript-eslint/types@7.14.1": + version "7.14.1" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz#a43a540dbe5df7f2a11269683d777fc50b4350aa" + integrity sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg== -"@typescript-eslint/typescript-estree@7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.0.tgz#4cc24fc155088ebf3b3adbad62c7e60f72c6de1c" - integrity sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw== +"@typescript-eslint/typescript-estree@7.14.1": + version "7.14.1" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz#ba7c9bac8744487749d19569e254d057754a1575" + integrity sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA== dependencies: - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/visitor-keys" "7.13.0" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1857,21 +1865,21 @@ ts-api-utils "^1.3.0" "@typescript-eslint/utils@^6.0.0 || ^7.0.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.0.tgz#f84e7e8aeceae945a9a3f40d077fd95915308004" - integrity sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ== + version "7.14.1" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz#3307b8226f99103dca2133d0ebcae38419d82c9d" + integrity sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.13.0" - "@typescript-eslint/types" "7.13.0" - "@typescript-eslint/typescript-estree" "7.13.0" + "@typescript-eslint/scope-manager" "7.14.1" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/typescript-estree" "7.14.1" -"@typescript-eslint/visitor-keys@7.13.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.0.tgz#2eb7ce8eb38c2b0d4a494d1fe1908e7071a1a353" - integrity sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw== +"@typescript-eslint/visitor-keys@7.14.1": + version "7.14.1" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz#cc79b5ea154aea734b2a13b983670749f5742274" + integrity sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA== dependencies: - "@typescript-eslint/types" "7.13.0" + "@typescript-eslint/types" "7.14.1" eslint-visitor-keys "^3.4.3" JSONStream@^1.0.4, JSONStream@^1.3.5: @@ -1895,10 +1903,10 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.11.3: - version "8.11.3" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.12.0: + version "8.12.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" + integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== add-stream@^1.0.0: version "1.0.0" @@ -2491,9 +2499,9 @@ camelcase@^8.0.0: integrity sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA== caniuse-lite@^1.0.30001629: - version "1.0.30001632" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz#964207b7cba5851701afb4c8afaf1448db3884b6" - integrity sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg== + version "1.0.30001638" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz#598e1f0c2ac36f37ebc3f5b8887a32ca558e5d56" + integrity sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ== chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" @@ -3306,9 +3314,9 @@ eastasianwidth@^0.2.0: integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== electron-to-chromium@^1.4.796: - version "1.4.799" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.799.tgz#271c56654ab4dc703037e47a5af4fc8945160611" - integrity sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q== + version "1.4.814" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz#176535a0b899c9c473464502ab77576aa8bb1cbe" + integrity sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw== elliptic@^6.4.1, elliptic@^6.5.2, elliptic@^6.5.5: version "6.5.5" @@ -3344,14 +3352,14 @@ emoji-regex@^9.2.2: integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== engine.io-client@~6.5.2: - version "6.5.3" - resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz#4cf6fa24845029b238f83c628916d9149c399bc5" - integrity sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q== + version "6.5.4" + resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz#b8bc71ed3f25d0d51d587729262486b4b33bd0d0" + integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" engine.io-parser "~5.2.1" - ws "~8.11.0" + ws "~8.17.1" xmlhttprequest-ssl "~2.0.0" engine.io-parser@~5.2.1: @@ -3360,9 +3368,9 @@ engine.io-parser@~5.2.1: integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== engine.io@~6.5.2: - version "6.5.4" - resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc" - integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg== + version "6.5.5" + resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz#430b80d8840caab91a50e9e23cb551455195fc93" + integrity sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" @@ -3373,7 +3381,7 @@ engine.io@~6.5.2: cors "~2.8.5" debug "~4.3.1" engine.io-parser "~5.2.1" - ws "~8.11.0" + ws "~8.17.1" env-paths@^2.2.1: version "2.2.1" @@ -3614,15 +3622,15 @@ eslint-visitor-keys@^4.0.0: integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== eslint@^9.3.0: - version "9.4.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz#79150c3610ae606eb131f1d648d5f43b3d45f3cd" - integrity sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA== + version "9.5.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz#11856034b94a9e1a02cfcc7e96a9f0956963cd2f" + integrity sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/config-array" "^0.15.1" + "@eslint/config-array" "^0.16.0" "@eslint/eslintrc" "^3.1.0" - "@eslint/js" "9.4.0" + "@eslint/js" "9.5.0" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.3.0" "@nodelib/fs.walk" "^1.2.8" @@ -3634,7 +3642,7 @@ eslint@^9.3.0: eslint-scope "^8.0.1" eslint-visitor-keys "^4.0.0" espree "^10.0.1" - esquery "^1.4.2" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^8.0.0" @@ -3654,11 +3662,11 @@ eslint@^9.3.0: text-table "^0.2.0" espree@^10.0.1: - version "10.0.1" - resolved "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" - integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== + version "10.1.0" + resolved "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" + integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== dependencies: - acorn "^8.11.3" + acorn "^8.12.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^4.0.0" @@ -3667,7 +3675,7 @@ esprima@^4.0.0: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: +esquery@^1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -4510,20 +4518,17 @@ inquirer@^3.3.0: through "^2.3.6" inquirer@^9.2.22: - version "9.2.23" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-9.2.23.tgz#cd2fe34edca12315b624fbc3c8cb99b1c4f61f90" - integrity sha512-kod5s+FBPIDM2xiy9fu+6wdU/SkK5le5GS9lh4FEBjBHqiMgD9lLFbCbuqFNAjNL2ZOy9Wd9F694IOzN9pZHBA== + version "9.3.1" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-9.3.1.tgz#71482e4fd283deebe9d175dc7c78b12fb5ff6a7c" + integrity sha512-A5IdVr1I04XqPlwrGgTJMKmzRg5ropqNpSeqo0vj1ZmluSCNSFaPZz4eazdPrhVcZfej7fCEYvD2NYa1KjkTJA== dependencies: "@inquirer/figures" "^1.0.3" - "@ljharb/through" "^2.3.13" ansi-escapes "^4.3.2" - chalk "^5.3.0" - cli-cursor "^3.1.0" cli-width "^4.1.0" external-editor "^3.1.0" - lodash "^4.17.21" mute-stream "1.0.0" ora "^5.4.1" + picocolors "^1.0.1" run-async "^3.0.0" rxjs "^7.8.1" string-width "^4.2.3" @@ -4581,11 +4586,11 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.5.0: - version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + version "2.14.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" is-data-view@^1.0.1: version "1.0.1" @@ -5382,9 +5387,9 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lint-staged@^15.2.5: - version "15.2.6" - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.6.tgz#6e4b0c4ba4a692c52e2143a3bb4b360ac5832121" - integrity sha512-M/3PdijFXT/A5lnbSK3EQNLbIIrkE00JZaD39r7t4kfFOqT1Ly9LgSZSMMtvQ3p2/C8Nyj/ou0vkNHmEwqoB8g== + version "15.2.7" + resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz#97867e29ed632820c0fb90be06cd9ed384025649" + integrity sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw== dependencies: chalk "~5.3.0" commander "~12.1.0" @@ -5398,15 +5403,15 @@ lint-staged@^15.2.5: yaml "~2.4.2" listr2@~8.2.1: - version "8.2.1" - resolved "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz#06a1a6efe85f23c5324180d7c1ddbd96b5eefd6d" - integrity sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g== + version "8.2.3" + resolved "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz#c494bb89b34329cf900e4e0ae8aeef9081d7d7a5" + integrity sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw== dependencies: cli-truncate "^4.0.0" colorette "^2.0.20" eventemitter3 "^5.0.1" log-update "^6.0.0" - rfdc "^1.3.1" + rfdc "^1.4.1" wrap-ansi "^9.0.0" load-json-file@^4.0.0: @@ -5720,9 +5725,9 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: brace-expansion "^1.1.7" minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" @@ -5786,9 +5791,9 @@ mute-stream@1.0.0: integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== nan@^2.14.0: - version "2.19.0" - resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" - integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== + version "2.20.0" + resolved "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" + integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== natural-compare@^1.4.0: version "1.4.0" @@ -5875,9 +5880,9 @@ object-filter@^1.0.2: integrity sha512-NahvP2vZcy1ZiiYah30CEPw0FpDcSkSePJBMpzl5EQgCmISijiGuJm3SPYp7U+Lf2TljyaIw3E5EgkEx/TNEVA== object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + version "1.13.2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== object-is@^1.1.5: version "1.1.6" @@ -6556,10 +6561,10 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" @@ -6598,7 +6603,7 @@ rx-lite@*, rx-lite@^4.0.8: resolved "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" integrity sha512-Cun9QucwK6MIrp3mry/Y7hqD1oFqTYLQ4pGxaHTjIdaFDWRGGLikqp6u8LcWJnzpoALg9hap+JGk8sFIUuEGNA== -rxjs@^7.5.5, rxjs@^7.8.1: +rxjs@^7.2.0, rxjs@^7.5.5, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -6769,12 +6774,12 @@ slice-ansi@^7.0.0: is-fullwidth-code-point "^5.0.0" socket.io-adapter@~2.5.2: - version "2.5.4" - resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz#4fdb1358667f6d68f25343353bd99bd11ee41006" - integrity sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg== + version "2.5.5" + resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082" + integrity sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg== dependencies: debug "~4.3.4" - ws "~8.11.0" + ws "~8.17.1" socket.io-client@^4.7.5: version "4.7.5" @@ -7285,6 +7290,11 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typescript@^5.5.2: + version "5.5.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507" + integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew== + uglify-js@^3.1.4: version "3.18.0" resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz#73b576a7e8fda63d2831e293aeead73e0a270deb" @@ -7400,9 +7410,9 @@ uuid@^9.0.1: integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + version "9.3.0" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" @@ -7547,10 +7557,10 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: version "5.1.0"