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

ffmock

v2.0.0

Published

Fire Frontend Mock Server

Downloads

20

Readme

FFMock - Fire Frontend Mock Server

前端开发经常要模拟后端接口的返回数据(mock),把 mock 写在前端代码里不够方便,此工具改为运行一个能返回 mock 数据的 server 来解决此问题。
前端的请求统一发给此 mock server,对需要 mock 对接口返回 mock 数据,对不需要 mock 的接口返回原接口的响应。

使用方法

全局使用

sudo npm install -g ffmock
ffmock /path/to/mock.config.js

项目内使用

安装依赖

npm install ffmock

package.json

{
  "name": "xxx",
  "scripts": {
    "mock": "ffmock /path/to/mock.config.js"
  }
}

运行 mock

npm run mock

config 自动 reload

ffmock 会监控 mock config 文件,自动加载最新的配置内容

mock config 格式

module.exports = {
  // mock 监听的端口
  port: 9095,

  /*
  定义上游 API URL
  遇到 mocks 里没定义的请求时,会代理到此网址;mock 处理函数里也可手动请求此网址,使用其响应内容。

  传值:
  - 若为字符串,会把它和请求路径拼起来,作为要调用的 URL
  - 若为函数,由函数返回完整的调用 URL
  - 若为空,请求 upstream 会抛出异常
  */
  upstream: null,

  // mock 前面架了反向代理(如 Nginx)时可配置此项以便正确识别接口路径
  base: '',

  // 预处理器。所有请求在发给 mock 函数前都会先由此函数进行一遍处理
  // 与 mock 处理函数格式相同
  preprocess: async (request, response, utils) => {},

  // 后处理器。所有请求在结束前都会由此函数再处理一遍
  // 与 mock 处理函数格式相同
  postprocess: async (request, response, utils) => {},

  // mock 内容
  // 若 API 没有匹配的 mocks 没定义的 API,会返回 upstream 的响应内容
  mocks: {
    // APIPath: mockData | mockFunction
    // path 结尾带不带 '/' 都能匹配上

    // 可以直接指定一个数据作为响应结果(输出时会将其 JSON 化)
    apiPath1: { a: 1, b: 2 },

    /*
    也可以指定一个函数,实现更复杂的行为,例如:
    - 生成与 request 对应的 response
    - 把修改过的 upstream 响应结果作为 response
    - 自定义 HTTP headers、模拟随机的请求失败、模拟网络延迟
    详见下方的 "mockFunction 格式"
    */
    apiPath2: (request, resopnse, utils) => doSomeThing(),

    // 路径结尾可以带 * 号,代表通配符
    // 例如以下路径可匹配 /path/ /path/abc/ /path/abc/def/
    '/path/*': {}

    // 路径任意小节以 : 开头,代表这小节可以是任意值
    // 例如以下路径可匹配 /path/abc/detail /path/123/detail
    '/path/:abc/detail'

    // 带通配符的路径,优先级低于不带通配符的
  },
}

mockFunction 格式

/*
request     ServerRequest     客户端请求内容
response    ServerResponse    mock 响应内容
utils       {}                一些工具函数

mockFunction 通过修改 response 的属性来设置响应内容(注意,不是通过返回 data 来指定响应内容),
例如设置 resonse.data 或 response.body。
详见 ServerResponse 格式说明。

若 mock 需要异步执行,可以返回一个 promise(或把 mockFunction 定义成 async 函数)
这样当返回的 promise resolved 时,才执行响应(此 promise 无需 resolve 任何结果)
*/
async function mockFunction(request, response, utils) {
  if (request.query.someFlag) {
    response.data = { success: true }
  } else {
    response.data = { success: false }
  }
  await utils.sleep(3) // 3 秒后才响应
}

utils 列表

{
  // 完整的 mock config 内容
  config,

  /*
  用 upstream 的响应结果填充当前 response
  可通过 options 自定义向 upstream 发起的请求,格式见 ClientRequest 的说明
  注意:这是个异步函数,要使用它,mockFunction 必须也是异步的
  */
  API: async (options) => {},

  // 随机数生成器
  random: {
    int: (min, max) => int,
    float: (min, max) => float,
    string: (len, seed='abcdefg0123456...') => string,
    choice: ([a, b, c]) => item,     // 从数组里随机返回一个 item
  },

  // 生成一个指定秒数后完成的 promise,用于实现异步的 sleep 效果
  sleep: async (seconds) => {},
}

ServerRequest -- 客户端请求内容

// 以 URL www.baidu.com:9900/abcde?a=1&b=2#xyz 为例
{
    method,         // GET
    host,           // www.baidu.com:9900
    path,           // /abcde
    query,          // { a: '1', b: '2' }

    // headers 经过特殊处理,读写时无需介意 header name 大小写。
    // 例如用 'content-type' 也能读到 'Content-Type'
    headers,        // Headers({ 'Content-Type': 'xxx' })
    body,           // 请求的原始 body
    data,           // 若 Content-Type 是 json 或 x-www-form-urlencoded 会被解析成 object,否则为 undefined
                    // (JSON 解析失败也为 undefined)
}

ServerResponse -- mock 响应内容

{
    status,         // status code,默认 200
    headers,        // Headers()
    body,           // 响应体,字符串形式。可被 data 覆盖
    data,           // 此值不为 undefined 时,会将其 JSON 化作为 body
}

ClientRequest -- utils.API() 的请求内容

构造参数:

{
    method,
    url,
    query,         // object, 会作为 query string 补充到 URL 里
    headers,
    body,
    data,          // 若指定,会根据 headers['Content-Type'] 对其格式化(默认 JSON 化)并代替 body
}

数据格式:

// 以 URL https://www.baidu.com:9900/abcde?a=1&b=2#xyz 为例
{
    method,             // GET
    protocol,           // https:
    host,               // www.baidu.com
    port,               // 9900
    path,               // /abcde
    headers,            // Headers()
    body,
}

ClientResponse -- utils.API() 的返回内容(一般用不到)

{
    status,     // status code
    headers,    // Headers()
    body,       // 原始响应体
    data,       // 解析过的响应体。Content-Type 不为 json 或 json 解析失败时为 null
}

mock 使用方式演示

修改原接口返回的数据

module.exports = {
  upstream: 'xxx',
  mocks: {
    some_api: async (request, response, utils) => {
      await utils.API()
      response.data.foo = 'bar2'
    },
  },
}

在多次请求、多个接口之间保留数据

// id: value
const APIAData = {}

module.exports = {
  upstream: 'xxx',
  mocks: {
    'api/a/get': (request, response, utils) => {
      const id = request.query.id
      response.data = id in APIAData ? APIAData[id] : null
    },
    'api/a/set': (request, response, utils) => {
      const id = request.query.id
      APIAData[id] = request.query.value || null
    },
  },
}

定义一个全局的预处理器 (也可用同样的方法定义后处理器)

const preprocess = mockFunction => {
  return (request, response, utils) => {
    // 进行一些预处理行为
    response.headers['My-Custom-Header'] = 'Custom-Value'

    mockFunction(request, response, utils)
  }
}

module.exports = {
  upstream: 'xxx',
  mocks: {
    // 用 preprocess 包裹原 mockFunction 即可应用此预处理器
    'api/a/get': preprocess((request, response, utils) => {
      // xxx
    }),
  },
}