@cloudbase/cloud-api

The cloud api request package.

Usage no npm install needed!

<script type="module">
  import cloudbaseCloudApi from 'https://cdn.skypack.dev/@cloudbase/cloud-api';
</script>

README

@cloudbase/cloud-api

云 API 3.0 请求封装,仅适用于 Node。

调用云API

支持 API 秘钥或临时秘钥鉴权。

import { CloudApiService } from '@cloudbase/cloud-api'

const service = new CloudApiService({
    service: 'tcb',
    credential: {
        secretId: 'xxx',
        secretKey: 'xxx',
        token: 'xxx'
    }
})

service.request('DescribeEnvs').then(console.log)
// 或
service
    .request({
        action: DescribeEnvs
    })
    .then(console.log)

const { CloudApiService } = require('@cloudbase/cloud-api')

const service = new CloudApiService({
    service: 'tcb',
    credential: {
        secretId: 'xxx',
        secretKey: 'xxx'
    }
})

service.request('DescribeEnvs').then(console.log)

结果

{
  EnvList: [],
  RequestId: '09a1ece6-7cb1-4a8f-b8b6-e4cc066d1fbe'
}

异步 credential

在某些情况下,你的 credential 可能是异步获取。你可以配置 getCredential 方法,异步传递 credential 信息。建议结合 getInstance() 方法使用,避免重复请求获取 credential 信息。

const tcbService = CloudApiService.getInstance({
    service: 'tcb',
    getCredential: async () => {
        // 你的异步逻辑
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve({})
            }, 1000)
        })
    }
})

const res = await tcbService.request('DescribeEnvs')

request()

定义:async request(action: string, data: Record<string, any> = {}, method: 'POST' | 'GET' = 'POST')

使用 request 方法发起请求。

getInstance()

getInstance() 静态方法内部是一个工厂函数,会根据服务类型缓存实例,能有效避免重复初始化实例带来的开销

const tcbService = CloudApiService.getInstance({
    credential,
    service: 'tcb'
})

const res = await tcbService.request('DescribeEnvs', {
    empty: null,
    b: undefined
})

清除内存中的 credential 缓存

在某些特殊的情况下,你可能需要在不退出进程的情况下重载 credential。你可以使用 clearCredentialCache() 方法清除内存中的 credential 缓存,使得下次请求前通过 getCredential 函数重新获取 credential

const tcbService = new CloudApiService({
    service: 'tcb',
    getCredential: () => {
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve(credential)
            }, 1000)
        })
    }
})

const res = await tcbService.request('DescribeEnvs')

tcbService.clearCredentialCache()

// 重新加载 credential
const res = await tcbService.request('DescribeEnvs')

选项

下面是 TS 定义

interface ServiceOptions {
    // 服务名,如 tcb scf
    service: string
    // 服务版本,如 2018-06-14
    version?: string
    // http 请求代理,如 http://127.0.0.1:1235
    // 需要准确声明,本 SDK 不会自动解析 proxy
    proxy?: string
    // 超时时间,毫秒
    timeout?: number
    // 基本参数,会被拼接到请求参数中
    baseParams?: Record<string, any>
    // 身份信息
    credential?: Credential
    // 获取身份信息的函数
    getCredential?: () => Promise<Credential> | Credential
}

interface Credential {
    secretId: string
    secretKey: string
    token?: string
}

调用weda后端

import { wedaRequest } from '@cloudbase/cloud-api'

// 使用示例
wedaRequest({
  action: 'DescribeWedaUserId',
  credentials: {
    secretId: 'xxx',
    secretKey: 'xxxx',
    sessionToken: 'xxxxxx',
  },
  /** 环境ID */
  envId: 'xxx-xxxx',
  /**
   * 调用的weda环境类型
   *  预览-pre,正式-prod
   */
  envType: 'pre',
  /** 用户ID */
  uid: 'xxxxxx',
  /** 
   * uid 类型, 1.tcb 2.微信 3.企业微信 4.weda内部
   */
  uidSource: 1
}).then(res => console.log(res))

// 方法定义, 返回原云API Response 内容
wedaRequest(params: IWedaRequestParams, config?: Partial<IWedaConfig>): Promise<any>

/**
 * 请求参数
 */
export interface IWedaRequestParams {
  /** 请求方法 */
  action: string;
  /**
   * 认证信息
   *  在tcb云函数中可通过 tcb.getCloudbaseContext 返回的环境变量获取相关信息:
   *    TENCENTCLOUD_SECRETID
   *    TENCENTCLOUD_SECRETKEY
   *    TENCENTCLOUD_SESSIONTOKEN
   */
  credentials: ICredentials | (() => Promise<ICredentials>)
  /**
   * 环境ID
   *    在tcb云函数中可通过 tcb.getCloudbaseContext(context) 返回的环境变量 TCB_ENV 获取
   */
  envId: string;
  /**
   * 客户端IP地址, 方便后端进行统计, 无可不传
   *  在tcb云函数中可通过 tcb.getCloudbaseContext 返回的 WX_CLIENTIP(微信侧) TCB_SOURCE_IP(云开发侧)拿到客户端IP地址
   *  详细文档 https://docs.cloudbase.net/api-reference/server/node-sdk/env.html#getcloudbasecontext
   */
  clientIp?: string
  /**
   * 自定义请求ID, 方便前后端调试, 无可不传
   *  在tcb 云函数中, 若可以保证前端一次云函数调用, 只向weda后端发起一次请求, 这可以通过 tcb.parseContext 拿到云函数的请求 request_id 并复用该ID
   *    若不能保证上述条件, 则不要复用云函数请求ID, 否则导致请求链路出问题难以定位
   *  详细文档 https://docs.cloudbase.net/api-reference/server/node-sdk/env.html#parsecontext
   */
  requestId?: string
  /**
   * 调用的weda环境类型
   *  预览-pre,正式-prod
   */
  envType: 'pre' | 'prod'
  /**
   * 用户ID
   *    在tcb 云函数中获取 uid/uidSource 的方法可参考下边的函数 getUserSource
   */
  uid: string;
  /** 
   * uid 类型, 1.tcb 2.微信 3.企业微信 4.weda内部
   */
  source: 1 | 2 | 3 | 4
  /**
   * 方法的其他参数
   */
  data?: Record<string, any>
}

interface IWedaConfig {
  /** 请求的接口地址, 默认 'https://gateway.weda.tencent-cloud.com/wedaapi' */
  url: string
  /**
   * 请求目标, 与 url 意义类似, 但可通过设置为 prod/pre 来指定地址, 优先使用 target
   * 可以是下边三个值
   *  'prod' 正式地址
   *  'pre' 预发地址
   *  'demo' 体验地址 
   *  url 任意一个url
   */
  target?: string
  /** 请求方法, 默认 POST */
  method: string
  /** 额外的自定义头 */
  headers?: Record<string, any>
  /** 自定义http代理地址 */
  proxy?: string
}

interface ICredentials {
  secretId: string
  secretKey: string
  sessionToken: string
}

在tcb云函数中获取uid及uidSource

/** 获取用户来源信息 */
export function getUserSource(context) {
  //  context 为tcb云函数的入口函数接收的 context, 必须传递该参数, 否则解析不到用户ID相关信息
  const envInfo = tcb.getCloudbaseContext(context);
  // @ts-ignore
  const openId: string | undefined = envInfo.WX_FROM_OPENID || envInfo.WX_OPENID;
  const uid = envInfo.TCB_UUID;
  if (!openId && !uid) {
    return;
  }
  return {
    /** uid 类型
     * 1.tcb 2.微信 3.企业微信 4.weda内部
     */
    source: openId ? 2 : 1,
    uid: openId || uid,
  };
}

调试

调试时, 可以通过在环境变量中增加 NODE_DEBUG=weda-request 来打印出详细的冗余日志