【手把手帶你擼一個腳手架】第四步, 通過擼碼獲取項目信息

系列文章:

前面的章節(jié)中我們已經(jīng)能夠獲取到命令行中輸入的參數(shù), 也能通過 gayhub 開放 api 中獲取到項目模板信息, 這里我們開始把之前的功能連綴起來 _

2018-11-15-15-37-26

本節(jié)用到的工具較多, list 一哈:

首先展示一下目錄結(jié)構(gòu)代碼地址

2018-11-15-20-19-15

各個文件介紹

bin/learn.js

#!/usr/bin/env node
require('../');

仍然作為項目的引導(dǎo)文件, 直接引入項目根目錄下的 index.js

index.js

require('babel-register');
const babel = require('@babel/core');
const babelPresetLatestNode = require('babel-preset-latest-node');

babel.transform('code();', {
  presets: [[babelPresetLatestNode, {
    target: 'current',
  }]],
});

require('babel-polyfill');
require('./src');

根目錄下的 index 作為項目的入口文件, 它的職責(zé)主要是兼容 es6, 并導(dǎo)入項目主文件 src/index.js

src/index.js

// colors console.log 文本添加字體顏色, 美觀
import 'colors';

// 接收命令行參數(shù), 提供基礎(chǔ)信息提示功能
import commander from 'commander';

// 內(nèi)部模塊
import { existsSync } from 'fs';
import { resolve } from 'path';
import { version } from '../package.json';

commander.version(version)
  .parse(process.argv);

// 獲取命令行中傳入的第一個參數(shù)
const [todo = ''] = commander.args;

// 判斷如果 command 目錄下是否存在用戶輸入的命令對應(yīng)的文件
if (existsSync(resolve(__dirname, `command/${todo}.js`))) {
  require(`./command/${todo}.js`);
} else {
  console.log(
    `
      你輸入了未知指令, 小哥哥我已經(jīng)受不了掛了...
    `.red,
  );
  process.exit(-1);
}

這個是項目的主文件, 也是整個程序的總控. 正如注釋, 執(zhí)行命令前, 從這里檢測我們的命令目錄下是否已經(jīng)存在了用戶請求的命令, 避免了用戶誤操作程序報錯的風(fēng)險.

command/download.js

// 命令管理
import commander from 'commander';
// 命令行交互工具
import inquirer from 'inquirer';
// 命令行中顯示加載中
import ora from 'ora';
import Git from '../tools/git';

class Download {
  constructor() {
    this.git = new Git();
    this.commander = commander;
    this.inquirer = inquirer;
    this.getProList = ora('獲取項目列表...');
    this.getTagList = ora('獲取項目版本...');
    this.downLoad = ora('正在加速為您下載代碼...');
  }

  run() {
    this.commander
      .command('download')
      .description('從遠程下載代碼到本地...')
      .action(() => { this.download(); });

    this.commander.parse(process.argv);
  }

  async download() {
    let getProListLoad;
    let getTagListLoad;
    let repos;
    let version;
    try {
      getProListLoad = this.getProList.start();
      repos = await this.git.getProjectList();
      getProListLoad.succeed('獲取項目列表成功');
    } catch (error) {
      console.log(error);
      getProListLoad.fail('獲取項目列表失敗...');
      process.exit(-1);
    }
    if (repos.length === 0) {
      console.log('\n可以開發(fā)的項目數(shù)為 0, 肯定是配置錯啦~~\n'.red);
      process.exit(-1);
    }
    const choices = repos.map(({ name }) => name);
    const questions = [
      {
        type: 'list',
        name: 'repo',
        message: '請選擇你想要開發(fā)的項目類型',
        choices,
      },
    ];
    const { repo } = await this.inquirer.prompt(questions);
    // 獲取項目的版本, 這里默認選擇確定項目的最近一個版本
    try {
      getTagListLoad = this.getTagList.start();
      [{ name: version }] = await this.git.getProjectVersions(repo);
      getTagListLoad.succeed('獲取項目版本成功');
    } catch (error) {
      console.log(error);
      getTagListLoad.fail('獲取項目版本失敗...');
      process.exit(-1);
    }

    console.log(`您選擇的項目是${repo}, 即將下載版本${version}`);
  }
}
const D = new Download();
D.run();

command 目錄下存放的是我們整個項目中所有的命令文件, 不同的命令對應(yīng)不同的文件, 體現(xiàn)了單一職責(zé)的設(shè)計. download 命令用到了我們上一節(jié)中提到的兩個接口(即獲取項目列表和獲取版本號列表)有疑問的同學(xué)請回頭參考系列文章第三步 _.

tools/git.js

import request from './request';
import { orgName } from '../../config';

class Git {
  constructor() {
    this.orgName = orgName;
  }

  getProjectList() {
    return request(`/orgs/${this.orgName}/repos`);
  }

  getProjectVersions(repo) {
    return request(`/repos/${this.orgName}/${repo}/tags`);
  }

  getProjectUrl() {

  }

  downloadProject() {

  }
}

export default Git;

此文件是 git 相關(guān)的操作的文件, 由于腳手架的核心功能就是獲取項目的 github 地址, 并下載, 所以我的 Git 類規(guī)劃了以上幾個功能, 獲取項目列表 獲取項目版本號列表 獲取項目地址 下載項目, 雖然后兩個功能在這一節(jié)還用不到, 我也先留下了代碼樁

tools/request.js

import axios from 'axios';
import { baseURL } from '../../config';

const instance = axios.create({
  baseURL,
  timeout: 1e4,
});

// Add a request interceptor
instance.interceptors.request.use(config => config,
  error => Promise.reject(error));

// Add a response interceptor
instance.interceptors.response.use(response => response.data,
  error => Promise.reject(error));

export default instance;

這個文件僅僅是對 axios 做了一層簡單的封裝, 封裝的手法我還不是掌握的很好, 如果有精通的小伙伴歡迎評論區(qū)賜教.


2018-11-15-20-39-14

config/index.js

// github 接口基礎(chǔ)地址
export const baseURL = 'https://api.github.com';
// organization 名稱
export const orgName = 'learn-cli-organization';

作為整個項目的配置文件, 承擔(dān)了保存項目運行過程中需要的配置信息的功能.

介紹完幾個文件, 感到如釋重負. 如果有手懶的小伙伴, 可以直接 github clone 本階段代碼按照第一步的方法配置即可

ps: git clone https://github.com/luoquanquan/learn-cli.git
ps: git checkout 0.0.1
ps: 完成后要執(zhí)行 npm inpm link 的喲 _

驗證代碼

終于到了驗證的環(huán)節(jié). 小伙伴們, 自己寫完或者 git clone 完代碼以后可以打開終端啦, 484 有點小小的雞凍 _

2018-11-15-20-54-10

輸入 learn download

2018-11-15-20-53-05

出現(xiàn)上圖所示的項目名稱和版本號, 說明我們已經(jīng)通過代碼獲取 git 項目信息成功啦.

2018-11-15-20-57-01

下集預(yù)告: 到現(xiàn)在, 我們已經(jīng)能夠從 github 獲取到項目的名稱和版本號, 下一步會嘗試把項目 download 到本地用到了工具 download-git-repo, 熱愛動手的小伙伴已經(jīng)可以開始著手啦, 說不定下一步就是你來寫喲 ??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容