0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

refactor(cli): add official connectors during init (#2132)

This commit is contained in:
Gao Sun 2022-10-12 17:53:38 +08:00 committed by GitHub
parent 27d3c2c00f
commit 926394030d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 52 deletions

View file

@ -1,13 +1,7 @@
import chalk from 'chalk';
import { CommandModule } from 'yargs'; import { CommandModule } from 'yargs';
import { oraPromise } from '../../utilities'; import { log } from '../../utilities';
import { import { addConnectors, addOfficialConnectors, inquireInstancePath } from './utils';
addConnectors,
fetchOfficialConnectorList,
inquireInstancePath,
normalizePackageName,
} from './utils';
const add: CommandModule<unknown, { packages: string[]; path?: string; official: boolean }> = { const add: CommandModule<unknown, { packages: string[]; path?: string; official: boolean }> = {
command: ['add [packages...]', 'a', 'install', 'i'], command: ['add [packages...]', 'a', 'install', 'i'],
@ -32,14 +26,13 @@ const add: CommandModule<unknown, { packages: string[]; path?: string; official:
handler: async ({ packages: packageNames, path, official }) => { handler: async ({ packages: packageNames, path, official }) => {
const instancePath = await inquireInstancePath(path); const instancePath = await inquireInstancePath(path);
const packages = official if (official) {
? await oraPromise(fetchOfficialConnectorList(), { await addOfficialConnectors(instancePath);
text: 'Fetch official connector list', }
prefixText: chalk.blue('[info]'),
})
: packageNames.map((name) => normalizePackageName(name));
await addConnectors(instancePath, packages); await addConnectors(instancePath, packageNames);
log.info('Restart your Logto instance to get the changes reflected.');
}, },
}; };

View file

@ -13,7 +13,7 @@ import tar from 'tar';
import { z } from 'zod'; import { z } from 'zod';
import { connectorDirectory } from '../../constants'; import { connectorDirectory } from '../../constants';
import { log } from '../../utilities'; import { log, oraPromise } from '../../utilities';
import { defaultPath } from '../install/utils'; import { defaultPath } from '../install/utils';
const coreDirectory = 'packages/core'; const coreDirectory = 'packages/core';
@ -96,38 +96,40 @@ export const addConnectors = async (instancePath: string, packageNames: string[]
log.info('Fetch connector metadata'); log.info('Fetch connector metadata');
const results = await Promise.all( const results = await Promise.all(
packageNames.map(async (packageName) => { packageNames
const run = async () => { .map((name) => normalizePackageName(name))
const { stdout } = await execPromise(`npm pack ${packageName} --json`, { cwd }); .map(async (packageName) => {
const result = npmPackResultGuard.parse(JSON.parse(stdout)); const run = async () => {
const { stdout } = await execPromise(`npm pack ${packageName} --json`, { cwd });
const result = npmPackResultGuard.parse(JSON.parse(stdout));
if (!result[0]) { if (!result[0]) {
throw new Error( throw new Error(
`Unable to execute ${chalk.green('npm pack')} on package ${chalk.green(packageName)}` `Unable to execute ${chalk.green('npm pack')} on package ${chalk.green(packageName)}`
); );
}
const { filename, name } = result[0];
const escapedFilename = filename.replace(/\//g, '-').replace(/@/g, '');
const tarPath = path.join(cwd, escapedFilename);
const packageDirectory = path.join(cwd, name.replace(/\//g, '-'));
await remove(packageDirectory);
await ensureDir(packageDirectory);
await tar.extract({ cwd: packageDirectory, file: tarPath, strip: 1 });
await unlink(tarPath);
log.succeed(`Added ${chalk.green(name)}`);
};
try {
await pRetry(run, { retries: 2 });
} catch (error: unknown) {
console.warn(`[${packageName}]`, error);
return packageName;
} }
})
const { filename, name } = result[0];
const escapedFilename = filename.replace(/\//g, '-').replace(/@/g, '');
const tarPath = path.join(cwd, escapedFilename);
const packageDirectory = path.join(cwd, name.replace(/\//g, '-'));
await remove(packageDirectory);
await ensureDir(packageDirectory);
await tar.extract({ cwd: packageDirectory, file: tarPath, strip: 1 });
await unlink(tarPath);
log.succeed(`Added ${chalk.green(name)}`);
};
try {
await pRetry(run, { retries: 2 });
} catch (error: unknown) {
console.warn(`[${packageName}]`, error);
return packageName;
}
})
); );
const errorPackages = results.filter(Boolean); const errorPackages = results.filter(Boolean);
@ -146,7 +148,7 @@ export const addConnectors = async (instancePath: string, packageNames: string[]
const officialConnectorPrefix = '@logto/connector-'; const officialConnectorPrefix = '@logto/connector-';
export const fetchOfficialConnectorList = async () => { const fetchOfficialConnectorList = async () => {
const { stdout } = await execPromise(`npm search ${officialConnectorPrefix} --json`); const { stdout } = await execPromise(`npm search ${officialConnectorPrefix} --json`);
const packages = z const packages = z
.object({ name: z.string() }) .object({ name: z.string() })
@ -160,3 +162,11 @@ export const fetchOfficialConnectorList = async () => {
) )
); );
}; };
export const addOfficialConnectors = async (instancePath: string) => {
const packages = await oraPromise(fetchOfficialConnectorList(), {
text: 'Fetch official connector list',
prefixText: chalk.blue('[info]'),
});
await addConnectors(instancePath, packages);
};

View file

@ -3,6 +3,7 @@ import { CommandModule } from 'yargs';
import { getDatabaseUrlFromConfig } from '../../database'; import { getDatabaseUrlFromConfig } from '../../database';
import { log } from '../../utilities'; import { log } from '../../utilities';
import { addOfficialConnectors } from '../connector/utils';
import { import {
validateNodeVersion, validateNodeVersion,
inquireInstancePath, inquireInstancePath,
@ -12,14 +13,16 @@ import {
createEnv, createEnv,
logFinale, logFinale,
decompress, decompress,
inquireOfficialConnectors,
} from './utils'; } from './utils';
export type InstallArgs = { export type InstallArgs = {
path?: string; path?: string;
skipSeed: boolean; skipSeed: boolean;
officialConnectors?: boolean;
}; };
const installLogto = async ({ path, skipSeed }: InstallArgs) => { const installLogto = async ({ path, skipSeed, officialConnectors }: InstallArgs) => {
validateNodeVersion(); validateNodeVersion();
// Get instance path // Get instance path
@ -34,7 +37,11 @@ const installLogto = async ({ path, skipSeed }: InstallArgs) => {
// Seed database // Seed database
if (skipSeed) { if (skipSeed) {
log.info(`You can use ${chalk.green('db seed')} command to seed database when ready.`); log.info(
`Skipped database seeding.\n\n' + ' You can use the ${chalk.green(
'db seed'
)} command to seed database when ready.\n`
);
} else { } else {
await seedDatabase(instancePath); await seedDatabase(instancePath);
} }
@ -42,11 +49,21 @@ const installLogto = async ({ path, skipSeed }: InstallArgs) => {
// Save to dot env // Save to dot env
await createEnv(instancePath, await getDatabaseUrlFromConfig()); await createEnv(instancePath, await getDatabaseUrlFromConfig());
// Add official connectors
if (await inquireOfficialConnectors(officialConnectors)) {
await addOfficialConnectors(instancePath);
} else {
log.info(
'Skipped adding official connectors.\n\n' +
` You can use the ${chalk.green('connector add')} command to add connectors at any time.\n`
);
}
// Finale // Finale
logFinale(instancePath); logFinale(instancePath);
}; };
const install: CommandModule<unknown, { path?: string; skipSeed: boolean }> = { const install: CommandModule<unknown, InstallArgs> = {
command: ['init', 'i', 'install'], command: ['init', 'i', 'install'],
describe: 'Download and run the latest Logto release', describe: 'Download and run the latest Logto release',
builder: (yargs) => builder: (yargs) =>
@ -62,9 +79,14 @@ const install: CommandModule<unknown, { path?: string; skipSeed: boolean }> = {
type: 'boolean', type: 'boolean',
default: false, default: false,
}, },
officialConnectors: {
alias: 'oc',
describe: 'Add official connectors after downloading Logto',
type: 'boolean',
},
}), }),
handler: async ({ path, skipSeed }) => { handler: async ({ path, skipSeed, officialConnectors }) => {
await installLogto({ path, skipSeed }); await installLogto({ path, skipSeed, officialConnectors });
}, },
}; };

View file

@ -152,3 +152,17 @@ export const logFinale = (instancePath: string) => {
`Use the command below to start Logto. Happy hacking!\n\n ${chalk.green(startCommand)}` `Use the command below to start Logto. Happy hacking!\n\n ${chalk.green(startCommand)}`
); );
}; };
export const inquireOfficialConnectors = async (initialAnswer?: boolean) => {
const { value } = await inquirer.prompt<{ value: boolean }>(
{
name: 'value',
message: 'Do you want to add official connectors?',
type: 'confirm',
default: true,
},
{ value: initialAnswer }
);
return value;
};