0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(cli): database config command

This commit is contained in:
Gao Sun 2022-10-05 02:30:37 +08:00
parent f05691b431
commit 0eb306a61c
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
7 changed files with 92 additions and 27 deletions

View file

@ -35,13 +35,15 @@
}, },
"dependencies": { "dependencies": {
"chalk": "^4.1.2", "chalk": "^4.1.2",
"find-up": "^5.0.0",
"got": "^11.8.2", "got": "^11.8.2",
"hpagent": "^1.0.0", "hpagent": "^1.0.0",
"inquirer": "^8.2.2", "inquirer": "^8.2.2",
"ora": "^5.0.0", "ora": "^5.0.0",
"semver": "^7.3.7", "semver": "^7.3.7",
"tar": "^6.1.11", "tar": "^6.1.11",
"yargs": "^17.6.0" "yargs": "^17.6.0",
"zod": "^3.18.0"
}, },
"devDependencies": { "devDependencies": {
"@silverhand/eslint-config": "1.0.0", "@silverhand/eslint-config": "1.0.0",

View file

@ -0,0 +1,13 @@
import { CommandModule } from 'yargs';
import { noop } from '../../utilities';
import { getUrl } from './url';
const database: CommandModule = {
command: ['database <command>', 'db'],
describe: 'Commands for Logto database',
builder: (yargs) => yargs.command(getUrl),
handler: noop,
};
export default database;

View file

@ -0,0 +1,12 @@
import { CommandModule } from 'yargs';
import { getConfig } from '../../utilities';
export const getUrl: CommandModule = {
command: 'get-url',
describe: 'Get database URL in Logto config file',
handler: async () => {
const { databaseUrl } = await getConfig();
console.log(databaseUrl);
},
};

View file

@ -9,6 +9,7 @@ import inquirer from 'inquirer';
import ora from 'ora'; import ora from 'ora';
import * as semver from 'semver'; import * as semver from 'semver';
import tar from 'tar'; import tar from 'tar';
import { CommandModule } from 'yargs';
import { downloadFile, log, safeExecSync } from '../utilities'; import { downloadFile, log, safeExecSync } from '../utilities';
@ -102,7 +103,7 @@ const decompress = async (toPath: string, tarPath: string) => {
decompressSpinner.succeed(); decompressSpinner.succeed();
}; };
const install = async ({ path: pathArgument = defaultPath, silent = false }: InstallArgs) => { const installLogto = async ({ path: pathArgument = defaultPath, silent = false }: InstallArgs) => {
validateNodeVersion(); validateNodeVersion();
const instancePath = (!silent && (await getInstancePath())) || pathArgument; const instancePath = (!silent && (await getInstancePath())) || pathArgument;
@ -122,4 +123,25 @@ const install = async ({ path: pathArgument = defaultPath, silent = false }: Ins
); );
}; };
const install: CommandModule<Record<string, unknown>, { path?: string; silent?: boolean }> = {
command: ['init', 'i', 'install'],
describe: 'Download and run the latest Logto release',
builder: (yargs) =>
yargs.options({
path: {
alias: 'p',
describe: 'Path of Logto, must be a non-existing path',
type: 'string',
},
silent: {
alias: 's',
describe: 'Entering non-interactive mode',
type: 'boolean',
},
}),
handler: async ({ path, silent }) => {
await installLogto({ path, silent });
},
};
export default install; export default install;

View file

@ -1,28 +1,12 @@
import yargs from 'yargs'; import yargs from 'yargs';
import { hideBin } from 'yargs/helpers'; import { hideBin } from 'yargs/helpers';
import database from './commands/database';
import install from './commands/install'; import install from './commands/install';
void yargs(hideBin(process.argv)) void yargs(hideBin(process.argv))
.command( .command(install)
['init', 'i', 'install'], .command(database)
'Download and run the latest Logto release',
{
path: {
alias: 'p',
describe: 'Path of Logto, must be a non-existing path',
type: 'string',
},
silent: {
alias: 's',
describe: 'Entering non-interactive mode',
type: 'boolean',
},
},
async ({ path, silent }) => {
await install({ path, silent });
}
)
.demandCommand(1) .demandCommand(1)
.showHelpOnFail(true) .showHelpOnFail(true)
.strict() .strict()

View file

@ -1,10 +1,16 @@
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import { createWriteStream } from 'fs'; import { createWriteStream } from 'fs';
import { readFile } from 'fs/promises';
import os from 'os';
import path from 'path';
import chalk from 'chalk'; import chalk from 'chalk';
import findUp from 'find-up';
import got, { Progress } from 'got'; import got, { Progress } from 'got';
import { HttpsProxyAgent } from 'hpagent'; import { HttpsProxyAgent } from 'hpagent';
import ora from 'ora'; import ora from 'ora';
// eslint-disable-next-line id-length
import z from 'zod';
export const safeExecSync = (command: string) => { export const safeExecSync = (command: string) => {
try { try {
@ -68,3 +74,31 @@ 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());
};

View file

@ -30,6 +30,7 @@ importers:
'@types/yargs': ^17.0.13 '@types/yargs': ^17.0.13
chalk: ^4.1.2 chalk: ^4.1.2
eslint: ^8.21.0 eslint: ^8.21.0
find-up: ^5.0.0
got: ^11.8.2 got: ^11.8.2
hpagent: ^1.0.0 hpagent: ^1.0.0
inquirer: ^8.2.2 inquirer: ^8.2.2
@ -42,8 +43,10 @@ importers:
ts-node: ^10.9.1 ts-node: ^10.9.1
typescript: ^4.7.4 typescript: ^4.7.4
yargs: ^17.6.0 yargs: ^17.6.0
zod: ^3.18.0
dependencies: dependencies:
chalk: 4.1.2 chalk: 4.1.2
find-up: 5.0.0
got: 11.8.3 got: 11.8.3
hpagent: 1.0.0 hpagent: 1.0.0
inquirer: 8.2.2 inquirer: 8.2.2
@ -51,6 +54,7 @@ importers:
semver: 7.3.7 semver: 7.3.7
tar: 6.1.11 tar: 6.1.11
yargs: 17.6.0 yargs: 17.6.0
zod: 3.18.0
devDependencies: devDependencies:
'@silverhand/eslint-config': 1.0.0_swk2g7ygmfleszo5c33j4vooni '@silverhand/eslint-config': 1.0.0_swk2g7ygmfleszo5c33j4vooni
'@silverhand/ts-config': 1.0.0_typescript@4.7.4 '@silverhand/ts-config': 1.0.0_typescript@4.7.4
@ -7493,7 +7497,6 @@ packages:
dependencies: dependencies:
locate-path: 6.0.0 locate-path: 6.0.0
path-exists: 4.0.0 path-exists: 4.0.0
dev: true
/flat-cache/3.0.4: /flat-cache/3.0.4:
resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
@ -10290,7 +10293,6 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
p-locate: 5.0.0 p-locate: 5.0.0
dev: true
/lodash._reinterpolate/3.0.0: /lodash._reinterpolate/3.0.0:
resolution: {integrity: sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=} resolution: {integrity: sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=}
@ -11920,7 +11922,6 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
yocto-queue: 0.1.0 yocto-queue: 0.1.0
dev: true
/p-locate/2.0.0: /p-locate/2.0.0:
resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==}
@ -11941,7 +11942,6 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
p-limit: 3.1.0 p-limit: 3.1.0
dev: true
/p-map-series/2.1.0: /p-map-series/2.1.0:
resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==} resolution: {integrity: sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==}
@ -12205,7 +12205,6 @@ packages:
/path-exists/4.0.0: /path-exists/4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true
/path-is-absolute/1.0.1: /path-is-absolute/1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
@ -15764,7 +15763,6 @@ packages:
/yocto-queue/0.1.0: /yocto-queue/0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true
/zod/3.18.0: /zod/3.18.0:
resolution: {integrity: sha512-gwTm8RfUCe8l9rDwN5r2A17DkAa8Ez4Yl4yXqc5VqeGaXaJahzYYXbTwvhroZi0SNBqTwh/bKm2N0mpCzuw4bA==} resolution: {integrity: sha512-gwTm8RfUCe8l9rDwN5r2A17DkAa8Ez4Yl4yXqc5VqeGaXaJahzYYXbTwvhroZi0SNBqTwh/bKm2N0mpCzuw4bA==}