转载

一起来为koa2中间件写definitions吧

前阵子 koa2 发布了,一些中间件也增加了对 koa2 的支持,这当然是大大的好事了。但是,像我这样喜欢用 typescript + koa2node 的人来说,某个中间件没对应的 .d.ts 文件会是件很蛋疼的事。

没人写只能自己来了,写过之后会发现其实很简单,还能对那些中间件有更深入的了解。下面介绍下怎么找到支持 koa2 的中间件以及怎么写对应的 .d.ts 文件:

middlewares

koa 的中间件可以在 koa 的 wiki 上看到,里面列出了哪些中间件支持 koa2 ,我们直接在上面找就行了。

为了方便,我写了个命令行工具 koa2-middlewares 来查看这些中间件(当然是用 typescript 写的啦)。全局安装后,通过命令行 koams list 可以查看所有的 koa2 中间件,

koams list -i 会过滤掉已经有 .d.ts 文件的中间件。具体用法参见该工具的 README 。

definitions

知道有哪些 koa2 中间件了就可以挑一个开始写了。以 koa-compress 为例:

通过 koams open koa-compress 命令打开 koa-compress 的 github主页 ,切到 v2.x 分支,可以看到它的用法如下:

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 的架子就是这样的:

/// <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 的源码:

'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行,通过源码我们可以得出以下结论:

  1. options 为非必须参数

  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. fork DefinitelyTyped 这个仓库到你的 github

  2. 在自己 fork 过来的 DefinitelyTyped 添加对应中间件目录

  3. 目录里放对应 .d.ts 文件和 -tests.ts 文件。

  4. 提交代码,发起 pull request ,等待合并。

结语

编写和发布一个 .d.ts 文件就是这么简单。目前我已经添加了 koa-routerkoa-statickoa-bodyparserkoa-favicon

喜欢 typescript + koa2 的童鞋可以一起来搞,方便自己也方便大家。

原文  https://segmentfault.com/a/1190000004886691
正文到此结束
Loading...