From 880d07ebf758bffcd0f84ebd8aeeec93bcf7298e Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Wed, 5 Oct 2022 15:21:37 +0800 Subject: [PATCH] refactor(cli): add `database set-url` command --- packages/cli/src/commands/database/index.ts | 6 +-- packages/cli/src/commands/database/url.ts | 16 +++++++- packages/cli/src/config.ts | 45 +++++++++++++++++++++ packages/cli/src/utilities.ts | 30 -------------- 4 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 packages/cli/src/config.ts diff --git a/packages/cli/src/commands/database/index.ts b/packages/cli/src/commands/database/index.ts index 5622a095a..c81899e46 100644 --- a/packages/cli/src/commands/database/index.ts +++ b/packages/cli/src/commands/database/index.ts @@ -1,12 +1,12 @@ import { CommandModule } from 'yargs'; import { noop } from '../../utilities'; -import { getUrl } from './url'; +import { getUrl, setUrl } from './url'; const database: CommandModule = { - command: ['database ', 'db'], + command: ['database', 'db'], describe: 'Commands for Logto database', - builder: (yargs) => yargs.command(getUrl), + builder: (yargs) => yargs.command(getUrl).command(setUrl).strict(), handler: noop, }; diff --git a/packages/cli/src/commands/database/url.ts b/packages/cli/src/commands/database/url.ts index 5f35fd2fc..4d9751fa4 100644 --- a/packages/cli/src/commands/database/url.ts +++ b/packages/cli/src/commands/database/url.ts @@ -1,6 +1,6 @@ import { CommandModule } from 'yargs'; -import { getConfig } from '../../utilities'; +import { getConfig, patchConfig } from '../../config'; export const getUrl: CommandModule = { command: 'get-url', @@ -10,3 +10,17 @@ export const getUrl: CommandModule = { console.log(databaseUrl); }, }; + +export const setUrl: CommandModule, { url: string }> = { + command: 'set-url ', + describe: 'Set database URL and save to config file', + builder: (yargs) => + yargs.positional('url', { + describe: 'The database URL (DSN) to use, including database name', + type: 'string', + demandOption: true, + }), + handler: async (argv) => { + await patchConfig({ databaseUrl: String(argv.url) }); + }, +}; diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts new file mode 100644 index 000000000..e784a93ee --- /dev/null +++ b/packages/cli/src/config.ts @@ -0,0 +1,45 @@ +import { readFile, writeFile } from 'fs/promises'; +import os from 'os'; +import path from 'path'; + +import chalk from 'chalk'; +import findUp from 'find-up'; +// eslint-disable-next-line id-length +import z from 'zod'; + +import { log } from './utilities'; + +// Logto config +const logtoConfigFilename = '.logto.json'; +const getConfigPath = async () => + (await findUp(logtoConfigFilename)) ?? path.join(os.homedir(), logtoConfigFilename); + +const getConfigJson = async () => { + const configPath = await getConfigPath(); + + try { + const raw = await readFile(configPath, 'utf8'); + + // Prefer `unknown` over the original return type `any`, will guard later + // eslint-disable-next-line no-restricted-syntax + return JSON.parse(raw) as unknown; + } catch {} +}; + +const configGuard = z + .object({ + databaseUrl: z.string().optional(), + }) + .default({}); + +type LogtoConfig = z.infer; + +export const getConfig = async () => { + return configGuard.parse(await getConfigJson()); +}; + +export const patchConfig = async (config: LogtoConfig) => { + const configPath = await getConfigPath(); + await writeFile(configPath, JSON.stringify({ ...(await getConfig()), ...config }, undefined, 2)); + log.info(`Updated config in ${chalk.green(configPath)}`); +}; diff --git a/packages/cli/src/utilities.ts b/packages/cli/src/utilities.ts index 13d86abc4..aa8f47206 100644 --- a/packages/cli/src/utilities.ts +++ b/packages/cli/src/utilities.ts @@ -1,16 +1,10 @@ import { execSync } from 'child_process'; import { createWriteStream } from 'fs'; -import { readFile } from 'fs/promises'; -import os from 'os'; -import path from 'path'; import chalk from 'chalk'; -import findUp from 'find-up'; import got, { Progress } from 'got'; import { HttpsProxyAgent } from 'hpagent'; import ora from 'ora'; -// eslint-disable-next-line id-length -import z from 'zod'; export const safeExecSync = (command: string) => { try { @@ -78,27 +72,3 @@ export const downloadFile = async (url: string, destination: string) => { // Intended // eslint-disable-next-line @typescript-eslint/no-empty-function export const noop = () => {}; - -// Logto config -const logtoConfig = '.logto.json'; - -const getConfigJson = async () => { - const configPath = (await findUp(logtoConfig)) ?? path.join(os.homedir(), logtoConfig); - - try { - const raw = await readFile(configPath, 'utf8'); - - // Prefer `unknown` over the original return type `any`, will guard later - // eslint-disable-next-line no-restricted-syntax - return JSON.parse(raw) as unknown; - } catch {} -}; - -export const getConfig = async () => { - return z - .object({ - databaseUrl: z.string().optional(), - }) - .default({}) - .parse(await getConfigJson()); -};