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

ohana

v1.0.3

Published

A simple server that return fake json data for test

Downloads

116

Readme

ohana

A http server that return simulation json data.

中文文档

Install

npm install ohana

Usage

You can use a variety data template parser. Recommendation: madoka and mockjs

var madoka = require("madoka");
var Mock = require('mockjs');
var Server = require("ohana");

// use 'madoka.generate' as default parser
var server = new Server({
  parser: madoka.generate
});

// get article parser
server.get('/article/', {
  delay: 200,
  data: function (params, query) {
    console.log(params);
    console.log(query);

    return [
      '{{ repeat(10) }}',
      {
        'id': '{{ index() }}',
        'title': '{{ lorem(1, "sentences") }}',
        'author': '{{ firstName() }} {{ lastName() }}',
        'brief': '{{ lorem(1, "paragraphs") }}',
        'post_time': '{{ date(new Date(2014, 0, 1), "YYYY-MM-dd HH:mm:ss") }}',
        'read_count': '{{ integer(100, 10000) }}'
      }

    ];

  }
});

// get one article, use mock.js to parse tempate.
server.get('/article/:id', {
  parser: Mock.mock,
  data: function (params, query) {
    return {
      "status": "ok",
      "data": {
        "id": params.id,
        "title": "@TITLE(5, 7)",
        "author": "@NAME",
        "post_time": "@DATETIME('yyyy-MM-dd HH:mm:ss')",
        "content": "@PARAGRAPH(2)",
        "poster": "@IMAGE('700x350', '#ccc', '#000', 'hello world')",
        "read_count|0-1000": 100
      }
    }
  }
});

// process data before response.
server.get('/user/filter/', {
  beforeResponse: function (data) {
    return data.data;
  },
  data: function (params, query) {
    return {
      'data': [
        '{{ repeat(5, 7) }}',
        {
          'user_name': '{{ firstName() }} {{ lastName() }}'
        }
      ]
    }
  }
});

// specify content-type
// return 'text/html'
 server.get('/user/:id/tag', {
   contentType: 'text/html',
   beforeResponse: function(data) {
     return data.tag;
   },
   data: {
     tag: 'loli'
   }
 });

server.start(3000);

API

Server(options)

Server constructor

  • options

    • parser: default parser. Every function like below can use as a parser.
    function parser(dataTemplate) {
      // parse tempate logic
      var data = someOperate(dataTemplate);
    
      // return the parsed data.
      return data;
    }
    
    • contentType: default content-type
    • onError: handle error
    • proxy: default proxy request config
      • urlRoot: the root url of the target server
      • method: request method,GET | POST | PUT | PATCH | DELETE

server.get(path, options)

Listen a GET request.

  • path: url path
  • options:
    • parser: template parser
    • delay: delay response. Unit is ms.
    • beforeResponse: A function process data before response
    • contentType: response content-type
    • statusCode: http status code
    • data: data template. It can be a function. Function parameter 'params' matching routing parameters, 'query' is submitted or parameter query.
server.get('/article/:id', {
  data: function (params, query) {
    return {
      "status": "ok",
      "data": {
        "id": params.id,
        "title": "@TITLE(5, 7)",
        "author": "@NAME",
        "post_time": "@DATETIME('yyyy-MM-dd HH:mm:ss')",
        "content": "@PARAGRAPH(2)",
        "poster": "@IMAGE('700x350', '#ccc', '#000', 'hello world')",
        "read_count|0-1000": 100
      }
    }
  }
});

server.post(path, options)

POST request.

server.delete(path, options)

DELETE request.

server.put(path, options)

PUT request.

server.patch(path, options)

PATCH request.

server.proxy(path, option)

Proxy request.

  • path: url path
  • options:
    • urlRoot: url root of target server,
    • method: request method,GET | POST | PUT | PATCH | DELETE
server.proxy('/article/:id', {
  urlRoot: 'http://localhost:3000',
  method: DELETE
});

// global config
var server = new Server({
  proxy: {
    urlRoot: 'http://localhost:3000',
    method: 'get'
  }
});

// use global config
server.proxy('/article/');

server.proxy('/article/:id');

server.proxy('/article/', {
  method: 'POST'
});

server.proxy('/article/:id', {
  method: 'DELETE'
});

server.proxy('/article/:id', {
  method: 'PUT'
});

server.proxy('/article/:id', {
  method: 'PATCH'
});

server.register(apiList);

register module

  • apiList: api module list
server.register([
  require('./article/index'),
  require('./user/index')
]);

server.start(port, host)

  • port
  • host

Route

Basic string:

"/articles" will only match routes that == "/articles".

Named parameters:

"/articles/:title" will only match routes like "/articles/hello", but *not* "/articles/".

Optional named parameters:

"/articles/:title?" will match "/articles/hello" AND "/articles/"

Periods before optional parameters are also optional:

"/:n.:f?" will match "/1" and "/1.json"

Splaaaat! :

"/assets/*" will match "/assets/blah/blah/blah.png" and "/assets/".

"/assets/*.*" will match "/assets/1/2/3.js" as splats: ["1/2/3", "js"]

Mix splat with named parameters:

"/account/:id/assets/*" will match "/account/2/assets/folder.png" as params: {id: 2}, splats:["folder.png"]

Named RegExp:

"/lang/:lang([a-z]{2})" will match "/lang/en" but not "/lang/12" or "/lang/eng"

Raw RegExp:

/^\/(\d{2,3}-\d{2,3}-\d{4})\.(\w*)$/ (note no quotes, this is a RegExp, not a string.) will match "/123-22-1234.json". Each match group will be an entry in splats: ["123-22-1234", "json"]

visit: https://github.com/aaronblohowiak/routes.js


CH


ohana

一个返回模拟 json 数据的 http 服务器。

安装

npm install ohana

使用

可以使用多种 json 模板解析器。推荐使用 madokamockjs

var madoka = require("madoka");
var Mock = require('mockjs');
var Server = require("ohana");

// 使用 madoka.generate 为默认的解析器,解析数据模板
var server = new Server({
  parser: madoka.generate
});

// 获取文章列表
server.get('/article/', {
  delay: 200,
  data: function (params, query) {
    console.log(params);
    console.log(query);

    return [
      '{{ repeat(10) }}',
      {
        'id': '{{ index() }}',
        'title': '{{ lorem(1, "sentences") }}',
        'author': '{{ firstName() }} {{ lastName() }}',
        'brief': '{{ lorem(1, "paragraphs") }}',
        'post_time': '{{ date(new Date(2014, 0, 1), "YYYY-MM-dd HH:mm:ss") }}',
        'read_count': '{{ integer(100, 10000) }}'
      }

    ];

  }
});

// 获取一篇文章, 使用 mock.js 解析
server.get('/article/:id', {
  parser: Mock.mock,
  data: function (params, query) {
    return {
      "status": "ok",
      "data": {
        "id": params.id,
        "title": "@TITLE(5, 7)",
        "author": "@NAME",
        "post_time": "@DATETIME('yyyy-MM-dd HH:mm:ss')",
        "content": "@PARAGRAPH(2)",
        "poster": "@IMAGE('700x350', '#ccc', '#000', 'hello world')",
        "read_count|0-1000": 100
      }
    }
  }
});

// 输出数据之前,处理一下数据
server.get('/user/filter/', {
  beforeResponse: function (data) {
    return data.data;
  },
  data: function (params, query) {
    return {
      'data': [
        '{{ repeat(5, 7) }}',
        {
          'user_name': '{{ firstName() }} {{ lastName() }}'
        }
      ]
    }
  }
});

// 指定输出的 content-type
// 返回 text/html 类型
 server.get('/user/:id/tag', {
   contentType: 'text/html',
   beforeResponse: function(data) {
     return data.tag;
   },
   data: {
     tag: 'loli'
   }
 });

server.start(3000);

API

Server(options)

Server构造函数

  • options

    • parser: 默认数据模板解析器。任何像以下处理的方法都可以作为解析器
    function parser(dataTemplate) {
      // 解析数据模板的逻辑
      var data = someOperate(dataTemplate);
      // 返回解析后的数据
      return data;
    }
    
    • contentType: 默认输出数据的 content-type
    • onError: 错误处理
    • proxy: 代理请求参数
      • urlRoot: 目标服务器请求根目录,
      • method: 请求类型,GET | POST | PUT | PATCH | DELETE

server.get(path, options)

匹配 GET 方式的请求。

  • path: 路由匹配地址
  • options:
    • parser: 数据解析器。
    • delay: 延迟多少毫秒后返回。
    • beforeResponse: 数据输出之前处理数据。
    • contentType: 响应数据的 content-type
    • statusCode: http 状态码
    • data: 返回的数据,可以接受方法, 方法中的参数 params 是路由匹配的参数,query 是提交或查询的参数。
server.get('/article/:id', {
  data: function (params, query) {
    return {
      "status": "ok",
      "data": {
        "id": params.id,
        "title": "@TITLE(5, 7)",
        "author": "@NAME",
        "post_time": "@DATETIME('yyyy-MM-dd HH:mm:ss')",
        "content": "@PARAGRAPH(2)",
        "poster": "@IMAGE('700x350', '#ccc', '#000', 'hello world')",
        "read_count|0-1000": 100
      }
    }
  }
});

server.post(path, options)

与 get 同理

server.delete(path, options)

与 get 同理

server.put(path, options)

与 get 同理

server.patch(path, options)

与 get 同理

server.proxy(path, option)

代理请求

  • path: 路由匹配地址
  • options:
    • urlRoot: 目标服务器请求根目录,
    • method: 请求类型,GET | POST | PUT | PATCH | DELETE
server.proxy('/article/:id', {
  urlRoot: 'http://localhost:3000',
  method: DELETE
});

// 可以设置全局默认配置
var server = new Server({
  proxy: {
    urlRoot: 'http://localhost:3000',
    method: 'get'
  }
});

// 之后可以省略配置
server.proxy('/article/');

server.proxy('/article/:id');

server.proxy('/article/', {
  method: 'POST'
});

server.proxy('/article/:id', {
  method: 'DELETE'
});

server.proxy('/article/:id', {
  method: 'PUT'
});

server.proxy('/article/:id', {
  method: 'PATCH'
});

server.register(apiList);

注册 api

  • apiList: api 模块列表
server.register([
  require('./article/index'),
  require('./user/index')
]);

server.start(port, host)

  • port: 服务器监听的网络端口
  • host: 主机

路由匹配规则:

字符串:

"/articles" 只会匹配到 "/articles"。 /articles/ 不会被匹配到。

命名参数:

"/articles/:title" 只会匹配到像"/articles/hello"的路由, 但是不会匹配到 "/articles/".

可选参数:

"/articles/:title?" 匹配 "/articles/hello" 和 "/articles/"。

可选参数前面的参数也是可选的:

"/:n.:f?" 会匹配到 "/1" 和 "/1.json"

星号(splat):

"/assets/*" 匹配到 "/assets/blah/blah/blah.png" 和 "/assets/".

"/assets/*.*" 会匹配到 "/assets/1/2/3.js", 并且有 splats: ["1/2/3", "js"]

星号和命名参数:

"/account/:id/assets/*" 会匹配到 "/account/2/assets/folder.png",并且有 params: {id: 2}, splats:["folder.png"]

正则表达式:

"/lang/:lang([a-z]{2})" 会匹配到 "/lang/en", 但是不会匹配到 "/lang/12" 和 "/lang/eng"

参考: https://github.com/aaronblohowiak/routes.js