0.2.10 • Published 4 years ago

@stkevintan/parrot v0.2.10

Weekly downloads
12
License
MIT
Repository
-
Last release
4 years ago

Parrot

Highly customizable and type safe tool to fetch the swagger json from yapi and convert it into ts modules with nunjunks template.

NPM   GitHub top language   npm (scoped)   David

Installation

npm -D @stkevintan/parrot

Usage

// yapi.ts
import {Parrot} from '@stkevintan/parrot'

const {url, headers} from 'path/to/connect-config'

const tagMapper = (tag: string) => {
  switch(tag){
    case '用户': return 'user',
    case '权限': return 'auth',
    case '部门权限': return 'auth',
    default: return 'common'
  }
}

Parrot.fromHTTP(url, headers).then(parrot => parrot.convert({
  out: 'src/api.ts',
  tagMapper,
  templates: {
    // custom the header template
    header: require.resolve('./header.njk')
  },
  // only parse the response.data schema to interface 
  responseInterceptor: schema => {
    if (schema && schema.properties && schema.properties.data) {
      return schema.properties.data
    }
    return schema
  }
})).then((content) => {
  console.log('the content is generated with', content.split('\n').length, 'lines')
})

Then, you can exec this file by ts-node in bash:

ts-node -O '{"module":"commonjs"}' yapi

Finaly, the outfile src/api.ts will be generated, and you can use it as an api module like following:

//src/test.ts
import * as api from './api'

// get with params
api.user.getUsers({region: "cn"}).then(users => {
  console.log(users)
})

// post with json body
api.user.postUser({id: 1, name: 'kevin'}).then(ok => console.log(ok))

// post with formData, version 1
function uploadV1(file: File) {
  api.user.postAvatar({ avatar: file, desc: "xxx" }).then(ok => console.log(ok))
}

// post with formData, version 2
function uploadV2(file: File) {
  const form = new FormData()
  form.append("avatar", file)
  form.append("desc", "xxx")
  api.user.postAvatar(form)
}

Notice: all the api module and functions are type guaranteed. You can import the related interfaces or types as well

API Doc

Parrot

There are two ways to get a parrot instance:

import { Parrot } from '@stkevintan/parrot'

//Option one: (get the swagger content in some way)
const swagger = fs.readFileSync('swagger.json', { encoding: 'utf8' })
const parrot = new Parrot(swagger)

// Option two: (retrive the swagger content from remote url)
Parrot.fromHTTP(url, headers).then(parrot => { })

Method

writeSwagger(path: string, options?: Option): Promise<void>

type Option =  {
  stringify?: (value: any) => string
  encoding?: string | null
  mode?: string | number 
  flag?: string 
}

write the swagger json into file which path indicated the location of the file and stringify function can be customized. eg: write swagger content into yaml format:

import YAML from 'yamljs'
import { Parrot } from '@stkevintan/parrot'

Parrot.fromHTTP(url, headers)
  .then(parrot => {
    return parrot.writeSwagger('./swagger.yaml', { stringify: YAML.stringify.bind(YAML) })
  })
  .then(() => {
    console.log('done')
  })

convert(option: Option): Promise<string>

convert swagger to ts file. the Option interface's definition:

export type Part = 'header' | 'interface' | 'fn' | 'body'

export type InterfaceType = 'query' | 'path' | 'body' | 'formData' | 'response'

export type Method = 'get' | 'put' | 'patch' | 'post' | 'delete'

export interface Option {
  tagMapper?: (tag: string) => string | undefined
  tplRoot?: string
  templates?: {
    [key in Part]?: string
  }
  apiNameMapper?: (path: string, method: Method) => string
  interfaceNameMapper?: (apiName: string, type: InterfaceType) => string
  responseInterceptor?: (schema: Schema) => Schema
  out?: string
  skipBodyOfGet?: boolean
}
optiondescriptiondefault
tagMappera function that map the swagger tag to a legal variable nametag => 'tag' + index++
tplRoottemplates directory location, which must container the four template part: header, interface, fn, body
templatescustom the templates{}
apiNameMappermap the api to a legal function namepath + method
interfaceNameMappergenerate the interface nameapiName + type
responseInterceptora intercept function to preprocess the response schema before generate the interface, it is usefull to extract the exact response type that your api return like { code: 0, data: exact_data }schema => schema
outthe file path to write out
skipBodyOfGetwhether or not to skip the body parameters of get requesttrue

Template

the template is using nunjunks format, and it has been divided into four parts:

partdescription
headerthe ts file header template, provided the HeaderContext enviroment
interfacethe ts interface template, provided the InterfaceContext environment
fnths ts api function template, provided the FnContext environment
bodyths ts main module template, provided the BodyContext environment

The context definitions:

// more type definitions can be found in source: src/type.ts
export interface HeaderContext {
  date: string
  basePath: string
}

export interface InterfaceContext {
  name: string
  description?: string
  field?: Field
}

export interface FnContext {
  description?: string
  name: string
  url: string
  method: string
  query?: string
  body?: string
  path?: string
  response?: string
}

export interface BodyContext {
  tags: [string, TagDescr][]
}

The default templates is written in typescript with axios.

You can totally rewrite all the template by providing a custom tplRoot in options, or you can just replace some specific part by the templates options.

Source file can be found in: src/templates

0.2.10

4 years ago

0.1.10

5 years ago

0.1.9

5 years ago

0.1.8

5 years ago

0.1.7

5 years ago

0.1.6

5 years ago

0.1.5

5 years ago

0.1.4

5 years ago

0.1.3

5 years ago

0.1.2

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago