open-index/open-npm huggingface dataset:
npm package: @kenobi.ai/rrweb-plugin-canvas-webrtc-record
Description: Plugin that live streams contents of canvas elements via webrtc
Author: kenobi
Latest version: 2.0.0-alpha.20

# rrweb canvas webrtc plugin

Plugin that live streams contents of canvas elements via webrtc

## Example of live streaming via `yarn live-stream`

https://user-images.githubusercontent.com/4106/186701616-fd71a107-5d53-423c-ba09-0395a3a0252f.mov

## Instructions

### Record side

```js
// Record side

import rrweb from 'rrweb';
import { RRWebPluginCanvasWebRTCRecord } from 'rrweb-plugin-canvas-webrtc-record';

const webRTCRecordPlugin = new RRWebPluginCanvasWebRTCRecord({
  signalSendCallback: (msg) => {
    // provides webrtc sdp offer signal & connect message
    // make sure you send this to the replayer's `webRTCReplayPlugin.signalReceive(signal)`
    sendSignalToReplayer(msg); // example of function that sends the signal to the replayer
  },
});

rrweb.record({
  emit: (event) => {
    // send these events to the `replayer.addEvent(event)`, how you do that is up to you
    // you can send them to a server for example which can then send them to the replayer
    sendEventToReplayer(event); // example of function that sends the event to the replayer
  },
  plugins: [
    // add the plugin to the list of plugins, and initialize it via `.initPlugin()`
    webRTCRecordPlugin.initPlugin(),
  ],
  recordCanvas: false, // we don't want canvas recording turned on, we're going to do that via the plugin
});
```

### Replay Side

```js
// Replay side
import rrweb from 'rrweb';
import { RRWebPluginCanvasWebRTCReplay } from 'rrweb-plugin-canvas-webrtc-replay';

const webRTCReplayPlugin = new RRWebPluginCanvasWebRTCReplay({
  canvasFoundCallback(canvas, context) {
    console.log('canvas', canvas);
    // send the canvas id to `webRTCRecordPlugin.setupStream(id)`, how you do that is up to you
    // you can send them to a server for example which can then send them to the replayer
    sendCanvasIdToRecordScript(context.id); // example of function that sends the id to the record script
  },
  signalSendCallback(signal) {
    // provides webrtc sdp offer signal & connect message
    // make sure you send this to the record script's `webRTCRecordPlugin.signalReceive(signal)`
    sendSignalToRecordScript(signal); // example of function that sends the signal to the record script
  },
});

const replayer = new rrweb.Replayer([], {
  UNSAFE_replayCanvas: true, // turn canvas replay on!
  liveMode: true, // live mode is needed to stream events to the replayer
  plugins: [webRTCReplayPlugin.initPlugin()],
});
replayer.startLive(); // start the replayer in live mode

replayer.addEvent(event); // call this whenever an event is received from the record script
```

## More info

https://github.com/rrweb-io/rrweb/pull/976
npm package: @kenoo/qrcode
Description: qrcode.js binding of vue 2
Author: kenoo
Latest version: 1.0.2
Deprecated: false

## vue-qrcode

> qrcode.js binding of vue 2

### Install

With [Yarn](https://yarnpkg.com):
```bash
yarn add @kenoo/qrcode
```

With npm:
```bash
npm install @kenoo/qrcode --save
```

### Usage
[example](https://wangbinyq.github.io/vue-qrcode.js/test/)

```html
    <qrcode class="qrcode"
      :text="text"
      :size="size"
      :colorLight="colorLight"
      :colorDark="colorDark"
      :logo="'https://avatars0.githubusercontent.com/u/1384521?v=3&s=80'"
      :logoSize="40"
      >
    </qrcode>
```

### License
MIT
npm package: @kenostod/utl-snap
Description: UTL MetaMask Snap v2.0 — Fee X-Ray, FAL™ Flash Arbitrage Alerts, Loyalty Tiers, Governance, Credentials, and passive income from every UTL transaction on BNB Smart Chain.
Author: Kenostod Blockchain Academy
Latest version: 2.0.0

# UTL MetaMask Snap

## Overview

The UTL MetaMask Snap integrates the Universal Transaction Layer directly into MetaMask, enabling users to earn passive income from cross-chain transaction fees without leaving their wallet.

## Features

### Transaction Insights
Every transaction shows a UTL panel displaying:
- Transaction value and UTL fee (0.1%)
- Current tier and multiplier
- Cumulative fees contributed
- Total rewards earned
- Auto-compound status

### RPC Methods

| Method | Description |
|--------|-------------|
| `utl_optIn` | Activate UTL fee redistribution |
| `utl_optOut` | Deactivate UTL participation |
| `utl_dashboard` | View full earnings dashboard |
| `utl_getStats` | Get stats as JSON (for dapps) |
| `utl_updateStake` | Sync KENO stake amount |
| `utl_claimRewards` | Initiate reward claim |
| `utl_toggleAutoCompound` | Toggle auto-restaking |
| `utl_weeklyReport` | Get weekly earnings report |

### Tier System
Based on KENO staked:
- **Observer** (0 KENO): 0.1x multiplier
- **Participant** (1,000 KENO): 1.0x multiplier
- **Advocate** (10,000 KENO): 1.2x multiplier
- **Champion** (100,000 KENO): 1.5x multiplier
- **Guardian** (1,000,000 KENO): 2.0x multiplier

## Development

### Prerequisites
- Node.js 18+
- MetaMask Flask (developer version)

### Setup
```bash
cd utl/metamask-snap
npm install
npm run build
```

### Testing
1. Install MetaMask Flask
2. Run `npm start` for watch mode
3. Open companion dapp at localhost:8000
4. Connect and test snap functions

### Publishing
```bash
npm publish --access public
```
Then request allowlisting from MetaMask team.

## Integration with Companion Dapp

```javascript
// Connect to snap
const snapId = 'npm:@kenostod/utl-snap';

await ethereum.request({
  method: 'wallet_requestSnaps',
  params: { [snapId]: {} }
});

// Opt in
await ethereum.request({
  method: 'wallet_invokeSnap',
  params: {
    snapId,
    request: { method: 'utl_optIn' }
  }
});

// Get stats
const stats = await ethereum.request({
  method: 'wallet_invokeSnap',
  params: {
    snapId,
    request: { method: 'utl_getStats' }
  }
});
```

## Permissions Required
- `snap_dialog` — Show UI panels to user
- `snap_notify` — Push notifications for earnings
- `snap_manageState` — Store user preferences locally
- `endowment:transaction-insight` — Analyze transactions before signing
- `endowment:ethereum-provider` — Interact with blockchain
- `endowment:network-access` — Fetch external data
- `endowment:rpc` — Receive RPC calls from dapps

## License

MIT — Kenostod Blockchain Academy
npm package: @kenote/api-proxy
Description: .
Author: thondery
Latest version: 1.0.53

# @kenote/api-proxy

Automation API proxy module based on the Kenote.js framework.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/api-proxy.svg
[npm-url]: https://www.npmjs.com/package/@kenote/api-proxy
[downloads-image]: https://img.shields.io/npm/dm/@kenote/api-proxy.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/api-proxy
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

```ts
import { Context, Controller, Get, NextHandler, Post } from '@kenote/core'
import { getEntrance, getProxyResponse } from '@kenote/api-proxy'
import * as service from '../service'

@Controller('/')
export default class MainController {

  @Get('/:channel/:pathLabel?/:tag?')
  @Post('/:channel/:pathLabel?/:tag?')
  async handler (ctx: Context, next: NextHandler) {
    let { channel, pathLabel } = ctx.params
    let sandbox: Record<string, unknown> = { service }
    try {
      let { 
        payload, 
        notFound, 
        isUser, 
        entrance, 
        setting, 
        authenticationState, 
        serviceModules 
      } = await getEntrance({ channel, pathLabel, getUser, sandbox })(ctx, 'channels')
      if (notFound) return ctx.status(404)
      if (authenticationState?.type === 'jwt' && isUser === 'Unauthorized') {
        return await ctx.status(401).send('Unauthorized')
      }
      let [ type, result ] = await getProxyResponse(entrance, payload)({ serviceModules, setting, logger: console, ctx })
      if (entrance?.native) {
        ctx.setHeader('content-type', type)
        return ctx.send(result)
      }
      return ctx.json(result)
    } catch (error) {
      if (error?.code >= 1000) {
        ctx.json({ error: error.message })
      }
      else {
        return next(error)
      }
    }
  }
}
```

---
MIT License.
npm package: @kenote/common
Description: Based on @kenote common methods and types.
Author: thondery
Latest version: 1.0.51

# @kenote/common

Based on `@kenote` common methods and types.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/common.svg
[npm-url]: https://www.npmjs.com/package/@kenote/common
[downloads-image]: https://img.shields.io/npm/dm/@kenote/common.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/common
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## CommonEngine

```ts
import { CommonEngine } from '@kenote/common'
import express, { Express } from 'express'
import { RequestListener } from 'http'

export class ServiceEngine extends CommonEngine<Express> {

  constructor (options?: any) {
    super()
    this.__application = express()
  }

  get name (): string {
    return 'express'
  }

  get server (): RequestListener {
    return this.__application
  }
}
```

## HttpClient

```ts
import { HttpClient, xhrClient } from '@kenote/common'

// Axios
const client: ClientInstance = axios
// XMLHttpRequest
const client: ClientInstance = xhrClient(new XMLHttpRequest())

const httpClient = (options?: HeaderOptions) => new HttpClient(client, options)

async function start () {
  // Send Get
  await httpClient().get(url, params)
  // Send Post
  await httpClient().post(url, body)
  // Download
  await httpClient().download(url)
  // Upload
  await httpClient().upload(url)
}
```

## DataNodeProxy

```ts
import { dataNodeProxy, CommonDataNode } from '@kenote/common'

const data: CommonDataNode[] = [
  {
    key: '1',
    name: 'home'
  }
]

const dataProxy = dataNodeProxy(data)
// Find Single Node
let node = dataProxy.find({ name: 'home' })
console.log( node )
// Add Single Node
dataProxy.add(null, { key: '2', name: 'aaa' })
dataProxy.add('1', { key: '3', name: 'bbb' })
// Update Single Node
dataProxy.update('1', { name: 'ccc' })
// Remove Single Node
dataProxy.remove('1')
// Get Changed Data
console.log( dataProxy.data )
```

---
MIT License.
npm package: @kenote/config
Description: Get profile module.
Author: thondery
Latest version: 1.0.40

# @kenote/config

Get profile module

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/config.svg
[npm-url]: https://www.npmjs.com/package/@kenote/config
[downloads-image]: https://img.shields.io/npm/dm/@kenote/config.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/config
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## 使用方法

`data/config.yaml`
```yaml
host: localhost

port: 3000

site_name: 站点名称

redis:
  host: 127.0.0.1
  port: 6379
  db: 0
```

`data/index.js`
```js
module.exports = {
  a: 1
}
```

`app.ts`
```ts
import { loadConfig, asyncRequire } from '@kenote/config'

/**
 * 读取配置文件
 */
const config = loadConfig('data')
/**
 * 异步导入JS
 */
const ct = asyncRequire('./data')
```

---
MIT License.
npm package: @kenote/core
Description: The core library of the Kenote.js.
Author: thondery
Latest version: 1.0.47

# @kenote/core

The core library of the Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/core.svg
[npm-url]: https://www.npmjs.com/package/@kenote/core
[downloads-image]: https://img.shields.io/npm/dm/@kenote/core.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/core
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/koa'

@Module({
  imports: [],
  plugins: [],
  middlewares: [],
  httpException: {
    notFound: (ctx: Context) => {
      return ctx.status(404)
    },
    exception: (err: any, ctx: Context) => {
      ctx.renderException('error', { message: 'This page could internal server error' })
    }
  }
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

### Controller

```ts
import { Context, Controller, Get, NextHandler, Post } from '@kenote/core'


@Controller()
class MainController {

  @Get('/path')
  async handle (ctx: Context, next: NextHandler) {
    // ...
  }

  @Post('/path')
  async handle (ctx: Context, next: NextHandler) {
    // ...
  }

  @Put('/path')
  async handle (ctx: Context, next: NextHandler) {
    // ...
  }

  @Delete('/path')
  async handle (ctx: Context, next: NextHandler) {
    // ...
  }
}
```

### Middleware

```ts
import { Middleware, Action, Context, Property } from '@kenote/core'
import { HttpError } from 'http-errors'

const service = {
  // ...
}

@Middleware()
class Restful {

  @Action()
  api (ctx: Context) {
    return (data: any, error?: HttpError) => {
      if (error != null) {
        let { message } = error
        ctx.json({ error: message })
      } else {
        ctx.json({ data })
      }
    }
  }

  @Property()
  service (ctx: Context) {
    return service
  }
}

declare module '@kenote/core' {
  interface Context {

    api (data: any, error?: HttpError): void
    
    service: typeof service
  }
}
```


---
MIT License.
npm package: @kenote/express
Description: Using Express web framework to Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/express

Using Express web framework to Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/express.svg
[npm-url]: https://www.npmjs.com/package/@kenote/express
[downloads-image]: https://img.shields.io/npm/dm/@kenote/express.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/express
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/express'

@Module({
  imports: [],
  plugins: [],
  middlewares: [],
  httpException: {
    notFound: (ctx: Context) => {
      return ctx.status(404)
    },
    exception: (err: any, ctx: Context) => {
      ctx.renderException('error', { message: 'This page could internal server error' })
    }
  }
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/express-passport
Description: Passport plug-in based on Express for Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/express-passport

Passport plug-in based on Express for Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/express-passport.svg
[npm-url]: https://www.npmjs.com/package/@kenote/express-passport
[downloads-image]: https://img.shields.io/npm/dm/@kenote/express-passport.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/express-passport
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts

import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/express'
import session from '@kenote/express-session'
import { MemoryStore } from 'express-session'
import passportPlugin from '@kenote/express-passport'
import passport from 'passport'
import { Strategy } from 'passport-local'

// Add Strategy
passport.use(new Strategy(
  (username, password, done) => {
    return done(null, { username })
  }
))

@Module({
  imports: [],
  plugins: [
    session({
      secret: 'secret name',
      store: new MemoryStore(),
      resave: true,
      saveUninitialized: true
    }),
    passportPlugin()
  ],
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/express-session
Description: Session plug-in based on Express for Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/express-session

Session plug-in based on Express for Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/express-session.svg
[npm-url]: https://www.npmjs.com/package/@kenote/express-session
[downloads-image]: https://img.shields.io/npm/dm/@kenote/express-session.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/express-session
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/express'
import session from '@kenote/express-session'
import { MemoryStore } from 'express-session'

@Module({
  imports: [],
  plugins: [
    session({
      secret: 'secret name',
      store: new MemoryStore(),
      resave: true,
      saveUninitialized: true
    })
  ],
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/koa
Description: Using Koa web framework to Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/koa

Using Koa web framework to Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/koa.svg
[npm-url]: https://www.npmjs.com/package/@kenote/koa
[downloads-image]: https://img.shields.io/npm/dm/@kenote/koa.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/koa
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/koa'

@Module({
  imports: [],
  plugins: [],
  middlewares: [],
  httpException: {
    notFound: (ctx: Context) => {
      return ctx.status(404)
    },
    exception: (err: any, ctx: Context) => {
      ctx.renderException('error', { message: 'This page could internal server error' })
    }
  }
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/koa-passport
Description: Passport plug-in based on Koa for Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/koa-passport

Passport plug-in based on Koa for Kenote.js.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/koa-passport.svg
[npm-url]: https://www.npmjs.com/package/@kenote/koa-passport
[downloads-image]: https://img.shields.io/npm/dm/@kenote/koa-passport.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/koa-passport
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/koa'
import session from '@kenote/koa-session'
import redisStore from 'koa-redis'
import passportPlugin from '@kenote/koa-passport'
import passport from 'koa-passport'
import { Strategy } from 'passport-local'

// Add Strategy
passport.use(new Strategy(
  (username, password, done) => {
    return done(null, { username })
  }
))

@Module({
  imports: [],
  plugins: [
    session({
      store: redisStore(),
    }),
    passportPlugin()
  ],
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/koa-session
Description: Session plug-in based on Koa for Kenote.js.
Author: thondery
Latest version: 1.0.32

# @kenote/koa-session

Session plug-in based on Koa for Kenote.js.


[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/koa-session.svg
[npm-url]: https://www.npmjs.com/package/@kenote/koa-session
[downloads-image]: https://img.shields.io/npm/dm/@kenote/koa-session.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/koa-session
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Usage

`index.ts`
```ts
import { Module, ServerFactory } from '@kenote/core'
import { ServiceEngine } from '@kenote/koa'
import session from '@kenote/koa-session'
import redisStore from 'koa-redis'

@Module({
  imports: [],
  plugins: [
    session({
      store: redisStore(),
    })
  ],
})
class AppModule {}

async bootstarp () {
  let factory = await ServerFactory(new ServiceEngine()).create(AppModule)
  factory.server.listen(4000)
}
```

---
MIT License.
npm package: @kenote/mailer
Description: Auxiliary tool for NodeMailer.
Author: thondery
Latest version: 1.0.32

# @kenote/mailer

Auxiliary tool for NodeMailer.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/mailer.svg
[npm-url]: https://www.npmjs.com/package/@kenote/mailer
[downloads-image]: https://img.shields.io/npm/dm/@kenote/mailer.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/mailer
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## 使用方法
```ts
import { Mailer } from '@kenote/mailer'
import { renderString } from 'nunjucks'

const mailer = new Mailer({
  // SMTP 选项
  smtpOptions: {
    host: 'smtp.ethereal.email',
    port: 587,
    auth: {
      user: 'penelope.leuschke41@ethereal.email',
      pass: 'aPxRSFBXbM7dseEwKK'
    }
  },
  // 邮件模版目录
  mailDir: path.resolve(process.cwd(), 'mails'),
  // 渲染模版函数
  renderString
})

const mail = {
  from: 'penelope.leuschke41@ethereal.email',
  to: 'penelope.leuschke41@ethereal.email',
  subject: 'Ethereal Email',
}

const context = {
  site_name: 'Kenote',
  username: 'thondery',
  email_verify_url: 'http://localhost:8080'
}

// 发送邮件
mailer.asyncSend(mail)
// 发送模版邮件
mailer.sendMail('email_verify.mjml', context)(mail)
```

---
MIT License.
npm package: @kenote/mongoose
Description: Auxiliary tool for Mongoose.
Author: thondery
Latest version: 1.0.40

# @kenote/mongoose

Auxiliary tool for Mongoose. 

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/mongoose.svg
[npm-url]: https://www.npmjs.com/package/@kenote/mongoose
[downloads-image]: https://img.shields.io/npm/dm/@kenote/mongoose.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/mongoose
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## 使用方法

```ts
import { model, Schema } from 'mongoose'
import { modelDao } from '@kenote/mongoose'

const userModel = model('user', new Schema({
  id: {
    type: Number,
    default: 0,
    index: { unique: true }
  },
  username: {
    type: String,
    required: true
  }
}))

modelDao(userModel, {
  select: ['username'],
  populate: {
    path: ''
  },
  sort: { _id: 1 },
  limit: 10
})

```

---
MIT License.
npm package: @kenote/protobuf
Description: Client sending protobuf data through socket.
Author: thondery
Latest version: 1.0.32

# @kenote/protobuf

Client sending protobuf data through socket.

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/protobuf.svg
[npm-url]: https://www.npmjs.com/package/@kenote/protobuf
[downloads-image]: https://img.shields.io/npm/dm/@kenote/protobuf.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/protobuf
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Examples

`Node.js` 端用法
```ts
import { Protobuf, TCPSocket } from '@kenote/protobuf'

const options: Protobuf.Configure = {
  // 文件目录
  path: './pb',
  // 入口文件
  socket: 'socket.proto',
  // 编码设置
  encode: {
    // 消息类型
    type: 'MSG_REQUEST_BASE',
    // 字段默认值
    fields: {},
    // 消息编号映射路径
    msgtype: 'msgtype',
    // 消息参数映射路径
    payload: 'payload'
  },
  // 解码设置
  decode: {
    // 消息类型
    type: 'MSG_RESPONSE_BASE',
    // 字段解码相关类型
    fields: {}
  },
  // 默认请求消息类型
  requestType: 'MSG_RESPONSE_PAYLOAD'
}

// 创建示例对象
const protobuf = new Protobuf(options)

// 对消息进行编码
const buffer = protobuf.encode(1000, { ... })

// 解码返回数据
const data = protobuf.decode(buffer.slice(4))

// 与 TCP Socket 并行用法
async function bootstrap () {
  let config: TCPSocket.Configure = {
    // 主机
    host: '0.0.0.0',
    // 端口
    port: 8080,
    // 设置 ProtoBuffer
    protobuf: options
  }
  try {
    // 创建客户端
    let client = new TCPSocket(config)
    // 发送请求数据并进行编/解码，完成后自动关闭连接
    let result = await client.encode(1000, { ... }).send(true)
    console.log(result)
  } catch (error) {
    console.error(error.message)
  }
}
```

浏览器端使用

1. 先转换 proto 文件

```bash
# 将 proto 文件转为 js
pbjs -t static-module -w commonjs -o socket.js socket.proto
# 根据 js 生成 ts 类型
pbts -o socket.d.ts socket.js
```

2. 使用 ts

```ts
import { Browser } from '@kenote/protobuf'
import PBSocket from './socket'

const options: Browser.Configure<typeof PBSocket> = {
  // 接入protobuf的TS类型
  socket: PBSocket,
  // 编码设置
  encode: {
    // 消息类型
    type: 'com.socket.MSG_REQUEST_BASE',
    // 字段默认值
    fields: {},
    // 消息编号映射路径
    msgtype: 'msgtype',
    // 消息参数映射路径
    payload: 'payload'
  },
  // 解码设置
  decode: {
    // 消息类型
    type: 'com.socket.MSG_RESPONSE_BASE',
    // 字段解码相关类型
    fields: {}
  },
  // 默认请求消息类型
  requestType: 'com.socket.MSG_RESPONSE_PAYLOAD'
}

// 创建示例对象
const protobuf = new Browser(options)

// 对消息进行编码
const buffer = protobuf.encode(1000, { ... })

// 将 Buffer 转为 ArrayBuffer
const arrayBuffer = new Uint8Array(buffer.slice(4)).buffer

// 解码返回数据
const data = protobuf.decode(buffer)
```

---
MIT License.
npm package: @kenote/upload
Description: Upload module for HTTP Server.
Author: thondery
Latest version: 1.0.32

# @kenote/upload

Upload module for HTTP Server. 

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Gratipay][licensed-image]][licensed-url]

[npm-image]: https://img.shields.io/npm/v/@kenote/upload.svg
[npm-url]: https://www.npmjs.com/package/@kenote/upload
[downloads-image]: https://img.shields.io/npm/dm/@kenote/upload.svg
[downloads-url]: https://www.npmjs.com/package/@kenote/upload
[licensed-image]: https://img.shields.io/badge/license-MIT-blue.svg
[licensed-url]: https://github.com/kenote/kenote.js/blob/main/LICENSE

## Examples

```ts
import express from 'express'
import bodyParser from 'body-parser'
import { uploadStore, putStream } from '@kenote/upload'

const config = {
  max_limit: '4mb',
  urlprefix: 'http://localhost:4000/uploadfiles',
  root_dir: 'uploadfiles',
  original_name: true,
  errors: {
    limit: 301,
    mimetype: 302
  }
}

function ErrorInfo (code: number, opts: string[]) {
  return {
    code,
    message: opts.join(',')
  }
}

const app = express()
app.use(bodyParser.json({ limit: '1mb' }))
app.use(bodyParser.urlencoded({ extended: true, limit: '1mb' }))

app.post('/upload', async (req, res, next) => {
  try {
    let store = uploadStore(options, req)
    let result = await store.upload(putStream, ErrorInfo)
    return res.json(result)
  } catch (error) {
    return next(error)
  }
})

app.listen(4000)
```

---
MIT License.