一塊兒來爲koa2中間件寫definitions吧

前陣子koa2發佈了,一些中間件也增長了對koa2的支持,這固然是大大的好事了。可是,像我這樣喜歡用typescript+koa2node的人來講,某個中間件沒對應的.d.ts文件會是件很蛋疼的事。javascript

沒人寫只能本身來了,寫過以後會發現其實很簡單,還能對那些中間件有更深刻的瞭解。下面介紹下怎麼找到支持koa2的中間件以及怎麼寫對應的.d.ts文件:java

middlewares

koa的中間件能夠在koawiki上看到,裏面列出了哪些中間件支持koa2,咱們直接在上面找就好了。node

爲了方便,我寫了個命令行工具koa2-middlewares來查看這些中間件(固然是用typescript寫的啦)。全局安裝後,經過命令行koams list能夠查看全部的koa2中間件,
koams list -i會過濾掉已經有.d.ts文件的中間件。具體用法參見該工具的READMEgit

definitions

知道有哪些koa2中間件了就能夠挑一個開始寫了。以koa-compress爲例:github

經過koams open koa-compress命令打開koa-compressgithub主頁,切到v2.x分支,能夠看到它的用法以下:typescript

var compress = require('koa-compress')
var Koa = require('koa')

var app = new Koa()
app.use(compress({
  filter: function (content_type) {
    return /text/i.test(content_type)
  },
  threshold: 2048,
  flush: require('zlib').Z_SYNC_FLUSH
}))

從用法上看知道koa-compress這個模塊導出的是一個函數,接受一個options參數,options有三個屬性,因此單從readme上的代碼示例來看,koa-compress.d.ts的架子就是這樣的:npm

/// <reference path="../node/node.d.ts" />
/// <reference path="../koa/koa.d.ts" />

declare module "koa-compress" {

    import * as Koa from "koa";

    function compress(options: {
        filter: (content_type: string) => boolean;
        threshold: number;
        flush:number;
    })

    export = compress;
}

咱們再看下koa-compress的源碼:json

'use strict';

/**
 * Module dependencies.
 */

var compressible = require('compressible')
var isJSON = require('koa-is-json')
var status = require('statuses')
var Stream = require('stream')
var bytes = require('bytes')
var zlib = require('zlib')

/**
 * Encoding methods supported.
 */

var encodingMethods = {
  gzip: zlib.createGzip,
  deflate: zlib.createDeflate
}

/**
 * Compress middleware.
 *
 * @param {Object} [options]
 * @return {Function}
 * @api public
 */

module.exports = (options) => {
  options = options || {}

  var filter = options.filter || compressible

  var threshold = !options.threshold ? 1024
    : typeof options.threshold === 'number' ? options.threshold
    : typeof options.threshold === 'string' ? bytes(options.threshold)
    : 1024

  return function compress(ctx, next) {
    ctx.vary('Accept-Encoding')

    return next().then(() => {
      var body = ctx.body
      if (!body) return
      if (ctx.compress === false) return
      if (ctx.request.method === 'HEAD') return
      if (status.empty[ctx.response.status]) return
      if (ctx.response.get('Content-Encoding')) return

      // forced compression or implied
      if (!(ctx.compress === true || filter(ctx.response.type))) return

      // identity
      var encoding = ctx.acceptsEncodings('gzip', 'deflate', 'identity')
      if (!encoding) ctx.throw(406, 'supported encodings: gzip, deflate, identity')
      if (encoding === 'identity') return

      // json
      if (isJSON(body)) body = ctx.body = JSON.stringify(body)

      // threshold
      if (threshold && ctx.response.length < threshold) return

      ctx.set('Content-Encoding', encoding)
      ctx.res.removeHeader('Content-Length')

      var stream =
      ctx.body = encodingMethods[encoding](options)

      if (body instanceof Stream) {
        body.pipe(stream)
      } else {
        stream.end(body)
      }
    });
  };
}

代碼一共就76行,經過源碼咱們能夠得出如下結論:api

  1. options爲非必須參數app

  2. options.filteroptions.threshold都爲非必須屬性

  3. options參數最後傳給了zlib模塊的方法,因此這個options是繼承於zlib.ZlibOptions

  4. koa-compress導出的函數執行後返回一個函數,這個函數是能夠做爲koa實例的use方法的參數

因此往koa-compress.d.ts中填內容後會是下面這個樣子:

/// <reference path="../node/node.d.ts" />
/// <reference path="../koa/koa.d.ts" />

declare module "koa-compress" {

    import * as Koa from "koa";
    import * as zlib from "zlib";

    interface ICompressOptions extends zlib.ZlibOptions {

        filter?: (content_type: string) => boolean;

        threshold?: number
    }
    
    function compress(options?: ICompressOptions): { (ctx: Koa.Context, next?: () => any): any };

    export = compress;
}

到這裏koa-compress.d.ts基本就算是寫好了,再加點註釋什麼的就能夠用得很爽了,最終版本能夠看下koa-compress.d.ts

寫一個.d.ts文件就是這麼簡單,寫完咱們還要發佈出去給別人用。具體步驟以下:

  1. forkDefinitelyTyped這個倉庫到你的github

  2. 在本身fork過來的DefinitelyTyped添加對應中間件目錄

  3. 目錄裏放對應.d.ts文件和-tests.ts文件。

  4. 提交代碼,發起pull request,等待合併。

結語

編寫和發佈一個.d.ts文件就是這麼簡單。目前我已經添加了koa-routerkoa-statickoa-bodyparserkoa-favicon

喜歡typescript+koa2的童鞋能夠一塊兒來搞,方便本身也方便你們。

相關文章
相關標籤/搜索