diff --git a/src/commands/config.ts b/src/commands/config.ts index 41691692..f4563bca 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -1,5 +1,37 @@ -import {config as configServices} from '../services/config/config.services'; +import {red} from 'kleur'; +import {logHelpConfigApply} from '../help/config.apply.help'; +import {logHelpConfig} from '../help/config.help'; +import {logHelpConfigInit} from '../help/config.init.help'; +import {applyConfig} from '../services/config/apply.services'; +import {init} from '../services/config/init.services'; export const config = async (args?: string[]) => { - await configServices(args); + const [subCommand] = args ?? []; + + switch (subCommand) { + case 'apply': + await applyConfig(args); + break; + case 'init': + await init(args); + break; + default: + console.log(red('Unknown subcommand.')); + logHelpConfig(args); + } +}; + +export const helpConfig = (args?: string[]) => { + const [subCommand] = args ?? []; + + switch (subCommand) { + case 'apply': + logHelpConfigApply(args); + break; + case 'init': + logHelpConfigInit(args); + break; + default: + logHelpConfig(args); + } }; diff --git a/src/commands/deprecated/init.ts b/src/commands/deprecated/init.ts new file mode 100644 index 00000000..70ee1248 --- /dev/null +++ b/src/commands/deprecated/init.ts @@ -0,0 +1,16 @@ +import {logHelpInit} from '../../help/deprecated/init.help'; +import {init as initServices} from '../../services/config/init.services'; + +/** + * @deprecated alias for backwards compatibility + */ +export const init = async (args?: string[]) => { + await initServices(args); +}; + +/** + * @deprecated + */ +export const helpInit = (args?: string[]) => { + logHelpInit(args); +}; diff --git a/src/commands/init.ts b/src/commands/init.ts deleted file mode 100644 index 5dd3b16b..00000000 --- a/src/commands/init.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {isNullish} from '@dfinity/utils'; -import {hasArgs} from '@junobuild/cli-tools'; -import {cyan} from 'kleur'; -import {getToken} from '../configs/cli.config'; -import {junoConfigExist} from '../configs/juno.config'; -import {login as consoleLogin} from '../services/auth/login.services'; -import {initConfigInteractive, initConfigNoneInteractive} from '../services/init.services'; -import {confirm, confirmAndExit} from '../utils/prompt.utils'; - -export const init = async (args?: string[]) => { - if (hasArgs({args, options: ['--minimal']})) { - await initWithPlaceholder(); - return; - } - - await initWithSatelliteId(args); -}; - -const initWithPlaceholder = async () => { - await assertOverwrite(); - - await initConfigNoneInteractive(); -}; - -const initWithSatelliteId = async (args?: string[]) => { - const token = await getToken(); - - if (isNullish(token)) { - const login = await confirm( - `Your terminal is not authenticated. Would you like to ${cyan('log in')} now?` - ); - - if (!login) { - return; - } - - await consoleLogin(args); - } - - await assertOverwrite(); - - await initConfigInteractive(); -}; - -const assertOverwrite = async () => { - if (await junoConfigExist()) { - await confirmAndExit( - 'Your existing configuration will be overwritten. Are you sure you want to continue?' - ); - } -}; diff --git a/src/constants/help.constants.ts b/src/constants/help.constants.ts index a90499a1..7b320fb2 100644 --- a/src/constants/help.constants.ts +++ b/src/constants/help.constants.ts @@ -1,13 +1,12 @@ import {magenta, yellow} from 'kleur'; export const CHANGES_DESCRIPTION = 'Review and apply changes submitted to your module.'; -export const CONFIG_DESCRIPTION = 'Apply configuration to satellite.'; export const HOSTING_DESCRIPTION = 'Deploy or clear the frontend code of your app on your satellite.'; +export const CONFIG_DESCRIPTION = 'Manage your project configuration'; export const EMULATOR_DESCRIPTION = 'Handle tasks related to the emulator like starting/stopping a local network.'; export const FUNCTIONS_DESCRIPTION = "Build and upgrade your satellite's serverless functions."; -export const INIT_DESCRIPTION = 'Set up your project.'; export const LOGIN_DESCRIPTION = 'Generate an authentication for use in non-interactive environments.'; export const LOGOUT_DESCRIPTION = @@ -23,6 +22,9 @@ export const WHOAMI_DESCRIPTION = 'Display your current profile, access key, and links to your satellite.'; export const RUN_DESCRIPTION = 'Run a custom script in the CLI context.'; +export const CONFIG_APPLY_DESCRIPTION = 'Apply configuration to satellite.'; +export const CONFIG_INIT_DESCRIPTION = 'Set up your project by creating a config file.'; + export const HOSTING_DEPLOY_DESCRIPTION = 'Deploy your app to your satellite.'; export const HOSTING_CLEAR_DESCRIPTION = 'Remove frontend files (JS, HTML, CSS, etc.) from your satellite.'; diff --git a/src/help/config.apply.help.ts b/src/help/config.apply.help.ts new file mode 100644 index 00000000..e451faff --- /dev/null +++ b/src/help/config.apply.help.ts @@ -0,0 +1,29 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {CONFIG_APPLY_DESCRIPTION, OPTIONS_ENV, OPTION_HELP} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('config')} ${magenta('apply')} ${yellow('[options]')} + +Options: + ${yellow('--force')} Overwrite configuration without checks. + ${OPTIONS_ENV} + ${OPTION_HELP}`; + +const doc = `${CONFIG_APPLY_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${CONFIG_APPLY_DESCRIPTION} + +${usage} +`; + +export const logHelpConfigApply = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/config.help.ts b/src/help/config.help.ts index fe770f49..bbf61118 100644 --- a/src/help/config.help.ts +++ b/src/help/config.help.ts @@ -1,14 +1,17 @@ -import {cyan, green, yellow} from 'kleur'; -import {CONFIG_DESCRIPTION, OPTIONS_ENV, OPTION_HELP} from '../constants/help.constants'; +import {cyan, green, magenta, yellow} from 'kleur'; +import { + CONFIG_APPLY_DESCRIPTION, + CONFIG_DESCRIPTION, + CONFIG_INIT_DESCRIPTION +} from '../constants/help.constants'; import {helpOutput} from './common.help'; import {TITLE} from './help'; -const usage = `Usage: ${green('juno')} ${cyan('config')} ${yellow('[options]')} +const usage = `Usage: ${green('juno')} ${cyan('config')} ${magenta('')} ${yellow('[options]')} -Options: - ${yellow('--force')} Overwrite configuration without checks. - ${OPTIONS_ENV} - ${OPTION_HELP}`; +Subcommands: + ${magenta('apply')} ${CONFIG_APPLY_DESCRIPTION} + ${magenta('init')} ${CONFIG_INIT_DESCRIPTION}`; const doc = `${CONFIG_DESCRIPTION} diff --git a/src/help/config.init.help.ts b/src/help/config.init.help.ts new file mode 100644 index 00000000..00f8d1da --- /dev/null +++ b/src/help/config.init.help.ts @@ -0,0 +1,29 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {CONFIG_INIT_DESCRIPTION, OPTION_HELP, OPTIONS_ENV} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('config')} ${magenta('init')} ${yellow('[options]')} + +Options: + ${yellow('--minimal')} Skip few prompts and generate a config file with a placeholder satellite ID. + ${OPTIONS_ENV} + ${OPTION_HELP}`; + +const doc = `${CONFIG_INIT_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${CONFIG_INIT_DESCRIPTION} + +${usage} +`; + +export const logHelpConfigInit = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/deprecated/init.help.ts b/src/help/deprecated/init.help.ts new file mode 100644 index 00000000..825af827 --- /dev/null +++ b/src/help/deprecated/init.help.ts @@ -0,0 +1,24 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {CONFIG_INIT_DESCRIPTION} from '../../constants/help.constants'; +import {helpOutput} from '../common.help'; +import {TITLE} from '../help'; + +const usage = `Alias for: ${green('juno')} ${cyan('config')} ${magenta('init')} ${yellow('[options]')}`; + +const doc = `${CONFIG_INIT_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${CONFIG_INIT_DESCRIPTION} + +${usage} +`; + +export const logHelpInit = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/help.ts b/src/help/help.ts index ee805374..8181e065 100644 --- a/src/help/help.ts +++ b/src/help/help.ts @@ -5,7 +5,6 @@ import { EMULATOR_DESCRIPTION, FUNCTIONS_DESCRIPTION, HOSTING_DESCRIPTION, - INIT_DESCRIPTION, LOGIN_DESCRIPTION, LOGOUT_DESCRIPTION, OPEN_DESCRIPTION, @@ -38,7 +37,6 @@ Commands: ${cyan('functions')} ${FUNCTIONS_DESCRIPTION} ${cyan('help')} Display help information. ${cyan('hosting')} ${HOSTING_DESCRIPTION} - ${cyan('init')} ${INIT_DESCRIPTION} ${cyan('login')} ${LOGIN_DESCRIPTION} ${cyan('logout')} ${LOGOUT_DESCRIPTION} ${cyan('open')} ${OPEN_DESCRIPTION} diff --git a/src/help/init.help.ts b/src/help/init.help.ts deleted file mode 100644 index 27fffa25..00000000 --- a/src/help/init.help.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {cyan, green, yellow} from 'kleur'; -import {INIT_DESCRIPTION, OPTION_HELP, OPTIONS_ENV} from '../constants/help.constants'; -import {helpOutput} from './common.help'; -import {TITLE} from './help'; - -const usage = `Usage: ${green('juno')} ${cyan('init')} ${yellow('[options]')} - -Options: - ${yellow('--minimal')} Skip few prompts and generate a config file with a placeholder satellite ID. - ${OPTIONS_ENV} - ${OPTION_HELP}`; - -const doc = `${INIT_DESCRIPTION} - -\`\`\` -${usage} -\`\`\` -`; - -const help = `${TITLE} - -${INIT_DESCRIPTION} - -${usage} -`; - -export const logHelpInit = (args?: string[]) => { - console.log(helpOutput(args) === 'doc' ? doc : help); -}; diff --git a/src/index.ts b/src/index.ts index 8ad02b98..b62b4399 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,14 +2,14 @@ import {hasArgs} from '@junobuild/cli-tools'; import {red} from 'kleur'; import {login, logout} from './commands/auth'; import {changes, helpChanges} from './commands/changes'; -import {config} from './commands/config'; +import {config, helpConfig} from './commands/config'; import {clear, helpClear} from './commands/deprecated/clear'; import {deploy, helpDeploy} from './commands/deprecated/deploy'; import {dev, helpDev} from './commands/deprecated/dev'; +import {helpInit, init} from './commands/deprecated/init'; import {emulator, helpEmulator} from './commands/emulator'; import {functions, helpFunctions} from './commands/functions'; import {helpHosting, hosting} from './commands/hosting'; -import {init} from './commands/init'; import {open} from './commands/open'; import {helpRun, run as runCmd} from './commands/run'; import {snapshot} from './commands/snapshot'; @@ -18,9 +18,7 @@ import {status} from './commands/status'; import {upgrade} from './commands/upgrade'; import {version as versionCommand} from './commands/version'; import {whoami} from './commands/whoami'; -import {logHelpConfig} from './help/config.help'; import {help} from './help/help'; -import {logHelpInit} from './help/init.help'; import {logHelpLogin} from './help/login.help'; import {logHelpLogout} from './help/logout.help'; import {logHelpOpen} from './help/open.help'; @@ -71,7 +69,7 @@ export const run = async () => { logHelpOpen(args); break; case 'config': - logHelpConfig(args); + helpConfig(args); break; case 'clear': helpClear(args); @@ -99,7 +97,7 @@ export const run = async () => { logHelpSnapshot(args); break; case 'init': - logHelpInit(args); + helpInit(args); break; case 'logout': logHelpLogout(args); diff --git a/src/services/assets/deploy.services.ts b/src/services/assets/deploy.services.ts index 139b8414..24e28636 100644 --- a/src/services/assets/deploy.services.ts +++ b/src/services/assets/deploy.services.ts @@ -2,11 +2,11 @@ import {isEmptyString} from '@dfinity/utils'; import {hasArgs, nextArg} from '@junobuild/cli-tools'; import {yellow} from 'kleur'; import {compare} from 'semver'; -import {init} from '../../commands/init'; import {noJunoConfig} from '../../configs/juno.config'; import {type DeployOptions} from '../../types/deploy'; import {clearProposalStagedAssets} from '../changes/changes.clear.services'; -import {config} from '../config/config.services'; +import {applyConfig} from '../config/apply.services'; +import {init} from '../config/init.services'; import {links} from '../links.services'; import {getSatelliteVersion} from '../version.services'; import {deployImmediate} from './_deploy/deploy.individual.services'; @@ -22,7 +22,7 @@ export const deploy = async (args?: string[]) => { const configOption = hasArgs({args, options: ['--config']}); if (configOption) { console.log(''); - await config(args); + await applyConfig(args); } await links(); diff --git a/src/services/config/config.services.ts b/src/services/config/apply.services.ts similarity index 99% rename from src/services/config/config.services.ts rename to src/services/config/apply.services.ts index f17da245..86512fff 100644 --- a/src/services/config/config.services.ts +++ b/src/services/config/apply.services.ts @@ -58,7 +58,7 @@ type SetConfigResults = [ type EditConfig = Omit; -export const config = async (args?: string[]) => { +export const applyConfig = async (args?: string[]) => { const {satellite, satelliteConfig} = await assertConfigAndLoadSatelliteContext(); const {satelliteId} = satellite; @@ -87,7 +87,7 @@ export const config = async (args?: string[]) => { } // Effectively update the configurations and collections of the Satellite - const results = await applyConfig({satellite, editConfig}); + const results = await executeSetConfigs({satellite, editConfig}); // Save the new hashes in the CLI state saveLastAppliedConfigHashes({ @@ -251,7 +251,7 @@ const loadCurrentConfig = async (params: { } }; -const applyConfig = async ({ +const executeSetConfigs = async ({ satellite, editConfig }: { diff --git a/src/services/init.services.ts b/src/services/config/init.services.ts similarity index 78% rename from src/services/init.services.ts rename to src/services/config/init.services.ts index f5368e20..347ac772 100644 --- a/src/services/init.services.ts +++ b/src/services/config/init.services.ts @@ -1,25 +1,70 @@ import {isNullish, nonNullish} from '@dfinity/utils'; -import {assertAnswerCtrlC} from '@junobuild/cli-tools'; +import {assertAnswerCtrlC, hasArgs} from '@junobuild/cli-tools'; import type {ConfigType, PartialConfigFile} from '@junobuild/config-loader'; import {cyan, yellow} from 'kleur'; import {unlink} from 'node:fs/promises'; import {basename} from 'node:path'; import prompts from 'prompts'; -import {getCliOrbiters, getCliSatellites} from '../configs/cli.config'; +import {getCliOrbiters, getCliSatellites, getToken} from '../../configs/cli.config'; import { detectJunoConfigType, + junoConfigExist, junoConfigFile, noJunoConfig, writeJunoConfig, writeJunoConfigPlaceholder -} from '../configs/juno.config'; -import type {CliOrbiterConfig, CliSatelliteConfig} from '../types/cli.config'; -import {type EmulatorConfigWithoutConsole} from '../types/emulator'; -import type {PackageManager} from '../types/pm'; -import {detectPackageManager} from '../utils/pm.utils'; -import {NEW_CMD_LINE} from '../utils/prompt.utils'; - -export const promptConfigType = async (): Promise => { +} from '../../configs/juno.config'; +import type {CliOrbiterConfig, CliSatelliteConfig} from '../../types/cli.config'; +import {type EmulatorConfigWithoutConsole} from '../../types/emulator'; +import type {PackageManager} from '../../types/pm'; +import {detectPackageManager} from '../../utils/pm.utils'; +import {confirm, confirmAndExit, NEW_CMD_LINE} from '../../utils/prompt.utils'; +import {login as consoleLogin} from '../auth/login.services'; + +export const init = async (args?: string[]) => { + if (hasArgs({args, options: ['--minimal']})) { + await initWithPlaceholder(); + return; + } + + await initWithSatelliteId(args); +}; + +const initWithPlaceholder = async () => { + await assertOverwrite(); + + await initConfigNoneInteractive(); +}; + +const initWithSatelliteId = async (args?: string[]) => { + const token = await getToken(); + + if (isNullish(token)) { + const login = await confirm( + `Your terminal is not authenticated. Would you like to ${cyan('log in')} now?` + ); + + if (!login) { + return; + } + + await consoleLogin(args); + } + + await assertOverwrite(); + + await initConfigInteractive(); +}; + +const assertOverwrite = async () => { + if (await junoConfigExist()) { + await confirmAndExit( + 'Your existing configuration will be overwritten. Are you sure you want to continue?' + ); + } +}; + +const promptConfigType = async (): Promise => { const {configType}: {configType: ConfigType} = await prompts({ type: 'select', name: 'configType', @@ -38,7 +83,7 @@ export const promptConfigType = async (): Promise => { return configType; }; -export type InitConfigParams = PartialConfigFile & {pm: PackageManager | undefined} & { +type InitConfigParams = PartialConfigFile & {pm: PackageManager | undefined} & { source: string; }; @@ -60,7 +105,7 @@ export const initConfigNoneInteractive = async ({ }); }; -export const initConfigInteractive = async () => { +const initConfigInteractive = async () => { const satelliteId = await initSatelliteConfig(); const orbiterId = await initOrbiterConfig(); diff --git a/src/services/emulator/_runner.services.ts b/src/services/emulator/_runner.services.ts index b2a9dca1..1f56ab9d 100644 --- a/src/services/emulator/_runner.services.ts +++ b/src/services/emulator/_runner.services.ts @@ -25,7 +25,7 @@ import { hasExistingContainer, isContainerRunning } from '../../utils/runner.utils'; -import {initConfigNoneInteractive} from '../init.services'; +import {initConfigNoneInteractive} from '../config/init.services'; import {createDeployTargetDir} from './_fs.services'; export const startContainer = async () => {