npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@stkevintan/parrot

v0.2.10

Published

convert yapi or swagger json to typescript code

Downloads

23

Readme

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
}

| option | description | default | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ | | tagMapper | a function that map the swagger tag to a legal variable name | tag => 'tag' + index++ | | tplRoot | templates directory location, which must container the four template part: header, interface, fn, body | | | templates | custom the templates | {} | | apiNameMapper | map the api to a legal function name | path + method | | interfaceNameMapper | generate the interface name | apiName + type | | responseInterceptor | a 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 | | out | the file path to write out | | | skipBodyOfGet | whether or not to skip the body parameters of get request | true |

Template

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

| part | description | | --------- | ---------------------------------------------------------------------- | | header | the ts file header template, provided the HeaderContext enviroment | | interface | the ts interface template, provided the InterfaceContext environment | | fn | ths ts api function template, provided the FnContext environment | | body | ths 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