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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tmsfe/tms-cloud-sdk

v0.0.6

Published

[TOC]

Downloads

10

Readme

@tmsfe/tms-cloud-sdk

[TOC]


Thoughts

云开发提供了完整的一套服务端能力,可以让我们快速开发服务端业务逻辑而不用关注运维部署的细节。在过往的项目中,已经有一些典型的应用场景。

但是在云函数的开发和发布环节,还是有不少痛点,tms-cloud-sdk致力于解决云函数开发环节的痛点。部署环节的痛点另行方案解决,不在此讨论。

下面列举大家日常云开发联调过程中反馈的问题。我们围绕这些问题来封装公共能力。


重复且模板化的云函数框架初始代码

在每个云函数初始化时,都会存在类似的代码:

const TcbRouter = require('tcb-router');
const cloud = require('wx-server-sdk');

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
const getWxContext = () => {
  const wxContext = cloud.getWXContext();

  return {
    openId: wxContext.OPENID,
    appId: wxContext.APPID,
    unionId: wxContext.UNIONID,
  };
};

// 云函数入口函数
exports.main = async (event) => {
  const app = new TcbRouter({ event });
  app.use(async (ctx, next) => {
    // 统一参数处理
    const { openId } = cloud.getWXContext()();
    const { event } = ctx._req; // eslint-disable-line
    Object.assign(ctx, { data: {
      openId,
      ...event,
    } });
    try {
      const resData = await next();
      Object.assign(ctx, { body: { errCode: 0, errMsg: 'success', resData } });
    } catch (e) {
      // 统一异常处理
      const { errCode, errMsg } = e;
      Object.assign(ctx, { body: { errCode, errMsg, resData: null } });
    }
  });

  app.router('xxx/xxx', () => {}); // 路由注册
  return app.serve();
};

分析这段代码,不同云函数之间有差异的只是路由注册的部分,参数预处理的中间件完全可以复用。

我们也有必要统一所有云函数的基础中间件,以实现日志打印的标准化;之前遇到部分云函数日志打印不全,需要排查时无从查起的尴尬场面;如果我们将日志打印标准化在基础中间件里,就可以避免此类问题。


海报图开发调试效率低下

很多时候我们需要绘制一张动态的还报图片,有很多云函数有写过这个逻辑,现在也有一个 canvasImg 的云函数来画图;其思路是在Node端用canvas画图,然后将canvas保存成图片。这种实现思路,开发联调的效率必然不高。

我们没有现成的可视化canvas画图工具,只能边改边发布云函数来调试,且此方案依赖的node-canvas包,在云函数环境无法正常安装,本地和云端需要兼容不同的node_modules依赖,见云函数中特殊npm包的分层解决方案

换个思路,如果我们不去画canvas,而是去写HTML页面,这样本地就可以快速完成复杂视觉的HTML开发,云函数要做的只是将这个HTML渲染,保存成图片即可。且云函数环境已默认集成 puppeteer 包,不存在依赖安装问题。

按照这个思路,我们在tms-cloud-sdk中封装了画图的公共方法,拿来即用。


生成小程序码还要依赖后端

云函数中可以免鉴权调用微信的开放接口,直接生成小程序码,在一些业务场景需要生成动态小程序码让用户分享,前端可自己完成。

我们在tms-cloud-sdk中封装了生成小程序码的接口,在微信开放能力的基础上做了扩展,支持上传到云存储或转base64,方便大家拿来即用。


内容安全检测不能拿来即用

云函数中可以免鉴权调用微信的内容安全检测接口,但接口需要传很多定制参数,需要了解上下文背景。我们对这个接口做了一层封装,使用时只需传要检测的内容即可。


Documentation

serve 云函数初始化

serve方法是tms-cloud-sdk提供的云函数入口高阶函数,业务只需传入路由表和自定义中间件即可。serve方法中封装了统一的参数预处理,包括对不同调用方(小程序端、定时任务、微信回调、HTTP访问)的入参标准化。

同时,serve方法统一增加了云函数出入参的日志打印中间件。


参数

Object routes

路由表,Object类型,key为路由路径,value为处理函数

Array middleware

自定义中间件,Array类型,每一项为独立中间件函数


返回值

Function fn

返回云函数入口函数,可以直接用于云函数初始化。


示例代码

const tmsCloud = require('@tmsfe/tms-cloud-sdk');

const routes = {
  'testfn/testroute': (ctx) => console.log(ctx),
};

const middleware = [async (ctx, next) => {
  tmsCloud.logger.info(ctx);
  return await next();
}];

exports.main = tmsCloud.serve(routes, middleware);

html2img 将HTML渲染为图片

顾名思义,将html渲染成图片,适用于动态生成海报图、分享图等业务场景。

此方法是对 puppeteer 的二次封装,拓展了对图片文件的处理,可以拿来即用。


性能优化提示:

云函数运行时环境内置了 puppeteer, 我们的实现思路是用 puppeteerheadless 模式下打开要绘制的html页面,然后调用 screenshot 方法截图。

在这个过程中,初始化 puppeteer 实例需要时间,加载html页面需要时间,截图也需要时间,尤其是加载html页面,这个过程的耗时取决于html中加载的资源体量。如果在页面中使用了大量网络资源(图片、css)等时,加载耗时会明显增加。

因此建议在html中严格控制使用的网络资源,尽可能用 base64 的方式嵌入在html中。

在绘制图片时,难免会用到一些特殊字体,我们已经将常用的字体以css文件的形式存放在cdn上,在html中可以直接用link标签引用。 如有其他字体包定制需求,请参照下面的base64字体css文件,或联系petegao协助处理。

<!--腾讯体W3-->
<link rel="stylesheet" href="https://static.img.tai.qq.com/web/fonts/TencentSans-W3.css">
<!--腾讯体W7-->
<link rel="stylesheet" href="https://static.img.tai.qq.com/web/fonts/TencentSans-W3.css">
<!--苹果平方标准体-->
<link rel="stylesheet" href="https://static.img.tai.qq.com/web/fonts/PingFang-Normal.css">
<!--DIN-Alternate-->
<link rel="stylesheet" href="https://static.img.tai.qq.com/web/fonts/DIN-Alternate.css">

参数

Object options

绘图配置

| 属性 | 类型 | 默认值 | 必填 | 说明 | | ----------- | -------|----- |-----| ---- | | output | string | |否 |生成图片的云函数本地路径,只需指定目录路径,文件名自动生成;为空时不保存本地文件| | cloudOutput | string | |否 |生成图片的云存储路径,只需指定云存储目录路径,文件名自动生成;为空时不存储| | html | string | |是|要渲染的html内容,支持本地html文件路径、云存储fileID、网络https文件路径、或直接传html字符串| | content | string | |否|handlebars模板内容,传入后将把html视为handlebars模板来渲染| | transparent | boolean | false |否|绘制的图片是否透明背景| | encoding | string | binary | 否 |绘制图片的编码格式,支持 binary/base64, 默认为binary| | selector | string |body |否|要绘制的元素,默认是body,可以通过css选择器标识要绘制的元素| | type | string | png|否|生成图片的文件类型,jpeg/png,默认为png|


返回值

Object rsp

| 属性 | 类型 | 说明 | | ----------- | -------| ---- | | localPath | string |生成图片的云函数本地路径,入参传入output时有效| | fileContent | binary/base64 |生成的图片内容,内容格式为binary/base64,取决于入参的encoding| | encoding | string |与入参的encoding相同| | fileID | string |云存储文件ID,当入参传cloudOutput时有效| | tempFileURL | string |云存储文件http访问链接,当入参传cloudOutput时有效|


示例代码

const tmsCloud = require('@tmsfe/tms-cloud-sdk');

const routes = {
  'testfn/drawimg': async () => {
    const html = `
      <!DOCTYPE html>
      <html>
      <head>
      <style>
      #myHeader {
        background-color: lightblue;
        color: black;
        padding: 40px;
        text-align: center;
      } 
      </style>
      </head>
      <body>

      <h2>{{title}}</h2>
      <p>{{desc}}</p>

      <h1 id="myHeader">My Header</h1>

      </body>
      </html>
    `;
    const { tempFileURL } = await tmsCloud.html2img({
      html,
      content: {
        title: 'Yehuda',
        desc: 'Katz',
      }
      cloudOutput: 'testfn/',
    });
    return { tempFileURL };
  },
};

exports.main = tmsCloud.serve(routes);

callSinanServer 在云函数中调用SinanServer

在云函数中以L5的方式调用接入层SinanServer。

注意调用此方法的云函数必须是由微信环境(小程序调用/定时任务调用)触发,否则会提示微信cloudApiToken错误。


参数

String path

要请求的接口路径

Object param

要携带的参数,注意必须携带userId、token、wxAppId、seqId这几个公共参数,这些参数小程序里通过 tms.callCloudFunc 调用云函数时都有,直接透传即可。

String method

请求方法,支持 get/post

String env

请求的SinanServer环境,支持 test/production,分别对应SinanServer测试/生产环境


返回值

Object rsp

| 属性 | 类型 | 说明 | | ----------- | -------| ---- | | errCode | string |接口错误码| |errMsg | string |接口错误信息描述| | resData | object |业务数据|


示例代码

const tmsCloud = require('@tmsfe/tms-cloud-sdk');

const routes = {
  'testfn/callsinan': async (ctx) => {
    const { userId, token, seqId, wxAppId } = ctx.event;
    const res = await tmsCloud.callSinanServer(
      'user/carlist',
      { userId, token, seqId, wxAppId },
      'post',
      'production'
    );
    return res;
  },
};

exports.main = tmsCloud.serve(routes);

getAppCode 生成小程序码

在云函数中生成小程序码。

此方法是对微信开放能力 cloud.openapi.wxacode.getUnlimited 的二次封装,拓展了对小程序码图片文件的处理,可以拿来即用。

注意调用此方法的云函数必须是由微信环境(小程序调用/定时任务调用)触发,否则会提示微信cloudApiToken错误。


参数

Object config

生成小程序码的配置

| 属性 | 类型 | 默认值 | 必填 | 说明 | | ----------- | -------|----- |-----| ---- | | page | string | |否 |页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面| | scene | string | |否 |query参数,会拼在page后,在扫码打开的页面onLoad可以拿到。最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)| | checkPath | boolean | true | 否 |检查 page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但 page 有数量上限(60000个)请勿滥用| | envVersion | string | release | 否 |要打开的小程序版本。正式版为 release,体验版为 trial,开发版为 develop| | width | number | | 否 |二维码的宽度,单位 px,最小 280px,最大 1280px| | autoColor | boolean | | 否 |自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false| | lineColor | object | | 否 |autoColor 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示| | isHyaline | boolean | false | 否 |是否需要透明底色,为 true 时,生成透明底色的小程序| | saveToCloud | boolean | false | 否 |是否包存到云存储,默认false,传true时将自动上传至云存储,并返回文件ID与http访问链接|


返回值

Object rsp

| 属性 | 类型 | 说明 | | ----------- | -------| ---- | | contentType | string |小程序码图片类型,png/jpeg| |buffer | buffer |小程序码图片文件流| | string64 | string |小程序码base64字符串,可直接用于 image 标签 src 展示 | | fileID | string |云存储文件ID,当入参saveToCloud为true时有效,可直接用于 image 标签 src 展示 | | tempFileURL | string |云存储文件http访问链接 |


示例代码

const tmsCloud = require('@tmsfe/tms-cloud-sdk');

const routes = {
  'testfn/wxacode': async () => {
    const { tempFileURL, fileID, string64 } = await tmsCloud.getAppCode({
      page: 'modules/car/index/index',
      scene: 'wecarId=xxxx',
      checkPath: true,
      envVersion: 'release',
      saveToCloud: true,
    });
    return { tempFileURL, fileID, string64 };
  },
};

exports.main = tmsCloud.serve(routes);

msgSecCheck 文本内容安全检测

检查一段文本是否含有违法违规内容。

此方法是对 cloud.openapi.security.msgSecCheck 的封装,简化了调用参数。

注意调用此方法的云函数必须是由微信环境(小程序调用/定时任务调用)触发,否则会提示微信cloudApiToken错误。


参数

String openid

用户的openid,可以从云函数请求上下文中获取

String content

需检测的文本内容,文本字数的上限为2500字,需使用UTF-8编码


返回值

Object result

| 属性 | 类型 | 说明 | | ----------- | -------| ---- | | label | number |命中标签枚举值,100 正常;10001 广告;20001 时政;20002 色情;20003 辱骂;20006 违法犯罪;20008 欺诈;20012 低俗;20013 版权;21000 其他| |suggest | string |建议,有risky、pass、review三种值|


示例代码

const tmsCloud = require('@tmsfe/tms-cloud-sdk');

const routes = {
  'testfn/msgcheck': async (ctx) => {
    const { OPENID } = ctx.wx_context;
    const { label, suggest } = await tmsCloud.msgSecCheck(OPENID, 'xxxxx');
    return { label, suggest };
  },
};

exports.main = tmsCloud.serve(routes);

cloud

require('@tmsfe/tms-cloud-sdk').cloud

等价于

require('wx-server-sdk').cloud

logger

require('@tmsfe/tms-cloud-sdk').logger

等价于

require('wx-server-sdk').cloud.logger()

Contributing

在日常云开发过程中,肯定还有很多痛点,大家有想法欢迎随时提出需求,当然如果大家能协同共建,贡献代码,自然是最好的。