From 4260e6557e7bc362fde10f7e1ee380f4840f05fe Mon Sep 17 00:00:00 2001 From: Aliaksandr Bahdanau Date: Thu, 20 Jun 2024 20:10:58 +0300 Subject: [PATCH] feat: add help commands --- src/cli/build.ts | 6 +++ src/cli/constants.ts | 87 ++++++++++++++++++++++++++++++++++++++++++++ src/cli/convert.ts | 8 +++- src/cli/create.ts | 6 +++ src/cli/help.ts | 70 +---------------------------------- src/cli/run.ts | 7 +++- src/cli/set.ts | 8 ++++ src/cli/test.ts | 10 ++++- src/cli/verify.ts | 7 +++- 9 files changed, 136 insertions(+), 73 deletions(-) create mode 100644 src/cli/constants.ts diff --git a/src/cli/build.ts b/src/cli/build.ts index 6ef652c..8747b9f 100644 --- a/src/cli/build.ts +++ b/src/cli/build.ts @@ -3,6 +3,7 @@ import { findCompiles, selectFile } from '../utils'; import { UIProvider } from '../ui/UIProvider'; import arg from 'arg'; import { buildAll, buildOne } from '../build'; +import { helpArgs, helpMessages } from './constants'; export async function selectCompile(ui: UIProvider, args: Args) { return await selectFile(await findCompiles(), { @@ -15,7 +16,12 @@ export async function selectCompile(ui: UIProvider, args: Args) { export const build: Runner = async (args: Args, ui: UIProvider) => { const localArgs = arg({ '--all': Boolean, + ...helpArgs, }); + if (localArgs['--help']) { + ui.write(helpMessages['build']); + return; + } if (localArgs['--all']) { await buildAll(); diff --git a/src/cli/constants.ts b/src/cli/constants.ts new file mode 100644 index 0000000..bbfecd0 --- /dev/null +++ b/src/cli/constants.ts @@ -0,0 +1,87 @@ +export const templateTypes: { name: string; value: string }[] = [ + { + name: 'An empty contract (FunC)', + value: 'func-empty', + }, + { + name: 'A simple counter contract (FunC)', + value: 'func-counter', + }, + { + name: 'An empty contract (TACT)', + value: 'tact-empty', + }, + { + name: 'A simple counter contract (TACT)', + value: 'tact-counter', + }, +]; + +export const helpArgs = { '--help': Boolean }; +export const helpMessages = { + help: `Usage: blueprint help [command] + +Displays this message if no command is specified, or displays detailed help for the specified command. + +Blueprint is generally invoked as follows: blueprint [command] [command-args] [flags] + +List of available commands: +- create +- run +- build +- custom +- help +- test +- verify +- convert`, + create: `Usage: blueprint create [contract name] [flags] + +Creates a new contract together with supporting files according to a template. + +Contract name must be specified in PascalCase and may only include characters a-z, A-Z, 0-9. If not specified on the command line, it will be asked interactively. + +Flags: +--type - specifies the template type to use when creating the contract. If not specified on the command line, it will be asked interactively. +List of available types: +${templateTypes.map((t) => `${t.value} - ${t.name}`).join('\n')}`, + run: `Usage: blueprint run [script name] [flags] + +Runs a script from the scripts directory. + +Script name is matched (ignoring case) to a file in the scripts directory. If not specified on the command line, the available scripts will be presented interactively. + +Flags: +--mainnet, --testnet - specifies the network to use when running the script. If not specified on the command line, it will be asked interactively. +--custom [api-endpoint] - indicates that a custom API should be used when running the script, and the API URL optionally. (example: https://testnet.toncenter.com/api/v2/) +--custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4. +--custom-key - specifies the API key to use with the custom API, can only be used with API v2. +--custom-type - specifies the network type to be indicated to scripts. Options: custom (default), mainnet, testnet. +--tonconnect, --tonhub, --deeplink, --mnemonic - specifies the deployer to use when running the script. If not specified on the command line, it will be asked interactively. +--tonscan, --tonviewer, --toncx, --dton - specifies the network explorer to use when displaying links to the deployed contracts. Default: tonscan.`, + build: `Usage: blueprint build [contract name] [flags] + +Builds the specified contract according to the respective .compile.ts file. If the contract is written in TACT, all TACT-generated files (wrapper class, etc) will be placed in the build/ folder. + +If contract name is not specified on the command line, the buildable contracts (that have the respective .compile.ts files under wrappers directory) will be presented interactively, unless --all flag is specified. + +Flags: +--all - builds all buildable contracts instead of just one.`, + set: `Usage: blueprint set [value] +Available keys: +- func - overrides @ton-community/func-js-bin version, effectively setting the func version. The required version may be passed as the value, otherwise available versions will be displayed.`, + test: `Usage: blueprint test + +Just runs \`npm test\`, which by default runs \`jest\`.`, + verify: `Usage: blueprint verify [contract name] [flags] + +Builds a contract (similar to build command) and verifies it on https://verifier.ton.org. The contract must be already deployed on the network. If the contract's name is not specified on the command line, it will be asked interactively. + +Flags: +--mainnet, --testnet - specifies the network to use when running the script. If not specified on the command line, it will be asked interactively. +--custom [api-endpoint] - indicates that a custom API should be used when running the script, and the API URL optionally. (example: https://testnet.toncenter.com/api/v2/) Requires --custom-type to be specified. +--custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4. +--custom-key - specifies the API key to use with the custom API, can only be used with API v2. +--custom-type - specifies the network type to be indicated to scripts. Options: mainnet, testnet.`, + convert: `Usage: blueprint convert [path to build script] +Atempts to convert legacy bash build script to a blueprint compile wrapper.`, +} satisfies { [name: string]: string }; diff --git a/src/cli/convert.ts b/src/cli/convert.ts index c9889c5..b7b48aa 100644 --- a/src/cli/convert.ts +++ b/src/cli/convert.ts @@ -6,6 +6,7 @@ import { argSpec } from '../network/createNetworkProvider'; import { executeTemplate, TEMPLATES_DIR } from '../template'; import { WRAPPERS_DIR } from '../paths'; import { Args, Runner } from './Runner'; +import { helpArgs, helpMessages } from './constants'; function createWrapperName(old: string) { return old @@ -90,7 +91,12 @@ function parseCompileString(str: string, src_dir: string, ui: UIProvider) { } export const convert: Runner = async (args: Args, ui: UIProvider) => { - const localArgs = arg(argSpec); + const localArgs = arg({ ...argSpec, ...helpArgs }); + if (localArgs['--help']) { + ui.write(helpMessages['convert']); + return; + } + let filePath: string; if (localArgs._.length < 2) { filePath = await ui.input('Please specify path to convert from:'); diff --git a/src/cli/create.ts b/src/cli/create.ts index d5eaba3..b2ddac4 100644 --- a/src/cli/create.ts +++ b/src/cli/create.ts @@ -6,6 +6,7 @@ import { selectOption } from '../utils'; import arg from 'arg'; import { UIProvider } from '../ui/UIProvider'; import { buildOne } from '../build'; +import { helpArgs, helpMessages } from './constants'; function toSnakeCase(v: string): string { const r = v.replace(/[A-Z]/g, (sub) => '_' + sub.toLowerCase()); @@ -69,7 +70,12 @@ export const templateTypes: { name: string; value: string }[] = [ export const create: Runner = async (args: Args, ui: UIProvider) => { const localArgs = arg({ '--type': String, + ...helpArgs, }); + if (localArgs['--help']) { + ui.write(helpMessages['create']); + return; + } const name = localArgs._.length > 1 && localArgs._[1].trim().length > 0 diff --git a/src/cli/help.ts b/src/cli/help.ts index c8cc701..4dcfcb1 100644 --- a/src/cli/help.ts +++ b/src/cli/help.ts @@ -1,74 +1,6 @@ import { UIProvider } from '../ui/UIProvider'; import { Args, Runner } from './Runner'; -import { templateTypes } from './create'; - -const helpMessages: { [name: string]: string } = { - help: `Usage: blueprint help [command] - -Displays this message if no command is specified, or displays detailed help for the specified command. - -Blueprint is generally invoked as follows: blueprint [command] [command-args] [flags] - -List of available commands: -- create -- run -- build -- custom -- help -- test -- verify -- convert`, - create: `Usage: blueprint create [contract name] [flags] - -Creates a new contract together with supporting files according to a template. - -Contract name must be specified in PascalCase and may only include characters a-z, A-Z, 0-9. If not specified on the command line, it will be asked interactively. - -Flags: ---type - specifies the template type to use when creating the contract. If not specified on the command line, it will be asked interactively. -List of available types: -${templateTypes.map((t) => `${t.value} - ${t.name}`).join('\n')}`, - run: `Usage: blueprint run [script name] [flags] - -Runs a script from the scripts directory. - -Script name is matched (ignoring case) to a file in the scripts directory. If not specified on the command line, the available scripts will be presented interactively. - -Flags: ---mainnet, --testnet - specifies the network to use when running the script. If not specified on the command line, it will be asked interactively. ---custom [api-endpoint] - indicates that a custom API should be used when running the script, and the API URL optionally. (example: https://testnet.toncenter.com/api/v2/) ---custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4. ---custom-key - specifies the API key to use with the custom API, can only be used with API v2. ---custom-type - specifies the network type to be indicated to scripts. Options: custom (default), mainnet, testnet. ---tonconnect, --tonhub, --deeplink, --mnemonic - specifies the deployer to use when running the script. If not specified on the command line, it will be asked interactively. ---tonscan, --tonviewer, --toncx, --dton - specifies the network explorer to use when displaying links to the deployed contracts. Default: tonscan.`, - build: `Usage: blueprint build [contract name] [flags] - -Builds the specified contract according to the respective .compile.ts file. If the contract is written in TACT, all TACT-generated files (wrapper class, etc) will be placed in the build/ folder. - -If contract name is not specified on the command line, the buildable contracts (that have the respective .compile.ts files under wrappers directory) will be presented interactively, unless --all flag is specified. - -Flags: ---all - builds all buildable contracts instead of just one.`, - set: `Usage: blueprint set [value] -Available keys: -- func - overrides @ton-community/func-js-bin version, effectively setting the func version. The required version may be passed as the value, otherwise available versions will be displayed.`, - test: `Usage: blueprint test - -Just runs \`npm test\`, which by default runs \`jest\`.`, - verify: `Usage: blueprint verify [contract name] [flags] - -Builds a contract (similar to build command) and verifies it on https://verifier.ton.org. The contract must be already deployed on the network. If the contract's name is not specified on the command line, it will be asked interactively. - -Flags: ---mainnet, --testnet - specifies the network to use when running the script. If not specified on the command line, it will be asked interactively. ---custom [api-endpoint] - indicates that a custom API should be used when running the script, and the API URL optionally. (example: https://testnet.toncenter.com/api/v2/) Requires --custom-type to be specified. ---custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4. ---custom-key - specifies the API key to use with the custom API, can only be used with API v2. ---custom-type - specifies the network type to be indicated to scripts. Options: mainnet, testnet.`, - convert: `Usage: blueprint convert [path to build script] -Atempts to convert legacy bash build script to a blueprint compile wrapper.`, -}; +import { helpMessages } from './constants'; export let additionalHelpMessages: Record = {}; diff --git a/src/cli/run.ts b/src/cli/run.ts index f57115a..5a1d29f 100644 --- a/src/cli/run.ts +++ b/src/cli/run.ts @@ -3,9 +3,14 @@ import { createNetworkProvider, argSpec } from '../network/createNetworkProvider import { findScripts, selectFile } from '../utils'; import { UIProvider } from '../ui/UIProvider'; import arg from 'arg'; +import { helpArgs, helpMessages } from './constants'; export const run: Runner = async (args: Args, ui: UIProvider, context: RunnerContext) => { - const localArgs = arg(argSpec); + const localArgs = arg({ ...argSpec, ...helpArgs }); + if (localArgs['--help']) { + ui.write(helpMessages['run']); + return; + } const { module: mod } = await selectFile(await findScripts(), { ui, diff --git a/src/cli/set.ts b/src/cli/set.ts index 2f47d29..f381534 100644 --- a/src/cli/set.ts +++ b/src/cli/set.ts @@ -3,6 +3,8 @@ import { UIProvider } from '../ui/UIProvider'; import { readFile, writeFile } from 'fs/promises'; import { exec } from 'node:child_process'; import path from 'path'; +import arg from 'arg'; +import { helpArgs, helpMessages } from './constants'; const getVersions = (pkg: string, ui: UIProvider): Promise => { return new Promise((resolve, reject) => { @@ -54,6 +56,12 @@ const install = (cmd: string, ui: UIProvider): Promise => { } export const set: Runner = async (args: Args, ui: UIProvider) => { + const localArgs = arg(helpArgs); + if (localArgs['--help']) { + ui.write(helpMessages['set']); + return; + } + if (args._.length < 2) { throw new Error('Please pass a key'); } diff --git a/src/cli/test.ts b/src/cli/test.ts index 5707de6..dfb0a19 100644 --- a/src/cli/test.ts +++ b/src/cli/test.ts @@ -1,6 +1,14 @@ import { Runner } from './Runner'; import { execSync } from 'child_process'; +import arg from 'arg'; +import { helpArgs, helpMessages } from './constants'; + +export const test: Runner = async (args, ui) => { + const localArgs = arg(helpArgs); + if (localArgs['--help']) { + ui.write(helpMessages['test']); + return; + } -export const test: Runner = async () => { execSync('npm test', { stdio: 'inherit' }); }; diff --git a/src/cli/verify.ts b/src/cli/verify.ts index bfcf4e6..3877252 100644 --- a/src/cli/verify.ts +++ b/src/cli/verify.ts @@ -7,6 +7,7 @@ import { argSpec, createNetworkProvider } from '../network/createNetworkProvider import { selectCompile } from './build'; import { sleep } from '../utils'; import arg from 'arg'; +import { helpArgs, helpMessages } from './constants'; type FuncCompilerSettings = { compiler: 'func'; @@ -166,7 +167,11 @@ async function lookupCodeHash(hash: Buffer, ui: UIProvider, retryCount: number = } export const verify: Runner = async (args: Args, ui: UIProvider, context: RunnerContext) => { - const localArgs = arg(argSpec); + const localArgs = arg({ ...argSpec, ...helpArgs }); + if (localArgs['--help']) { + ui.write(helpMessages['verify']); + return; + } const sel = await selectCompile(ui, localArgs);