mirror of
https://github.com/appium/appium.git
synced 2026-10-19 14:32:18 +08:00
f01b6fb054
* chore(tsconfig): update dependency @tsconfig/node20 to v20.1.7 * fix: linter errors --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Mykola Mokhnach <mokhnach@gmail.com>
223 lines
5.6 KiB
TypeScript
223 lines
5.6 KiB
TypeScript
/**
|
|
* Scaffolding functions for CLI `init` command
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import {NAME_MKDOCS_YML, PIP_ENV_VARS, REQUIREMENTS_TXT_PATH} from './constants';
|
|
import * as YAML from 'yaml';
|
|
import {exec} from 'teen_process';
|
|
import {Simplify} from 'type-fest';
|
|
import {DocutilsError} from './error';
|
|
import {createScaffoldTask, ScaffoldTaskOptions} from './scaffold';
|
|
import type { ScaffoldTask } from './scaffold';
|
|
import {getLogger} from './logger';
|
|
import {MkDocsYml} from './model';
|
|
import {requirePython, stringifyYaml} from './fs';
|
|
|
|
/**
|
|
* Data for the base `mkdocs.yml` file
|
|
*/
|
|
const BASE_MKDOCS_YML: Readonly<MkDocsYml> = Object.freeze({
|
|
INHERIT: './node_modules/@appium/docutils/base-mkdocs.yml',
|
|
docs_dir: 'docs',
|
|
site_dir: 'site',
|
|
});
|
|
|
|
const log = getLogger('init');
|
|
const dryRunLog = getLogger('dry-run', log);
|
|
|
|
/**
|
|
* Function which scaffolds an `mkdocs.yml` file
|
|
*/
|
|
export const initMkDocs: ScaffoldTask<InitMkDocsOptions, MkDocsYml> = createScaffoldTask<InitMkDocsOptions, MkDocsYml>(
|
|
NAME_MKDOCS_YML,
|
|
BASE_MKDOCS_YML,
|
|
'MkDocs configuration',
|
|
{
|
|
deserialize: YAML.parse,
|
|
serialize: stringifyYaml,
|
|
transform: (content, opts, pkg) => {
|
|
let siteName = opts.siteName ?? content.site_name;
|
|
if (!siteName) {
|
|
siteName = pkg.name ?? '(no name)';
|
|
if (siteName) {
|
|
log.info('Using site name from package.json: %s', siteName);
|
|
}
|
|
}
|
|
let repoUrl: string | undefined = opts.repoUrl ?? content.repo_url;
|
|
if (!repoUrl) {
|
|
repoUrl = pkg.repository?.url;
|
|
if (repoUrl) {
|
|
log.info('Using repo URL from package.json: %s', repoUrl);
|
|
}
|
|
}
|
|
let repoName = opts.repoName ?? content.repo_name;
|
|
if (repoUrl && !repoName) {
|
|
let {pathname} = new URL(repoUrl);
|
|
pathname = pathname.slice(1);
|
|
const pathparts = pathname.split('/');
|
|
const owner = pathparts[0];
|
|
let repo = pathparts[1];
|
|
repo = repo.replace(/\.git$/, '');
|
|
repoName = [owner, repo].join('/');
|
|
if (repoName) {
|
|
log.info('Using repo name from package.json: %s', repoName);
|
|
}
|
|
}
|
|
let siteDescription = opts.siteDescription ?? content.site_description;
|
|
if (!siteDescription) {
|
|
siteDescription = pkg.description;
|
|
if (siteDescription) {
|
|
log.info('Using site description URL from package.json: %s', siteDescription);
|
|
}
|
|
}
|
|
return {
|
|
...content,
|
|
site_name: siteName,
|
|
repo_url: repoUrl,
|
|
repo_name: repoName,
|
|
site_description: siteDescription,
|
|
};
|
|
},
|
|
},
|
|
);
|
|
|
|
/**
|
|
* Installs Python dependencies
|
|
* @param opts Options
|
|
*/
|
|
export async function initPython({
|
|
pythonPath,
|
|
dryRun = false,
|
|
upgrade = false,
|
|
}: InitPythonOptions = {}): Promise<void> {
|
|
const foundPythonPath = await requirePython(pythonPath);
|
|
|
|
const args = ['-m', 'pip', 'install', '-r', REQUIREMENTS_TXT_PATH];
|
|
if (upgrade) {
|
|
args.push('--upgrade');
|
|
}
|
|
if (dryRun) {
|
|
dryRunLog.info(
|
|
'Would execute command: %s %s (environment variables: %s)',
|
|
foundPythonPath,
|
|
args.join(' '),
|
|
PIP_ENV_VARS,
|
|
);
|
|
} else {
|
|
log.debug('Executing command: %s %s (environment variables: %s)',
|
|
foundPythonPath,
|
|
args.join(' '),
|
|
PIP_ENV_VARS,
|
|
);
|
|
log.info('Installing Python dependencies...');
|
|
try {
|
|
const result = await exec(foundPythonPath, args, {env: PIP_ENV_VARS, shell: true});
|
|
const {code, stdout} = result;
|
|
if (code !== 0) {
|
|
throw new DocutilsError(`Could not install Python dependencies. Reason: ${stdout}`);
|
|
}
|
|
} catch (err) {
|
|
throw new DocutilsError(
|
|
`Could not install Python dependencies. Reason: ${(err as Error).message}`,
|
|
);
|
|
}
|
|
}
|
|
log.success('Successfully installed Python dependencies');
|
|
}
|
|
|
|
/**
|
|
* Options for {@linkcode initMkDocs}
|
|
*/
|
|
export interface InitMkDocsOptions extends ScaffoldTaskOptions {
|
|
copyright?: string;
|
|
repoName?: string;
|
|
repoUrl?: string;
|
|
siteDescription?: string;
|
|
siteName?: string;
|
|
}
|
|
|
|
/**
|
|
* Main handler for `init` command.
|
|
*
|
|
* This runs tasks in serial; it _could_ run in parallel, but it has deleterious effects upon
|
|
* console output which would need mitigation.
|
|
*/
|
|
export async function init({
|
|
python,
|
|
packageJson: packageJsonPath,
|
|
overwrite,
|
|
mkdocs,
|
|
mkdocsYml: mkdocsYmlPath,
|
|
siteName,
|
|
repoName,
|
|
repoUrl,
|
|
copyright,
|
|
dryRun,
|
|
cwd,
|
|
pythonPath,
|
|
upgrade,
|
|
}: InitOptions = {}): Promise<void> {
|
|
if (python) {
|
|
await initPython({pythonPath, dryRun, upgrade});
|
|
}
|
|
|
|
if (mkdocs && !upgrade) {
|
|
await initMkDocs({
|
|
dest: mkdocsYmlPath,
|
|
cwd,
|
|
siteName,
|
|
repoUrl,
|
|
repoName,
|
|
copyright,
|
|
packageJson: packageJsonPath,
|
|
overwrite,
|
|
dryRun,
|
|
});
|
|
}
|
|
}
|
|
|
|
export interface InitPythonOptions extends ScaffoldTaskOptions {
|
|
/**
|
|
* Path to `python` (v3.x) executable
|
|
*/
|
|
pythonPath?: string;
|
|
|
|
/**
|
|
* If true, upgrade only
|
|
*/
|
|
upgrade?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Options for `init` command handler
|
|
*
|
|
* The props of the various "path" options are rewritten as `dest` for the scaffold tasks functions.
|
|
*/
|
|
export type InitOptions = Simplify<
|
|
Omit<InitPythonOptions & InitMkDocsOptions, 'dest'> & {
|
|
/**
|
|
* If `true` will install Python deps
|
|
*/
|
|
python?: boolean;
|
|
/**
|
|
* If `true` will initialize a `mkdocs.yml` file
|
|
*/
|
|
mkdocs?: boolean;
|
|
/**
|
|
* Path to existing `package.json` file
|
|
*/
|
|
packageJson?: string;
|
|
/**
|
|
* Path to new or existing `mkdocs.yml` file
|
|
*/
|
|
mkdocsYml?: string;
|
|
|
|
/**
|
|
* If `true`, upgrade only
|
|
*/
|
|
upgrade?: boolean;
|
|
}
|
|
>;
|