체인의정석

컨트렉트 배포/운영용 프로그램 만들기 여러개의 파일 cmd에서 하나로 체크해서 넘기기 - 구현 (inquirer , oclif) 본문

개발/backend

컨트렉트 배포/운영용 프로그램 만들기 여러개의 파일 cmd에서 하나로 체크해서 넘기기 - 구현 (inquirer , oclif)

체인의정석 2022. 4. 29. 17:10
728x90
반응형

https://www.youtube.com/channel/UCHsRy47P2KlE749oAAjb0Yg

 

체인의정석

약력 현) 블록체인 개발자 前 블록워터 테크놀로지, 스마트컨트렉트 개발자 前 위데이터랩(주) 기획,마케팅 팀장 , 블록체인팀 선임연구원 홍익대학교 경영학 전공, 컴공 부전공 서강대학교 정

www.youtube.com

inquirer를 typescript에서 활용하기 위하여 조사한 사항은 다음과 같다.

 

1. 먼저 npm에서 소개된 깃허브 예제들

https://github.com/SBoudrias/Inquirer.js/tree/master/packages/inquirer/examples

 

GitHub - SBoudrias/Inquirer.js: A collection of common interactive command line user interfaces.

A collection of common interactive command line user interfaces. - GitHub - SBoudrias/Inquirer.js: A collection of common interactive command line user interfaces.

github.com

2.types 패키지

https://www.npmjs.com/package/@types/inquirer

 

@types/inquirer

TypeScript definitions for inquirer. Latest version: 8.2.1, last published: a month ago. Start using @types/inquirer in your project by running `npm i @types/inquirer`. There are 979 other projects in the npm registry using @types/inquirer.

www.npmjs.com

3. 온라인 예제

https://github.com/SBoudrias/Inquirer.js/issues/701

 

How do I work with typescript? · Issue #701 · SBoudrias/Inquirer.js

I created this simple cli app just to test out reactive interface of inquirer with typescript. I was able to run the module with typescript without reactive interface and it works fine. However, I&...

github.com

위 3개를 살펴보면서 코드를 가져와서 굴려봤는데 잘 되지 않았다.

 

결국 타입스크립트 환경에서의 inquirer를 사용하는 방법을 다시 찾아보게 되었다.

https://oclif.io/docs/prompting

 

oclif: The Open CLI Framework · Create command line tools your users love

Create command line tools your users love

oclif.io

그 결과 oclif/core라는 것을 알게 되었다.

 

https://www.christiandimas.com/build-interactive-cli-using-typescript/

 

Build an Interactive CLI Using TypeScript

Quickly build Interactive CLI using TypeScript, OCLIF, and Inquirer

www.christiandimas.com

 

여기도 좋은 예제인데 oclif와 enquirer를 동시에 사용하고 있었다. 위 2 예제를 통해서 나도 컨트렉트 배포 환경을 체인별로 다양하게 만들어서 배포 프로세스를 잘 만들어봐야겠다.

 

자료가 생각보다 많지는 않았는데 찾아보니 두 프로그램은 정말 다양한 서비스에서 사용되고 있었다. enquirer가 기존 툴이고 oclif는 상대적으로 덜 중요한거 같지만 세일즈포스에서 만든만큼 신뢰는 간다.

 

그럼 먼저 예제를 가져와서 한번 돌려보기 위해서는 npm 부터 찾아봐야겠다.

https://www.npmjs.com/package/@oclif/core

 

@oclif/core

base library for oclif CLIs. Latest version: 1.7.0, last published: 14 days ago. Start using @oclif/core in your project by running `npm i @oclif/core`. There are 340 other projects in the npm registry using @oclif/core.

www.npmjs.com

 

보니 타입스크립트가 기본값이다. 

npm i @oclif/core --save

https://oclif.io/docs/introduction

 

oclif: The Open CLI Framework · Create command line tools your users love

Create command line tools your users love

oclif.io

위의 빠르게 시작하기를 보면

$ npx oclif generate mynewcli
? npm package name (mynewcli): mynewcli
$ cd mynewcli
$ ./bin/dev hello world
hello world! (./src/commands/hello/world.ts)

이런식으로 몇가지 해야할 요소들이 있다.

% npx oclif generate deploy_cli   

     _-----_     
    |       |    ╭──────────────────────────╮
    |--(o)--|    │  Time to build an oclif  │
   `---------´   │    CLI! Version: 3.0.1   │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

'/...../deploy_cli'에 복제합니다...
? npm package name deploy_cli
? command bin name the CLI will export deploy_cli
? description oclif example Hello World CLI

 

다음으로 명령어를 통해서 디렉토리를 하나 만들어 주었다. 그러나 설치에 에러가 났다.

 

https://oclif.io/docs/features

 

oclif: The Open CLI Framework · Create command line tools your users love

Create command line tools your users love

oclif.io

 

다시 살펴보니 ts-node를 사용해서 실행이 가능했다. deploy_cli는 지우고.

import {Command, CliUx} from '@oclif/core'
console.log("here")

export class MyCommand extends Command {
  async run() {
    // just prompt for input
    const name = await CliUx.ux.prompt('What is your name?')

    // mask input after enter is pressed
    const secondFactor = await CliUx.ux.prompt('What is your two-factor token?', {type: 'mask'})

    // hide input while typing
    const password = await CliUx.ux.prompt('What is your password?', {type: 'hide'})

    this.log(`You entered: ${name}, ${secondFactor}, ${password}`)
  }
}

MyCommand.run()

 

이렇게 해주고

lambda256@ethan scripts % ts-node deployBridgeAndCustody.ts
here
What is your name?: ethan
What is your two-factor token?: ***
What is your password?: ***
You entered: ethan, 123, 123

이런 결과값을 받았다.

 

커멘트 창에서는 그럼 ts-node로 실행하는게 더 깔끔할것 같다.

 

이제 여기에다가 inquirer를 달고 배포함수를 달면 원하는 대로 나올것 같다.

 

하지만 에러가 발생하여 문의해 보니 , inquirer는 노드 버전에 따라서 에러가 나기도 한다고 한다.

노드 14버전으로 한번 해보라고 하여 노드를 14버전으로 바꿨다.

 

nvm을 사용하였는데 맥북OS를 회사 보안프로그램 업데이트시 업그레이드 했더니 다시 설치를 해야했다. 해당 내용은 아래 블로그 글에 다시 정리해두었다.

 

그리고 예제대로 하면 에러가 나와서 아래와 같이 약간 수정하였다.

 

import {Command, Flags} from '@oclif/core'

console.log("here")

export class MyCommand extends Command {
  static flags = {
    stage: Flags.string({options: ['development', 'staging', 'production']})
  }

  async run() {
    const {flags} = await this.parse(MyCommand)
    let stage = flags.stage
    if (!stage) {
      let responses: any = await inquirer.prompt([{
        name: 'stage',
        message: 'select a stage',
        type: 'list',
        choices: [{name: 'development'}, {name: 'staging'}, {name: 'production'}],
      }])
      stage = responses.stage
    }
    this.log(`the stage is: ${stage}`)
  }
}

MyCommand.run()

이렇게 하면 기본적인 동작이 가능하다.

하지만 나는 여러 함수를 단계적으로 선택 또는 입력해서 배포하고 선택하고 하는 과정을 반복해야 한다.

따라서 일단 기본 구조부터 작동하도록 만들었다.

import * as inquirer from 'inquirer'
import {Command, Flags} from '@oclif/core'

export class MyCommand extends Command {

  static flags = {
    process: Flags.string({options: ['testFunction', 'testFunction2']})
  }

  async run() {
    const {flags} = await this.parse(MyCommand);
    let process = flags.process
    if (!process) {
      let responses: any = await inquirer.prompt([{
        name: 'process',
        message: 'select a process',
        type: 'list',
        choices: [{name: 'testFunction'}, {name: 'testFunction2'}],
      }])
      process = responses.process
      console.log(process)
        if (process == 'testFunction') {
          console.log('this is testFunction')
          console.log("start")
          let result = testFunction(1,2);
          console.log("testFunction end with", result)
          await this.runLev2(result);
        } else if (process == 'testFunction2') {
          let result = testFunction2(1,2);
          console.log("testFunction end with", result)
          await this.runLev2(result);
        }
      }
    }

    async runLev2(input:number) {
      const {flags} = await this.parse(MyCommand);
      let process2 = flags.process
      if (!process2) {
        let responses: any = await inquirer.prompt([{
          name: 'process',
          message: 'select a process',
          type: 'list',
          choices: [{name: 'testFunctionNext'}, {name: 'testFunction2Next'}],
        }])
        process2 = responses.process
        console.log(process2)
          if (process2 == 'testFunctionNext') {
            console.log('this is testFunctionNext')
            let result = testFunction(input,2);
            console.log("testFunctionNext end with", result)
          } else if (process2 == 'testFunction2Next') {
            console.log('this is testFunction2Next')
            let result = testFunction2(input,2);
            console.log("testFunction2Next end with", result)
          }
        }
      }
}

MyCommand.run()

const testFunction = (a:number,b:number) => {
  return a+b;
}

const testFunction2 = (a:number,b:number) => {
  return 2*(a+b);
}

이렇게되면 결과는 다음과 같이 나온다.

? select a process testFunction
testFunction
this is testFunction
start
testFunction end with 3
? select a process testFunction2Next
testFunction2Next
this is testFunction2Next
testFunction2Next end with 10

다른 케이스도 테스트 해보겠다.

? select a process testFunction
testFunction
this is testFunction
start
testFunction end with 3
? select a process testFunctionNext
testFunctionNext
this is testFunctionNext
testFunctionNext end with 5

잘 작동한다.

 

이제 여기다가 블록체인 배포 프로세스를 각가 파일로 만들고 실행시키던걸 함수앞에 export를 붙여서 모듈화를 시키고 명령어 창에서 내리면 자동화 + 체크하며 배포하는 배포 프로세스가 완성되게 될거 같다.

728x90
반응형
Comments