1import chalk from 'chalk';
2import spawn from 'cross-spawn';
3import githubUsername from 'github-username';
4import ora from 'ora';
5
6export type StepOptions = ora.Options;
7
8export async function newStep<Result>(
9  title: string,
10  action: (step: ora.Ora) => Promise<Result> | Result,
11  options: StepOptions = {}
12): Promise<Result> {
13  const disabled = process.env.CI || process.env.EXPO_DEBUG;
14  const step = ora({
15    text: chalk.bold(title),
16    isEnabled: !disabled,
17    stream: disabled ? process.stdout : process.stderr,
18    ...options,
19  });
20
21  step.start();
22
23  try {
24    return await action(step);
25  } catch (error) {
26    step.fail();
27    console.error(error);
28    process.exit(1);
29  }
30}
31
32/**
33 * Finds user's name by reading it from the git config.
34 */
35export async function findMyName(): Promise<string> {
36  try {
37    return spawn.sync('git', ['config', '--get', 'user.name']).stdout.toString().trim();
38  } catch {
39    return '';
40  }
41}
42
43/**
44 * Finds user's email by reading it from the git config.
45 */
46export async function findGitHubEmail(): Promise<string> {
47  try {
48    return spawn.sync('git', ['config', '--get', 'user.email']).stdout.toString().trim();
49  } catch {
50    return '';
51  }
52}
53
54/**
55 * Get the GitHub username from an email address if the email can be found in any commits on GitHub.
56 */
57export async function findGitHubProfileUrl(email: string): Promise<string> {
58  try {
59    const username = (await githubUsername(email)) ?? '';
60    return `https://github.com/${username}`;
61  } catch {
62    return '';
63  }
64}
65
66/**
67 * Guesses the repository URL based on the author profile URL and the package slug.
68 */
69export async function guessRepoUrl(authorUrl: string, slug: string) {
70  if (/^https?:\/\/github.com\/[^/]+/.test(authorUrl)) {
71    const normalizedSlug = slug.replace(/^@/, '').replace(/\//g, '-');
72    return `${authorUrl}/${normalizedSlug}`;
73  }
74  return '';
75}
76