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

node-qi

v0.6.3

Published

`Function-driven elegant event cross-language framework`

Downloads

1

Readme

Intro

Function-driven elegant event cross-language framework

Design

Purpose

  • Serverless.
  • Focus on frontend.

Principle

  • Everything base Event
  • Everything is Function
  • Everything through IO

TODO

  • [ ] 函数调用机制,考虑更好的中间件?

0.7

  • [ ] 自定义 Listener
  • [ ] 插件机制
  • [ ] Dashboard

0.8

  • [ ] 函数分布式调用

Structures

Application Structure

- app
  + posts
    - posts.js
    - function.yml
  + login
    - login.js
    - function.yml
  + logout
    - logout.js
    - function.yml
  + resetPassword
    - function.yml
  - qi.<ENV>.yml
  - qi.yml

Runtime Structure (TODO)

App ID is defined by md5(<Machine Name>:<QI Directory>) or user defined --name

- [Home Diretory]
  - .qi
    - apps
      - [App ID].json
    - logs
      - [App ID].error.log

Design

                        <Event Listeners>

     HTTP (WS)    CRON        MQTT       Queue        EMAIL

        |           |           |           |           |

      Server      Timer    Subscriber    Worker     Postfix

        ↘           |           |           |           ↙

                    ↘           ↓          ↙                [Event Input]

                 ----------  Dispatcher  -----------
                 |                                 |
                 |              ↓                  |        ←   Error Event
                 |                                 |
                 |        Match Function           |                ↑
                 |                                 |
                 |              ↓   [Services]     |                |
                 |                                 |
                 |       Invoke Function           |                |
                 |                                 |
                 |              ↓                  |        →     Error
                 |                                 |
                 -----------------------------------

                                |                           [Event Output]

      ↙             ↙           ↓           ↘           ↘

  Render/Reply    <No>     MQTT Publish     <No>        <No>


                            <Event End>

Usage

Create qi app

bin/qi new [dir]

Create qi function

bin/qi create <function>

Start qi service

./bin/qi start [dir]

Config qi app

qi.xml

listeners:
  http:                                 # HTTP listener config
    cookie:
      keys: ["secret", "key"]
    session:
      type: cookie
      key: sess
      signed: true

  websocket:
    path: /ws

  queue:                                # Queue listener config
    host: localhost
    queue: default                    # Queue name for process
    concurrency: 1                    # Queue process concurrency

  mqtt: &mqttTestConfig
    url: mqtt://localhost:1883
    username: username
    password: password
    keepalive: 1
    connectTimeout: 1000

settings:                               # Services config for functions usage
  db:                                   # Service instance name
    url: 'mongodb://localhost:27017'    # Service config

  queue:                                # Service name
    queue: default                      # Use queue name
    host: localhost

  mqtt: *mqttTestConfig


settings:
  <dirName>:                      # Conver the function settings by dir name
    <key>: <value>

# TODO: implements
plugins:
  auth: plugin_auth

Write "events" function

events/events.js:

event is the data base on listener qi qi includes services and native params: function, event, invoke(function, event, qi)

exports.show = function *(event, qi, next) {
  return {
    body: {
      event: event
    }
  }
}

events/function.yml:

functions:
  show:                           # Function name
    events:                       # All events for function
      http:                       # Event name
        method: get
        path: /events
        cors: true                # Cors. not implements.
        stacks:
          - common.checkPlatform
          - common.checkIP

settings:
  <key>: <value>

Invoke the function

./bin/qi invoke events.show

Context

Context is qi

Events

HTTP / WEBSOCKET

HTTP Config

listeners:
  http:
    # Cookie config
    cookie:
      keys: ["secret", "key"]

    # Session config
    session:
      type: "cookie"
      key: "sess"
      signed: true

    // How many process to start
    process:
      instances: 2

HTTP Event Match

http match:

events:
  - type: http
    method: get
    path: /index/home
events:
  http: /index/home

HTTP Input

{
  "type": "http",
  "method": "get",
  "path": "/users",
  "url": "http://localhost/users",
  "secure": false,
  "origin": "http://localhost",
  "host": "locahost:3000",
  "domain": "localhost",
  "ip": "127.0.0.1",
  "ips": [],
  "query": {
    "a": "b"
  },
  "headers": {
    "user-agent": "xxx"
  },
  "cookies": {
    "uid": "xxxx"
  },
  "sessions": {
    "uid": "xxx"
  },
  "files": {
    "file": {
      "tmpPath": "/tmp/xxx",
      "name": "xxx",
      "size": 111
    }
  },
  "body": {
    "username": "xxx"
  }
}

HTTP Output

http output:

{
  "status": 200,
  "body": "OK",
  "sessions": {
    "uid": "xx"
  },
  "cookies": {
    "sess": "xxx"
  },
  "redirect": "Redirect URL",
  "file": "File to send to client",
  "attachment": "File to download"
}

websocket output:

return String

Queue

Queue Config

listeners:
  queue:
    name: "default"       # Queue name to process
    host: "localhost"     # Redis host for queue

settings:
  queue:                  # Service name
    queue: 'default'      # Use queue name
    host: "localhost"

Queue Match Event

events:
  - type: queue
    name: default

Queue Input

{
  "type": "queue",
  "name": "default",
  "<key>": "<value>"
}

Queue Output

return true/false is enough.

Cron

Cron Config

listeners:
  cron: true

Cron Match Event

events:
  - type: cron
    cron: "* * * * *"
events:
  cron: "* * * * *"

Cron Input

{
  "type": "cron",
  "time": 12342134123
}

Cron Output

return true/false is enough.

MQTT

MQTT Config

listeners:
  mqtt:
    url: mqtt://localhost:1883
    username: username
    password: password
    keepalive: 1
    connectTimeout: 1000

MQTT Match Event

events:
  - type: mqtt
    mqtt: default
    topic: posts/a

MQTT Input

{
  topic: "posts/a",
  payload: "message"
}

MQTT Output

return true/false is enough.