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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andremao/mockdb

v1.1.17

Published

这是一个支持 **热加载配置文件**、**JSON 文件持久化**、**模块化** 来管理 `mock` 请求的 Express 中间件模块

Readme

MockDB

这是一个支持 热加载配置文件JSON 文件持久化模块化 来管理 mock 请求的 Express 中间件模块

安装

npm i -D @andremao/mockdb

使用

  1. 在项目的根目录下新建目录 mockdb/mock,在此目录下创建的所有 *.js 文件都将自动识别为 mockdb 配置文件

  2. 当调用 service 方法获取 service 实例时,持久化的 *.json 文件会自动生成在 mockdb/db/*.json

  3. mockdb 配置文件内容如下(假设存在 mockdb/mock/user.js 配置文件):

    const service = require('@andremao/mockdb').service('user.json');
    const mockjs = require('mockjs');
    
    module.exports = {
      // 要被 mockjs 拦截的请求集
      requests: [
        // 增
        {
          // 请求类型支持大小写
          method: 'post',
          // 注意:
          //   mockjs 只能拦截本地主机地址(如:http://localhost:8080/user)
          //   mockjs 不能拦截跨域的线上地址(如:http://api.itcast.cn/user)
          url: '/user',
          handler(req, res) {
            console.log(req.body, 'req.body');
            // 插入单个,返回插入之后的对象(包含 id)
            const user = service.create(req.body);
            res.json({
              code: 200,
              message: '添加用户成功',
              data: user,
            });
          },
        },
        // 删
        {
          // 可以通过 active 配置该请求的激活状态,默认为激活
          active: false,
          method: 'delete',
          url: '/user/:id',
          handler(req, res) {
            console.log(req.params, 'req.params');
            // 根据 id 删除,返回被删除的对象
            const user = service.delete(req.params.id);
            res.json({
              code: 200,
              message: 'ok',
              user,
            });
          },
        },
        // 改
        {
          method: 'patch',
          url: '/user/:id',
          handler(req, res) {
            console.log(req.params, 'req.params');
            console.log(req.body, 'req.body');
            // 根据 id 补丁更新,返回更新后的对象
            const user = service.patch(req.params.id, req.body);
            res.json({
              code: 200,
              message: 'ok',
              user,
            });
          },
        },
        // 根据 id 查询
        {
          method: 'get',
          // 支持动态路由参数
          url: '/user/:id',
          handler(req, res) {
            const { id } = req.params;
            // 根据 id 查找用户
            const user = service.find(id);
            res.json({
              code: 200,
              message: '获取用户信息成功',
              data: user,
            });
          },
        },
        // 分页查询
        {
          method: 'GET',
          url: '/users',
          handler(req, res) {
            console.log(req.query, 'req.query');
    
            // // 如果json文件中没有数据,则自动生成100条
            // const { list } = service.getState();
            // if (!list || !list.length) {
            //   service.batchCreate(
            //     mockjs.mock({
            //       'list|100': [{ name: '@CNAME()', 'age|15-60': 1, id: '@GUID()' }],
            //     }).list,
            //   );
            // }
            // // /如果json文件中没有数据,则自动生成100条
    
            const { page, size, name, ageType } = req.query;
            const age = parseInt(req.query.age);
            const result = service.pagingQuery({
              page,
              size,
              // 过滤,就是数组的 filter 方法的回调函数
              filter(user) {
                const results = [];
                if (name) {
                  results.push(user.name.includes(name));
                }
                if (!isNaN(age)) {
                  switch (ageType) {
                    case 'eq':
                      results.push(user.age === age);
                      break;
                    case 'ne':
                      results.push(user.age !== age);
                      break;
                    case 'gt':
                      results.push(user.age > age);
                      break;
                    case 'lt':
                      results.push(user.age < age);
                      break;
                    case 'ge':
                      results.push(user.age >= age);
                      break;
                    case 'le':
                      results.push(user.age <= age);
                      break;
                  }
                }
                return results.every((v) => v);
              },
              // 排序,就是数组的 sort 方法的回调函数
              sort(user1, user2) {
                // 何时把 user1 放到 user2 后面? 当 user1.age > user2.age 时
                if (user1.age > user2.age) return 1;
                // 何时把 user1 放到 user2 前面? 当 user1.age > user2.age 时
                if (user1.age < user2.age) return -1;
                // 何时不用换位置? 当 user1.age === user2.age 时
                return 0;
    
                // 补充顺明:
                // 1 上面的代码等价:return user1.age - user2.age; 虽然代码量少,但不推荐,因为可读性差
                // 2 不要直接使用 return user1.age > user2.age; 因为在不同运行环境下执行结果可能不一致,有坑!!!
              },
            });
            res.json({
              code: 200,
              message: 'ok',
              ...result,
            });
          },
        },
      ],
    };
  4. 在 vue 中使用,修改 vue.config.js 配置文件:

    const mockdb = require('@andremao/mockdb');
    const bodyParser = require('body-parser');
    
    module.exports = {
      devServer: {
        before(app) {
          // 判断是否为开发环境
          if (process.env.NODE_ENV.toUpperCase() === 'DEVELOPMENT') {
            app.use(bodyParser.json(), mockdb.middleware());
          }
        },
      },
    };

    Demo 仓库地址:https://github.com/andremao/vue-mockdb-demo

  5. 重启项目即可,并支持热加载,后续改动 mockdb/mock/*.jsmockdb/db/*.json 文件无需重启

  6. 可以实现 mock 环境线上环境 混搭:

    1. 使用代理服务器(推荐),例如:Vue CLI 配置,详见:https://cli.vuejs.org/zh/config/#devserver-proxy

      const mockdb = require('@andremao/mockdb');
      const bodyParser = require('body-parser');
      
      module.exports = {
        devServer: {
          before(app) {
            // 判断是否为开发环境
            if (process.env.NODE_ENV.toUpperCase() === 'DEVELOPMENT') {
              app.use(bodyParser.json(), mockdb.middleware());
            }
          },
          proxy: {
            '/api': {
              target: 'http://some.api.itcast.cn',
              changeOrigin: true,
              pathRewrite: {
                '^/api': '',
              },
            },
          },
        },
      };
    2. 或者,配置 axios 的请求拦截器,动态设置 baseURL

      发请求:

      axios.post('/login?ismock=1', { uname: 'andremao', pwd: 'qwe123' });

      axios:

      // 创建 axios 请求实例
      const request = axios.create({
        baseURL: 'http://api.itcast.cn/',
      });
      
      // 请求拦截器
      request.interceptors.request.use((cfg) => {
        // 如果是 mock 则把请求 baseURL 改成 本地地址,不然 mockjs 拦截不到
        if (cfg.url.includes('ismock=1')) {
          cfg.baseURL = 'http://localhost:8080';
        }
        return cfg;
      });

API

mockdb

const mockdb = require('@andremao/mockdb');

mockdb.middleware()

获取中间件处理函数

mockdb.service(jsonFileName)

返回能操作 JSON 文件的 service 实例,jsonFileName 为 JSON 文件名(尽量和 mockdb 配置文件名保持一致

service

const service = mockdb.service('user.json');

service.create(model)

创建数据,model 为对象,如果没有 id,则会自动生成 id,返回 model(包含 id)

service.batchCreate(models)

批量创建,models 为数组,如果没有 id,则会自动生成 id,返回 models(包含 id)

service.delete(id)

根据 id 删除,删除成功返回被删除的数据,否则返回 null

service.patch(id, data)

根据 id 补丁更新,返回更新后的对象

service.find(id)

根据 id 查找,返回找到的对象

service.pagingQuery({ page, size, filter, sort })

分页查询,返回对象,形如{ data: [...], total: 100 }

参数列表如下:

  • page: 当前页码,默认 1
  • size: 每页条数,默认 10
  • filter: 过滤方法 filter 的回调函数,Function
  • sort: 排序方法 sort 的回调函数,Function

返回值如下:

  • data:查询到的数据列表,Array
  • total:满足条件的总数据量,Number

service.getState()

获取 JSON 文件中的全部数据,返回对象,形如:{ list: [ ... ], ... }

service.setState(state)

设置 JSON 文件中的全部数据,返回 service 实例

service.getDB()

返回 db 实例,具体 API 详见:lowdb