用户信息诊断

记录错误情况,和用户当前环境后上报

参考:feflow/utils.ts at readsource · FunnyLiu/feflow

其中列举了各种比较好的实现,比如收集用户信息、操作系统信息、项目信息等等

import os from 'os';
import path from 'path';
import fs from 'fs';
import objectFactory from './objectFactory';
import { execSync } from 'child_process';

const platform = os.platform();
const isWin = platform === 'win32';
const isMac = platform === 'darwin';
const cwd = process.cwd();

export const httpRegex = /^https?\:\/\/(?:[^\/]+)\/([^\/]+)\/([^\/.]+)(?:\.git)?/;
export const sshRegex = /^git@(?:[^\:]+)\:([^\/]+)\/([^\/\.]+)(?:\.git)?/;

const exec = (command: string) => {
  let result = '';
  try {
    result = execSync(command)
      .toString()
      .replace(/\n/, '');
  } catch (err) {}
  return result;
};

export const getGitStatus = (): boolean => {
  const hasGitCommand = exec('which git');
  const hasGitDir = fs.existsSync(path.join(cwd, '.git'));
  return hasGitCommand && hasGitDir;
};

const isGitAvailable = getGitStatus();

const getUserNameFromHostName = () => {
  const hostname = os.hostname();
  const [upperUserName, ...device] = hostname.split('-');
  return upperUserName.toLowerCase();
};

const getUserNameFromLinux = () => {
  const nameFromLinux = exec('whoami');
  if (nameFromLinux === 'root') {
    return '';
  }

  return nameFromLinux;
};

const getUserNameFromGit = () => {
  if (!isGitAvailable) {
    return '';
  }
  const nameFromLinux = exec('git config user.name');

  return nameFromLinux;
};

export const getUserName = () => {
  // mac/window
  if (isMac || isWin) {
    return getUserNameFromHostName() || getUserNameFromGit();
  }
  return getUserNameFromLinux() || getUserNameFromGit() || getUserNameFromHostName();
};

export const getProjectByPackage = () => {
  let project = '';
  const pkgPath = path.resolve(process.cwd(), './package.json');
  if (fs.existsSync(pkgPath)) {
    project = require(pkgPath).name;
  }
  return project;
};

export const getProjectByGit = (url?: string) => {
  let project = '';
  const gitRemoteUrl = url || exec('git remote get-url origin');
  let urlRegex: RegExp;

  if (httpRegex.test(gitRemoteUrl)) {
    urlRegex = httpRegex;
  } else if (sshRegex.test(gitRemoteUrl)) {
    urlRegex = sshRegex;
  }
  if (!urlRegex) return '';

  const [_, group, path] = urlRegex.exec(gitRemoteUrl) || [];
  project = group ? `${group}/${path}` : '';

  return project;
};

export const getSystemInfo = () => {
  const systemDetailInfo = objectFactory
    .create()
    .load('hostname', os.hostname())
    .load('type', os.type())
    .load('platform', os.platform())
    .load('arch', os.arch())
    .load('release', os.release())
    .done();
  return JSON.stringify(systemDetailInfo);
};

export const getProject = (ctx, local?: boolean): string => {
  const pkgConfig: any = ctx.pkgConfig || {};
  let project = '';
  if (pkgConfig.name && !local) {
    // feflow context
    project = pkgConfig.name;
  } else {
    try {
      // if not, read project name from project's package.json or git
      project = getProjectByPackage();
      if (!project && isGitAvailable) {
        project = getProjectByGit();
      }
    } catch (error) {}
  }

  return project;
};