ith5cn 1 mesiac pred
commit
173d1b434a

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+tab_width = 4

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+.idea
+.DS_Store
+node_modules
+
+/dist

+ 57 - 0
README.md

@@ -0,0 +1,57 @@
+## 项目安装
+```
+npm install
+```
+
+### 编辑版本
+```
+package.json
+sdk.js
+```
+
+### 编译压缩代码(开发环境)
+
+```
+// 普通是这个
+npm run dev
+
+// 天穹SDK-硬核渠道小游戏, 需要的是这个
+npm run dev:tq
+```
+
+### 编译压缩代码(生产环境)
+```
+// 普通是这个
+npm run build
+
+// 天穹SDK-硬核渠道小游戏, 需要的是这个
+npm run build:tq
+```
+
+
+### sdk使用文档(例子参考game.js)
+
+```
+import {
+  init,
+  loginUserInfo,
+  dataReport,
+  makePayment,
+  shareAppMessage,
+  payConfig,
+  navigateToMiniProgram,
+  getBindPhoneCode,
+  bindPhone,
+  onShareAppMessage,
+  requestSubscribeMessage,
+  triggerSubscribe
+} from 'dist/rywxwsdk.1.0.0.js'
+
+// 初始化skd
+await init({
+    app_version: "1.0.0",
+    config_id: "ttce36b88b51081cb507",
+    game_name: "头条小游戏",
+});
+
+```

+ 27 - 0
config/api.js

@@ -0,0 +1,27 @@
+// 生产环境接口地址
+const API_BASE = "https://app.hainanruiyu.cn/api/wxxyx";
+const REPORT_API_BASE = "https://tj.hainanruiyu.cn/api";
+const WX_API_BASE = "https://app.hainanruiyu.cn/api";
+// const IPV4_API_BASE = 'https://getipaddrv4.test.com'
+// const IPV6_API_BASE = 'https://getipaddrv6.test.com'
+
+//广告暂时废弃,后端传
+// const AD_BASE = 'https://adnotify.test.com/mvc/web/index.php'
+
+const apiConfig = {
+  COMMON: `${API_BASE}/index.php`,
+  IOS_REPORT: `${REPORT_API_BASE}/userinfo.php`,
+  ANDROID_REPORT: `${REPORT_API_BASE}/userinfo.php`,
+  WX_API: `${WX_API_BASE}/wxxyx/index.php`,
+  AD_REPORT: "",
+  IPV4: "",
+  IPV6: "",
+  // COMMON: `${API_BASE}/index.php`,
+  // IOS_REPORT: `${REPORT_API_BASE}/pgIns.php`,
+  // ANDROID_REPORT: `${REPORT_API_BASE}/andUserInfo.php`,
+  // AD_REPORT: `${AD_BASE}?r=mimigame/ad-init-log`,
+  // IPV4: `${IPV4_API_BASE}/mpsw/getIp.php`,
+  // IPV6: `${IPV6_API_BASE}/mpsw/getIp.php`,
+};
+
+export default apiConfig;

+ 31 - 0
config/game.js

@@ -0,0 +1,31 @@
+// 广告配置
+const AGENT_ID = 1000;
+const SITE_ID = 1000;
+const IOS_AGENT_ID = 1000;
+const IOS_SITE_ID = 1000;
+
+const ANDROID_SHARE_AGENT_ID = 1000;
+const ANDROID_SHARE_SITE_ID = 1000;
+const IOS_SHARE_AGENT_ID = 1000;
+const IOS_SHARE_SITE_ID = 1000;
+const MTYPE = 1; //默认自营微信小游戏的mtype
+
+// 生成分享query参数,改用后端传,废弃
+const makeShareQuery = () => {
+    return `agent_id=${ANDROID_SHARE_AGENT_ID}&site_id=${ANDROID_SHARE_SITE_ID}`
+}
+
+const makeIOSShareQuery = () => {
+    return `agent_id=${IOS_SHARE_AGENT_ID}&site_id=${IOS_SHARE_SITE_ID}`
+}
+
+const gameConfig = {
+    // 游戏配置
+    AGENT_ID: AGENT_ID,
+    IOS_AGENT_ID: IOS_AGENT_ID,
+    SITE_ID: SITE_ID,
+    IOS_SITE_ID: IOS_SITE_ID,
+    MTYPE: MTYPE,
+}
+
+export default gameConfig

+ 7 - 0
config/sdk.js

@@ -0,0 +1,7 @@
+const sdkConfig = {
+  SDK_VERSION: "1.0.3",
+  SDK_VERSION_CODE: "1003",
+  DEVICE_NO: "wx_minigame_imei",
+};
+
+export default sdkConfig;

+ 381 - 0
game.js

@@ -0,0 +1,381 @@
+import {
+  init,
+  loginUserInfo,
+  dataReport,
+  makePayment,
+  shareAppMessage,
+  payConfig,
+  navigateToMiniProgram,
+  getBindPhoneCode,
+  bindPhone,
+  onShareAppMessage,
+  requestSubscribeMessage,
+  triggerSubscribe,
+  createAd,
+  login,
+  secCheckText,
+  secCheckMedia,
+} from "./dist/rywxsdk.1.0.3.js";
+// } from "./index";
+
+// 初始化skd
+(async () => {
+  try {
+    let data = {
+      app_version: "1.0.1",
+      config_id: "wxa0167e87cc5efae3", //测试号id
+      game_name: "逍遥志",
+    };
+    // 静默授权
+    const res = await init(data);
+    console.log(res);
+    // 非静默授权
+    // const buttonStyle = {
+    //   type: 'text',
+    //   text: '点击进入游戏',
+    //   style: {
+    //     left: 10,
+    //     top: 76,
+    //     width: 200,
+    //     height: 40,
+    //     lineHeight: 40,
+    //     backgroundColor: '#ff0000',
+    //     color: '#FFFFFF',
+    //     textAlign: 'center',
+    //     fontSize: 16,
+    //     borderRadius: 4
+    //   },
+    //   withCredentials: true
+    // }
+    // await init(data,buttonStyle);
+    wx.showToast({
+      title: "进入游戏成功",
+    });
+    //拉起订阅
+    await requestSubscribeMessage();
+    //触发订阅
+    await triggerSubscribe("login");
+  } catch (error) {
+    console.log(error);
+  }
+})();
+
+//角色上报按钮
+const handleDataReport = async () => {
+  try {
+    let info = {
+      data_type: 2,
+      server_id: 1,
+      server_name: "测试1服",
+      role_id: "10000111",
+      role_name: "小林",
+      role_level: 1,
+      role_currency: "",
+      game_fee: ""
+    };
+    const res = await dataReport(info);
+    wx.showToast({
+      title: "角色上报成功",
+    });
+    console.log(res);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//展示下单按钮
+const handleMakePayment = async () => {
+  try {
+    let info = {
+      amt: 1,
+      server_id: 1,
+      server_name: "测试1服",
+      role_id: "10000111",
+      role_name: "小林",
+      role_level: 1,
+      ext: String(new Date().getTime()),
+      product_id: 1,
+      product_name: "测试商品"
+    };
+    wx.showToast({
+      title: "拉起订单成功",
+    });
+    makePayment(info)
+      .then((res) => {
+        if (res && Object.keys(res).length) {
+          console.log("下单类型返回", res);
+        }
+      })
+      .catch((error) => {
+        console.log(error);
+        // 如果是节流错误,显示友好提示
+        if (error.message === "请求过于频繁,请稍后再试") {
+          wx.showToast({
+            title: "操作过于频繁,请稍后再试",
+            icon: "none",
+          });
+        }
+      });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+const handleMakePayment2 = async () => {
+  try {
+    let info = {
+      amt: 2,
+      server_id: 1,
+      server_name: "测试1服",
+      role_id: "10000111",
+      role_name: "小林",
+      role_level: 1,
+      product_id: 1,
+      product_name: "测试1服",
+      ext: "aaaaaaa",
+    };
+    wx.showToast({
+      title: "拉起订单成功",
+    });
+
+    makePayment(info)
+      .then((res) => {
+        if (res && Object.keys(res).length) {
+          console.log("下单类型返回", res);
+        }
+      })
+      .catch((error) => {
+        console.log(error);
+        // 如果是节流错误,显示友好提示
+        if (error.message === "请求过于频繁,请稍后再试") {
+          wx.showToast({
+            title: "操作过于频繁,请稍后再试",
+            icon: "none",
+          });
+        }
+      });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//主动分享
+const handleShareAppMessage = async () => {
+  try {
+    let info = {
+      title: "分享测试",
+      imageUrl: "https://api-user.91fengwan.com/hd/img/632-2.jpg",
+      ext: "&ceshi=linquan321",
+    };
+    await shareAppMessage(info);
+    wx.showToast({
+      title: "分享成功",
+    });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+// 登录
+const handleLogin = async () => {
+  try {
+    const res = await login();
+    console.log("登录返回res", res);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//获取平台登录用户信息
+const handleLoginUserInfo = async () => {
+  try {
+    const res = await loginUserInfo();
+    console.log(res);
+    wx.showToast({
+      title: "获取成功",
+    });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//IOS 获取获取是否开启支付接口
+const handlePayConfig = async () => {
+  try {
+    const res = await payConfig()
+      .then((res) => { })
+      .catch((error) => { });
+    console.log(res);
+    wx.showToast({
+      title: "获取成功",
+    });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//展示跳转小程序按钮
+const handleNavigateToMiniProgram = async () => {
+  try {
+    await navigateToMiniProgram();
+    wx.showToast({
+      title: "打开成功",
+    });
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//展示获取短信
+const handleGetBindPhoneCode = async () => {
+  try {
+    const res = await getBindPhoneCode({
+      phone: "15975492315",
+    });
+    console.log(res)
+    wx.showToast({
+      title: "发送成功",
+    });
+  } catch (error) {
+    wx.showToast({
+      title: error.msg,
+    });
+    console.log(error);
+  }
+};
+
+//展示绑定手机
+const handleBindPhoneCode = async () => {
+  try {
+    let info = {
+      phone: "15975492315",
+      code: "101344",
+    };
+    await bindPhone(info);
+
+    wx.showToast({
+      title: "绑定成功",
+    });
+  } catch (error) {
+    wx.showToast({
+      title: error.msg,
+    });
+    console.log(error);
+  }
+};
+
+//主动监听
+const handleOnShareAppMessage = () => {
+  onShareAppMessage({
+    title: "测试",
+    imageUrl: "https://api-user.91fengwan.com/hd/img/632-2.jpg",
+    ext: "&ceshi=test",
+  });
+};
+
+//获取订阅
+const handleRequestSubscribeMessage = async () => {
+  try {
+    const res = await requestSubscribeMessage();
+    // await triggerSubscribe('login');
+    wx.showToast({
+      title: "获取成功",
+    });
+
+    // console.log(res)
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//创建广告
+const handleCreateAd = async () => {
+  try {
+    const res = await createAd({
+      ad_type: "video",
+      task: "123",
+    });
+    console.log(res);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//文本内容安全检测
+const handleSecCheckText = async () => {
+  try {
+    const res = await secCheckText({ content: "毛泽东真厉害", scene: 1 });
+    console.log(res);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+//多媒体内容安全检测
+const handleSecCheckMedia = async () => {
+  try {
+    const res = await secCheckMedia({
+      media_url: "https://api-user.91fengwan.com/hd/img/632-2.jpg",
+      media_type: "image",
+      scene: "123",
+    });
+    console.log(res);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+function newButtonMap(name, callback, x, y, w = 200, h = 30) {
+  return {
+    name: name,
+    callback: callback,
+    x: x,
+    y: y,
+    w: w,
+    h: h,
+  };
+}
+let buttonList = [
+  newButtonMap("登录", handleLogin, 10, 60),
+  newButtonMap("上报用户角色", handleDataReport, 10, 450),
+  newButtonMap("生成1元订单", handleMakePayment, 10, 500),
+  newButtonMap("生成2元订单", handleMakePayment2, 10, 540),
+  newButtonMap("主动分享", handleShareAppMessage, 10, 90),
+  newButtonMap("获取平台登陆用户信息", handleLoginUserInfo, 10, 130),
+  newButtonMap("IOS获取获取是否开启支付", handlePayConfig, 10, 170),
+  newButtonMap("跳转小程序", handleNavigateToMiniProgram, 10, 210),
+  newButtonMap("获取手机验证码", handleGetBindPhoneCode, 10, 250),
+  newButtonMap("绑定手机", handleBindPhoneCode, 10, 290),
+  newButtonMap("监听分享传参", handleOnShareAppMessage, 10, 330),
+  newButtonMap("获取订阅", handleRequestSubscribeMessage, 10, 370),
+  newButtonMap("创建广告", handleCreateAd, 10, 410),
+  newButtonMap("文本内容安全检测", handleSecCheckText, 10, 600),
+  newButtonMap("多媒体内容安全检测", handleSecCheckMedia, 10, 640),
+];
+
+const canvas = wx.createCanvas();
+const ctx = canvas.getContext("2d");
+
+ctx.fillStyle = "#ff0000";
+ctx.font = "14px Arial";
+ctx.strokeStyle = "#ff0000";
+for (let k in buttonList) {
+  // ctx.fillRech(0,0,200,40)
+  // let path = new Path2D()
+  // path.rect(buttonList[k].x, buttonList[k].y, buttonList[k].w, buttonList[k].h);
+  // ctx.stroke(path)
+  ctx.fillText(buttonList[k].name, 20, buttonList[k].y + 20);
+}
+wx.onTouchStart(function (a) {
+  let cur = a.touches[0];
+  for (let k in buttonList) {
+    if (
+      cur.clientX >= buttonList[k].x &&
+      cur.clientX <= buttonList[k].x + buttonList[k].w &&
+      cur.clientY >= buttonList[k].y &&
+      cur.clientY <= buttonList[k].y + buttonList[k].h
+    ) {
+      buttonList[k].callback();
+    }
+  }
+});

+ 4 - 0
game.json

@@ -0,0 +1,4 @@
+{
+    "deviceOrientation": "portrait",
+    "showStatusBar": false
+}

+ 24 - 0
index.js

@@ -0,0 +1,24 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-17 10:46:59
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 14:49:55
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\index.js
+ */
+
+export { init } from "./src/init.js";
+export { bindPhone, getBindPhoneCode } from "./src/bindPhone.js";
+export { navigateToMiniProgram } from "./utils/index.js";
+export {
+  payConfig,
+  makePayment,
+  triggerSubscribe,
+  requestSubscribeMessage,
+} from "./src/payment.js";
+export { loginUserInfo, login } from "./src/login.js";
+export { shareAppMessage, onShareAppMessage } from "./src/share.js";
+export { dataReport } from "./src/dataReport.js";
+export { secCheckText, secCheckMedia } from "./src/secCheck.js";
+
+// export {createAd} from "./src/ad.js"

+ 45 - 0
lib/DnSdk.js

@@ -0,0 +1,45 @@
+import { SDK } from "../lib/dn-sdk-minigame/index"
+import  { getStorage } from "../utils/index"
+
+class DnSdk {
+    static instance = null
+    static overrideShareFunc = false
+    constructor() {
+
+    }
+    
+    static init(dnSdkOptions) {
+        if(!dnSdkOptions) {
+            console.warn("DnSdk.init错误,请传入腾讯广告小游戏SDK参数")
+            return false
+        }
+        if (!this.instance) {
+            this.instance = new SDK(dnSdkOptions)
+        }
+
+        if(!this.overrideShareFunc) {
+            wx.shareAppMessage = (function(){
+                const nativeShareAppMessage = wx.shareAppMessage
+                return function(shareData) {
+                    console.log('override shareAppMessage exec')
+                    // 腾讯广告小游戏SDK上报
+                    DnSdk.getInstance().track('SHARE', {
+                        target: 'APP_MESSAGE'
+                    });
+                    return nativeShareAppMessage(shareData)
+                }
+            })()
+            this.overrideShareFunc = true
+        }
+    }
+
+    static getInstance() {
+        if (!this.instance) {
+            console.warn("请先执行miniGameSdk的init方法")
+            return false
+        }
+        return this.instance;
+    }
+}
+
+export default DnSdk

+ 102 - 0
lib/checkOrderToReport.js

@@ -0,0 +1,102 @@
+import { compile, uncompile, unixTimestamp } from "../utils/index.js";
+import request from "../utils/request.js";
+import DnSdk from "./DnSdk.js";
+
+class checkOrderToReport {
+  static instance = null;
+  static timer = null;
+  static reportDelayMap = [
+    //index是report次数 值是delayTime(秒)
+    20, // 立即
+    60, // 1分钟
+    120, // 2分钟
+    180, // 3分钟
+    300, // 5分钟
+    600, // 10分钟
+    1200, // 20分钟
+    1800, // 30分钟
+    3600, // 1小时
+    7200, // 2小时
+  ];
+
+  constructor() {}
+
+  async checkOrder() {
+    const res = wx.getStorageInfoSync();
+    for (let storageKey of res.keys) {
+      if (storageKey.indexOf("_extOrderToReport_") > -1) {
+        const order = uncompile(wx.getStorageSync(storageKey));
+        console.log("order",order);
+        const delayTimeMap = checkOrderToReport.reportDelayMap;
+        const delayTime = delayTimeMap[order.reportCount];
+        const timeDiff = unixTimestamp() - order.timestamp;
+        let currentMapIndex = -1;
+        for (let i = delayTimeMap.length - 1; i >= 0; i--) {
+          if (timeDiff >= delayTimeMap[i]) {
+            currentMapIndex = i;
+            break;
+          }
+        }
+        if (delayTime == undefined) {
+          // 删除超过重试次数的订单
+          wx.removeStorageSync(storageKey);
+          console.log(storageKey + " removed!");
+          continue;
+        }
+        if (timeDiff >= delayTime) {
+          let isPaid=0;
+          let isRefused=0;
+          // 请求判断是否支付成功
+          const res = await request.api("COMMON", {
+            do: "getExtPayStatus",
+            ext: order.ext,
+            order_no: order.order_no ?? null,
+          });
+          isPaid = res.isPaid ?? 0;
+          isRefused = res.isRefused ?? 0;
+
+          // isRefused=1 说明不需要上报
+          if (isRefused) {
+            wx.removeStorageSync(storageKey);
+            console.log(storageKey + " report Refused and removed!");
+          } else if (isPaid) {
+            DnSdk.getInstance().onPurchase(order.amt * 100); // 腾讯广告小游戏SDK上报
+            wx.removeStorageSync(storageKey);
+            console.log(storageKey + " report success and removed!");
+          } else {
+            if (currentMapIndex == delayTimeMap.length - 1) {
+              // 删除超过最长重试延时的订单
+              wx.removeStorageSync(storageKey);
+              console.log(storageKey + " removed!");
+              continue;
+            }
+            if (currentMapIndex > order.reportCount) {
+              order.reportCount = currentMapIndex;
+            }
+            order.reportCount += 1;
+            wx.setStorageSync(storageKey, compile(order));
+          }
+        }
+      }
+    }
+    checkOrderToReport.getInstance().timer = setTimeout(
+      checkOrderToReport.getInstance().checkOrder,
+      60000
+    );
+  }
+
+  run() {
+    if (!checkOrderToReport.getInstance().timer) {
+      checkOrderToReport.getInstance().checkOrder();
+    }
+  }
+
+  static getInstance() {
+    if (!this.instance) {
+      this.instance = new checkOrderToReport();
+    }
+    return this.instance;
+  }
+}
+
+export default checkOrderToReport;

+ 542 - 0
lib/dn-sdk-minigame/index.d.ts

@@ -0,0 +1,542 @@
+/**
+ * SDK 初始化参数
+ */
+interface SdkConfig {
+    /**
+     * 数据源ID,必填
+     */
+    user_action_set_id: number;
+    /**
+     * 加密key,必填
+     */
+    secret_key: string;
+    /**
+     * 微信小程序/小游戏APPID,wx开头,必填
+     */
+    appid: string;
+    /**
+     * 微信 openid,openid 和 unionid 至少填一个, 可以调用 setOpenId 设置
+     */
+    openid?: string;
+    /**
+     * 微信 unionid,openid 和 unionid 至少填一个, 可以调用 setUnionId 设置
+     */
+    unionid?: string;
+    /**
+     * 自定义用户ID,选填
+     */
+    user_unique_id?: string;
+    /**
+     * 是否自动采集事件
+     */
+    auto_track?: boolean;
+    /**
+     * 是否自动采集属性
+     */
+    auto_attr?: boolean;
+    /**
+     * 上报回调(包括成功、失败、重试的各种场景)
+     */
+    on_report_complete?: Function | undefined;
+    /**
+     * 明确上报失败的回调(sdk内部会直接丢弃的行为,无法再重试上报成功的部分)
+     */
+    on_report_fail?: Function | undefined;
+}
+/**
+ * 小程序/小游戏信息
+ */
+interface GameInfo {
+    /**
+     * 广告点击id、曝光id
+     */
+    ad_trace_id?: string;
+    /**
+     * 页面路径,小游戏没有
+     */
+    page_url?: string;
+    /**
+     * 页面名称,小游戏没有
+     */
+    page_title?: string;
+    /**
+     * 组件名称
+     */
+    component_name?: string;
+    /**
+     * 场景来源
+     */
+    source_scene?: number;
+    /**
+     * 渠道号
+     */
+    pkg_channel_id?: string;
+    /**
+     * 框架信息,小游戏没有
+     */
+    framework?: string;
+    /**
+     * 渠道来源
+     */
+    channel: string;
+    /**
+     * 启动参数
+     */
+    launch_options: string;
+}
+/**
+ * 设备信息
+ */
+interface DeviceInfo {
+    /**
+     * 设备品牌
+     */
+    device_brand: string;
+    /**
+     * 设备型号
+     */
+    device_model: string;
+    /**
+     * 微信App版本
+     */
+    wx_version: string;
+    /**
+     * 微信基础库版本
+     */
+    wx_lib_version: string;
+    /**
+     * 微信客户端平台
+     */
+    wx_platform: string;
+    /**
+     * 操作系统
+     */
+    os: string;
+    /**
+     * 操作系统版本
+     */
+    os_version: string;
+    /**
+     * 设备性能等级
+     */
+    benchmark_level: number;
+    /**
+     * 屏幕高度
+     */
+    screen_height: number;
+    /**
+     * 屏幕宽度
+     */
+    screen_width: number;
+}
+interface TrackBaseInfo extends SdkConfig, DeviceInfo {
+    local_id: string;
+    sdk_name: string;
+    sdk_version: string;
+    inner_param: {
+        app_version: string;
+        app_env_version: string;
+    };
+}
+/**
+ * 行为信息
+ */
+interface ActionInfo {
+    action_type: string;
+    action_param?: Record<string | number | symbol, unknown>;
+    is_sdk_auto_track: boolean;
+    session_id: string;
+    log_id: number;
+    action_id: string;
+    action_time: number;
+    revised_action_time: number;
+    is_retry: boolean;
+    retry_count: number;
+    ad_trace_id?: string;
+    page_url?: string;
+    page_title?: string;
+    component_name?: string;
+    source_scene?: number;
+    pkg_channel_id?: string;
+    /**
+     * 网络类型
+     */
+    network_type?: string;
+    inner_param?: Record<string | number | symbol, unknown>;
+    channel?: string;
+}
+interface LogParams {
+    log_type: string;
+    code?: number;
+    message?: string;
+    err_stack?: string;
+    user_action_set_id?: number;
+    appid?: string;
+    local_id?: string;
+    session_id?: string;
+    sdk_name?: string;
+    sdk_version?: string;
+    page_url?: string;
+    framework?: string;
+    device_brand?: string;
+    device_model?: string;
+    wx_version?: string;
+    wx_lib_version?: string;
+    wx_platform?: string;
+    os?: string;
+    os_version?: string;
+}
+interface TrackResponse {
+    code: number;
+    message: string;
+    actionId?: string;
+}
+
+interface QueueProps {
+    /**
+     * 数据源ID,用于本地存储队列key
+     */
+    userActionSetId: number;
+    /**
+     * 队列长度
+     */
+    maxLength: number;
+}
+interface QueueManagerProps extends QueueProps {
+    /**
+     * OG事件列表
+     */
+    ogEvents: string[];
+}
+interface IEvent extends ActionInfo {
+    inner_status?: string;
+}
+
+/**
+ * 队列原子操作
+ */
+
+declare class Queue {
+    protected maxLength: any;
+    protected userActionSetId: any;
+    protected lostActionMaps: Record<string, number>;
+    private stack;
+    private localStorageKey;
+    private timeStamp;
+    constructor({ userActionSetId, maxLength }: QueueProps);
+    getItems(): IEvent[];
+    getStorage(): IEvent[];
+    /**
+     * 上报丢失条数到日志系统
+     */
+    reportLostNum(): void;
+    /**
+     * 获取丢失条数map
+     * @returns 丢失条数map
+     */
+    getLostMaps(): Record<string, number>;
+    protected init(): void;
+    protected addItem(eventData: IEvent): void;
+    protected removeItems(actionIds: string[]): void;
+    protected updateForReportFail(actionIds: string[]): void;
+    protected updateForReporting(actionIds: string[]): void;
+    protected updateAllStack(stack: IEvent[]): void;
+    protected updateToStorage(): void;
+    /**
+     * 更新丢失条数
+     * @param sessionId 当前被丢弃行为的会话id
+     */
+    protected updateLostAction(sessionId: string): void;
+    /**
+     * 设置时间戳
+     */
+    protected setTimeStamp(): void;
+}
+
+declare class QueueManage extends Queue {
+    protected ogEvents: string[];
+    constructor({ userActionSetId, maxLength, ogEvents }: QueueManagerProps);
+    /**
+     * 获取可上报的队列
+     * @param reportMaxLength 需要上报的队列最大长度
+     */
+    getReportableActions(reportMaxLength?: number): IEvent[];
+    /**
+     * 添加行为到队列
+     * @param eventData 单条行为数据
+     */
+    addAction(eventData: IEvent): TrackResponse;
+    /**
+     * 根据acition_id删除行为
+     * @param actionIds 行为id列表
+     */
+    removeActions(actionIds: string[]): void;
+    /**
+     * 上报失败时更新队列状态
+     * @param actionIds
+     */
+    updateActionsForReportFail(actionIds: string[]): void;
+    /**
+     * 上报时更新队列状态为reporting
+     * @param actionIds 需要更新的行为id数组
+     */
+    updateActionsForReporting(actionIds: string[]): void;
+    /**
+     * 获取可上报队列长度
+     * @returns 可上报队列长度
+     */
+    getReportableActionsLength(): number;
+    /**
+     * 按照优先级从大到小给队列排序
+     * @param currEvent 当前事件
+     * @param stack 当前队列
+     */
+    sortQueue(currEvent: IEvent, stack: IEvent[]): IEvent[];
+    /**
+     * 计算优先级
+     * @param currTime 当前时间
+     * @param event 行为事件
+     * @returns 权重值
+     */
+    private caculateWeight;
+    /**
+     *
+     * @param currTime 当前时间
+     * @param actionTime 队列行为时间
+     * @returns 权重值
+     */
+    private formatWeight;
+}
+
+interface ConfigManager {
+    getRealTimeActionList: () => Array<string>;
+    getRequestTimeout: () => number;
+}
+interface ActionReporterProps {
+    getBaseInfo: () => TrackBaseInfo;
+    reportLog: (param: LogParams) => void;
+    queueManager: QueueManage;
+    configManager?: ConfigManager;
+    onReportComplete?: Function | undefined;
+    onReportFail?: Function | undefined;
+}
+/**
+ * 行为上报类
+ */
+declare class ActionReporter {
+    private static currentRequestCount;
+    private static requestConcurrency;
+    static setRequestConcurrency(n: number): void;
+    private getBaseInfo;
+    private reportLog;
+    private queueManager;
+    private configManager;
+    private onReportComplete;
+    private onReportFail;
+    private cgiBatchSize;
+    private reportThreshold;
+    private reportDelay;
+    private triggerExecuteSend;
+    private inspectDelay;
+    private inspectTimer;
+    private isNeedContinueSend;
+    constructor(props: ActionReporterProps);
+    /**
+     * 批量上报行为,track的时候触发
+     */
+    batchSend(): void;
+    /**
+     * 全量上报, flush的时候触发
+     */
+    flushSend(): void;
+    /**
+     * 执行指定数量的行为上报逻辑,超过接口batch上限则并行发送请求
+     */
+    private executeSend;
+    /**
+     * 组装上报用的行为数据
+     */
+    private generateActionReportParams;
+    /**
+     * 上报接口请求成功逻辑处理
+     * @param resData
+     * @param actionIdList
+     */
+    private dealSuccessData;
+    /**
+     * 上报接口请求失败逻辑处理
+     * @param errData
+     * @param actionIdList
+     */
+    private dealFailData;
+    /**
+     * wx.request文档:https://developers.weixin.qq.com/minigame/dev/api/network/request/wx.request.html
+     * @param param.data:接口请求参数、param.actionIdList:行为id列表
+     * @returns
+     */
+    private report;
+    /**
+     * 启动上报定时器
+     */
+    private startInspectTimer;
+    /**
+     * 上报回调数据
+     */
+    private doTrackCallbackFn;
+}
+
+declare abstract class SdkExtCommon {
+    protected special_method_symbol: symbol;
+    /**
+     * 付费
+     */
+    onPurchase(value: number): TrackResponse;
+    /**
+     * 进入前台
+     */
+    onEnterForeground(): TrackResponse;
+    /**
+     * 进入后台
+     */
+    onEnterBackground(): TrackResponse;
+    /**
+     * 启动
+     */
+    onAppStart(): TrackResponse;
+    /**
+     * 退出
+     */
+    onAppQuit(): TrackResponse;
+    /**
+     * 收藏
+     */
+    onAddToWishlist(): TrackResponse;
+    protected wrapTrack(action_type: ActionInfo["action_type"], action_param?: ActionInfo["action_param"]): TrackResponse;
+    abstract track(action_type: ActionInfo["action_type"], action_param?: ActionInfo["action_param"]): TrackResponse;
+}
+
+declare abstract class sdkExt extends SdkExtCommon {
+    /**
+     * 注册
+     */
+    onRegister(): TrackResponse;
+    /**
+     * 创角
+     */
+    onCreateRole(name?: string): TrackResponse;
+    /**
+     * 完成新手教程
+     */
+    onTutorialFinish(): TrackResponse;
+}
+
+declare const initializedInstanceSymbol: unique symbol;
+declare class SDK extends sdkExt {
+    private static [initializedInstanceSymbol];
+    static setRequestConcurrency(n: number): void;
+    static setDebug(debug: boolean): void;
+    protected env: string;
+    protected sdk_version: string;
+    protected sdk_name: string;
+    protected config?: SdkConfig;
+    protected deviceInfo: Partial<DeviceInfo>;
+    protected gameInfo: Partial<GameInfo>;
+    protected session_id: string;
+    protected log_id: number;
+    protected queueManage?: QueueManage;
+    protected actionReporter?: ActionReporter;
+    protected openid?: string;
+    protected unionid?: string;
+    protected user_unique_id?: string;
+    protected inited: boolean;
+    protected initErrMsg: string;
+    protected onReportComplete?: Function | undefined;
+    protected onReportFail?: Function | undefined;
+    constructor(sdkConfig: SdkConfig);
+    /**
+     * 返回初始化状态
+     * @returns
+     */
+    getInitResult(): {
+        inited: boolean;
+        initErrMsg: string;
+    };
+    /**
+     * 数据上报方法
+     * 0: 成功
+     * 100: 未完成初始化或重复初始化导致初始化失败,请先完成初始化
+     * 101: action_type 或 action_param 参数错误
+     * 102: action_param 参数过大,不能超过 xxxx 字符
+     * 103: 缓存队列已满,主动丢弃行为
+     *
+     */
+    track(action_type: ActionInfo['action_type'], action_param?: ActionInfo['action_param']): TrackResponse;
+    /**
+     * 立即上报数据
+     */
+    flush(): void;
+    /**
+     * 设置 openId
+     * 0: 成功
+     * 101: openid 格式错误
+     */
+    setOpenId(openid: string): {
+        code: number;
+        message: string;
+    };
+    /**
+       * 设置 unionid
+       * 0: 成功
+       * 101: unionid 格式错误
+       */
+    setUnionId(unionid: string): {
+        code: number;
+        message: string;
+    };
+    /**
+       * 设置 user_unique_id
+       * @param user_unique_id
+       */
+    setUserUniqueId(user_unique_id: string): {
+        code: number;
+        message: string;
+    };
+    protected doReportOnEnterBackground(): void;
+    /**
+       * 获取数据上报时所需要的 info 参数
+       */
+    private getTrackBaseInfo;
+    /**
+     * 生成上报队列需要的行为数据
+     * @param actionParams 行为参数
+     * @param is_sdk_auto_track 是否自动采集
+     * @returns
+     */
+    private createAction;
+    /**
+     * 给指定行为的inner_param字段追加字段
+     * @param action 待追加字段的行为
+     * @param key 待添加到inner_param字段的key
+     * @param value key对应的value
+     */
+    private addActionInnerParam;
+    /**
+     * 不同行为携带的渠道来源判断逻辑
+     * @param actionType
+     * @returns
+     */
+    private getChannelByActionType;
+    /**
+     * 上报日志
+     * @param params 日志参数
+     */
+    private reportLog;
+    private useAutoTrack;
+    private getAutoProxyRemoteConfig;
+    /**
+     * 设置openid时,如果值合法缓存到Storage
+     */
+    private saveValidOpenidToStorage;
+}
+
+export { SDK };

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 5 - 0
lib/dn-sdk-minigame/index.js


+ 683 - 0
lib/md5.js

@@ -0,0 +1,683 @@
+/**
+ * [js-md5]{@link https://github.com/emn178/js-md5}
+ *
+ * @namespace md5
+ * @version 0.7.3
+ * @author Chen, Yi-Cyuan [emn178@gmail.com]
+ * @copyright Chen, Yi-Cyuan 2014-2017
+ * @license MIT
+ */
+(function () {
+    'use strict';
+
+    var ERROR = 'input is invalid type';
+    var WINDOW = typeof window === 'object';
+    var root = WINDOW ? window : {};
+    if (root.JS_MD5_NO_WINDOW) {
+        WINDOW = false;
+    }
+    var WEB_WORKER = !WINDOW && typeof self === 'object';
+    var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
+    if (NODE_JS) {
+        root = global;
+    } else if (WEB_WORKER) {
+        root = self;
+    }
+    var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports;
+    var AMD = typeof define === 'function' && define.amd;
+    var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
+    var HEX_CHARS = '0123456789abcdef'.split('');
+    var EXTRA = [128, 32768, 8388608, -2147483648];
+    var SHIFT = [0, 8, 16, 24];
+    var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];
+    var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
+
+    var blocks = [], buffer8;
+    if (ARRAY_BUFFER) {
+        var buffer = new ArrayBuffer(68);
+        buffer8 = new Uint8Array(buffer);
+        blocks = new Uint32Array(buffer);
+    }
+
+    if (root.JS_MD5_NO_NODE_JS || !Array.isArray) {
+        Array.isArray = function (obj) {
+            return Object.prototype.toString.call(obj) === '[object Array]';
+        };
+    }
+
+    if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
+        ArrayBuffer.isView = function (obj) {
+            return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
+        };
+    }
+
+    /**
+     * @method hex
+     * @memberof md5
+     * @description Output hash as hex string
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {String} Hex string
+     * @example
+     * md5.hex('The quick brown fox jumps over the lazy dog');
+     * // equal to
+     * md5('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method digest
+     * @memberof md5
+     * @description Output hash as bytes array
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Array} Bytes array
+     * @example
+     * md5.digest('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method array
+     * @memberof md5
+     * @description Output hash as bytes array
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Array} Bytes array
+     * @example
+     * md5.array('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method arrayBuffer
+     * @memberof md5
+     * @description Output hash as ArrayBuffer
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @example
+     * md5.arrayBuffer('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method buffer
+     * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
+     * @memberof md5
+     * @description Output hash as ArrayBuffer
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @example
+     * md5.buffer('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method base64
+     * @memberof md5
+     * @description Output hash as base64 string
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {String} base64 string
+     * @example
+     * md5.base64('The quick brown fox jumps over the lazy dog');
+     */
+    var createOutputMethod = function (outputType) {
+        return function (message) {
+            return new Md5(true).update(message)[outputType]();
+        };
+    };
+
+    /**
+     * @method create
+     * @memberof md5
+     * @description Create Md5 object
+     * @returns {Md5} Md5 object.
+     * @example
+     * var hash = md5.create();
+     */
+    /**
+     * @method update
+     * @memberof md5
+     * @description Create and update Md5 object
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Md5} Md5 object.
+     * @example
+     * var hash = md5.update('The quick brown fox jumps over the lazy dog');
+     * // equal to
+     * var hash = md5.create();
+     * hash.update('The quick brown fox jumps over the lazy dog');
+     */
+    var createMethod = function () {
+        var method = createOutputMethod('hex');
+        if (NODE_JS) {
+            method = nodeWrap(method);
+        }
+        method.create = function () {
+            return new Md5();
+        };
+        method.update = function (message) {
+            return method.create().update(message);
+        };
+        for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
+            var type = OUTPUT_TYPES[i];
+            method[type] = createOutputMethod(type);
+        }
+        return method;
+    };
+
+    var nodeWrap = function (method) {
+        var crypto = eval("require('crypto')");
+        var Buffer = eval("require('buffer').Buffer");
+        var nodeMethod = function (message) {
+            if (typeof message === 'string') {
+                return crypto.createHash('md5').update(message, 'utf8').digest('hex');
+            } else {
+                if (message === null || message === undefined) {
+                    throw ERROR;
+                } else if (message.constructor === ArrayBuffer) {
+                    message = new Uint8Array(message);
+                }
+            }
+            if (Array.isArray(message) || ArrayBuffer.isView(message) ||
+                message.constructor === Buffer) {
+                return crypto.createHash('md5').update(new Buffer(message)).digest('hex');
+            } else {
+                return method(message);
+            }
+        };
+        return nodeMethod;
+    };
+
+    /**
+     * Md5 class
+     * @class Md5
+     * @description This is internal class.
+     * @see {@link md5.create}
+     */
+    function Md5(sharedMemory) {
+        if (sharedMemory) {
+            blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                    blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                        blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+            this.blocks = blocks;
+            this.buffer8 = buffer8;
+        } else {
+            if (ARRAY_BUFFER) {
+                var buffer = new ArrayBuffer(68);
+                this.buffer8 = new Uint8Array(buffer);
+                this.blocks = new Uint32Array(buffer);
+            } else {
+                this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+            }
+        }
+        this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0;
+        this.finalized = this.hashed = false;
+        this.first = true;
+    }
+
+    /**
+     * @method update
+     * @memberof Md5
+     * @instance
+     * @description Update hash
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Md5} Md5 object.
+     * @see {@link md5.update}
+     */
+    Md5.prototype.update = function (message) {
+        if (this.finalized) {
+            return;
+        }
+
+        var notString, type = typeof message;
+        if (type !== 'string') {
+            if (type === 'object') {
+                if (message === null) {
+                    throw ERROR;
+                } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
+                    message = new Uint8Array(message);
+                } else if (!Array.isArray(message)) {
+                    if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
+                        throw ERROR;
+                    }
+                }
+            } else {
+                throw ERROR;
+            }
+            notString = true;
+        }
+        var code, index = 0, i, length = message.length, blocks = this.blocks;
+        var buffer8 = this.buffer8;
+
+        while (index < length) {
+            if (this.hashed) {
+                this.hashed = false;
+                blocks[0] = blocks[16];
+                blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                    blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                        blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                            blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+            }
+
+            if (notString) {
+                if (ARRAY_BUFFER) {
+                    for (i = this.start; index < length && i < 64; ++index) {
+                        buffer8[i++] = message[index];
+                    }
+                } else {
+                    for (i = this.start; index < length && i < 64; ++index) {
+                        blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
+                    }
+                }
+            } else {
+                if (ARRAY_BUFFER) {
+                    for (i = this.start; index < length && i < 64; ++index) {
+                        code = message.charCodeAt(index);
+                        if (code < 0x80) {
+                            buffer8[i++] = code;
+                        } else if (code < 0x800) {
+                            buffer8[i++] = 0xc0 | (code >> 6);
+                            buffer8[i++] = 0x80 | (code & 0x3f);
+                        } else if (code < 0xd800 || code >= 0xe000) {
+                            buffer8[i++] = 0xe0 | (code >> 12);
+                            buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
+                            buffer8[i++] = 0x80 | (code & 0x3f);
+                        } else {
+                            code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
+                            buffer8[i++] = 0xf0 | (code >> 18);
+                            buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
+                            buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
+                            buffer8[i++] = 0x80 | (code & 0x3f);
+                        }
+                    }
+                } else {
+                    for (i = this.start; index < length && i < 64; ++index) {
+                        code = message.charCodeAt(index);
+                        if (code < 0x80) {
+                            blocks[i >> 2] |= code << SHIFT[i++ & 3];
+                        } else if (code < 0x800) {
+                            blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                        } else if (code < 0xd800 || code >= 0xe000) {
+                            blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                        } else {
+                            code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
+                            blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+                            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                        }
+                    }
+                }
+            }
+            this.lastByteIndex = i;
+            this.bytes += i - this.start;
+            if (i >= 64) {
+                this.start = i - 64;
+                this.hash();
+                this.hashed = true;
+            } else {
+                this.start = i;
+            }
+        }
+        if (this.bytes > 4294967295) {
+            this.hBytes += this.bytes / 4294967296 << 0;
+            this.bytes = this.bytes % 4294967296;
+        }
+        return this;
+    };
+
+    Md5.prototype.finalize = function () {
+        if (this.finalized) {
+            return;
+        }
+        this.finalized = true;
+        var blocks = this.blocks, i = this.lastByteIndex;
+        blocks[i >> 2] |= EXTRA[i & 3];
+        if (i >= 56) {
+            if (!this.hashed) {
+                this.hash();
+            }
+            blocks[0] = blocks[16];
+            blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                    blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                        blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+        }
+        blocks[14] = this.bytes << 3;
+        blocks[15] = this.hBytes << 3 | this.bytes >>> 29;
+        this.hash();
+    };
+
+    Md5.prototype.hash = function () {
+        var a, b, c, d, bc, da, blocks = this.blocks;
+
+        if (this.first) {
+            a = blocks[0] - 680876937;
+            a = (a << 7 | a >>> 25) - 271733879 << 0;
+            d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;
+            d = (d << 12 | d >>> 20) + a << 0;
+            c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
+            c = (c << 17 | c >>> 15) + d << 0;
+            b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
+            b = (b << 22 | b >>> 10) + c << 0;
+        } else {
+            a = this.h0;
+            b = this.h1;
+            c = this.h2;
+            d = this.h3;
+            a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
+            a = (a << 7 | a >>> 25) + b << 0;
+            d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
+            d = (d << 12 | d >>> 20) + a << 0;
+            c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
+            c = (c << 17 | c >>> 15) + d << 0;
+            b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
+            b = (b << 22 | b >>> 10) + c << 0;
+        }
+
+        a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
+        b = (b << 20 | b >>> 12) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[5] - 378558;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[8] - 2022574463;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[11] + 1839030562;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[14] - 35309556;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[1] - 1530992060;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[4] + 1272893353;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[7] - 155497632;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[10] - 1094730640;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[13] + 681279174;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[0] - 358537222;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[3] - 722521979;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[6] + 76029189;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[9] - 640364487;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[12] - 421815835;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[15] + 530742520;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[2] - 995338651;
+        b = (b << 23 | b >>> 9) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[0] - 198630844;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[5] - 57434055;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[10] - 1051523;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[15] - 30611744;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[4] - 145523070;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[2] + 718787259;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[9] - 343485551;
+        b = (b << 21 | b >>> 11) + c << 0;
+
+        if (this.first) {
+            this.h0 = a + 1732584193 << 0;
+            this.h1 = b - 271733879 << 0;
+            this.h2 = c - 1732584194 << 0;
+            this.h3 = d + 271733878 << 0;
+            this.first = false;
+        } else {
+            this.h0 = this.h0 + a << 0;
+            this.h1 = this.h1 + b << 0;
+            this.h2 = this.h2 + c << 0;
+            this.h3 = this.h3 + d << 0;
+        }
+    };
+
+    /**
+     * @method hex
+     * @memberof Md5
+     * @instance
+     * @description Output hash as hex string
+     * @returns {String} Hex string
+     * @see {@link md5.hex}
+     * @example
+     * hash.hex();
+     */
+    Md5.prototype.hex = function () {
+        this.finalize();
+
+        var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
+
+        return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
+            HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
+            HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
+            HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
+            HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
+            HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
+            HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
+            HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
+            HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
+            HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
+            HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
+            HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
+            HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
+            HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
+            HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
+            HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];
+    };
+
+    /**
+     * @method toString
+     * @memberof Md5
+     * @instance
+     * @description Output hash as hex string
+     * @returns {String} Hex string
+     * @see {@link md5.hex}
+     * @example
+     * hash.toString();
+     */
+    Md5.prototype.toString = Md5.prototype.hex;
+
+    /**
+     * @method digest
+     * @memberof Md5
+     * @instance
+     * @description Output hash as bytes array
+     * @returns {Array} Bytes array
+     * @see {@link md5.digest}
+     * @example
+     * hash.digest();
+     */
+    Md5.prototype.digest = function () {
+        this.finalize();
+
+        var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
+        return [
+            h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,
+            h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,
+            h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,
+            h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF
+        ];
+    };
+
+    /**
+     * @method array
+     * @memberof Md5
+     * @instance
+     * @description Output hash as bytes array
+     * @returns {Array} Bytes array
+     * @see {@link md5.array}
+     * @example
+     * hash.array();
+     */
+    Md5.prototype.array = Md5.prototype.digest;
+
+    /**
+     * @method arrayBuffer
+     * @memberof Md5
+     * @instance
+     * @description Output hash as ArrayBuffer
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @see {@link md5.arrayBuffer}
+     * @example
+     * hash.arrayBuffer();
+     */
+    Md5.prototype.arrayBuffer = function () {
+        this.finalize();
+
+        var buffer = new ArrayBuffer(16);
+        var blocks = new Uint32Array(buffer);
+        blocks[0] = this.h0;
+        blocks[1] = this.h1;
+        blocks[2] = this.h2;
+        blocks[3] = this.h3;
+        return buffer;
+    };
+
+    /**
+     * @method buffer
+     * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
+     * @memberof Md5
+     * @instance
+     * @description Output hash as ArrayBuffer
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @see {@link md5.buffer}
+     * @example
+     * hash.buffer();
+     */
+    Md5.prototype.buffer = Md5.prototype.arrayBuffer;
+
+    /**
+     * @method base64
+     * @memberof Md5
+     * @instance
+     * @description Output hash as base64 string
+     * @returns {String} base64 string
+     * @see {@link md5.base64}
+     * @example
+     * hash.base64();
+     */
+    Md5.prototype.base64 = function () {
+        var v1, v2, v3, base64Str = '', bytes = this.array();
+        for (var i = 0; i < 15;) {
+            v1 = bytes[i++];
+            v2 = bytes[i++];
+            v3 = bytes[i++];
+            base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
+                BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +
+                BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +
+                BASE64_ENCODE_CHAR[v3 & 63];
+        }
+        v1 = bytes[i];
+        base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
+            BASE64_ENCODE_CHAR[(v1 << 4) & 63] +
+            '==';
+        return base64Str;
+    };
+
+    var exports = createMethod();
+
+    if (COMMON_JS) {
+        module.exports = exports;
+    } else {
+        /**
+         * @method md5
+         * @description Md5 hash function, export to global in browsers.
+         * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+         * @returns {String} md5 hashes
+         * @example
+         * md5(''); // d41d8cd98f00b204e9800998ecf8427e
+         * md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6
+         * md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0
+         *
+         * // It also supports UTF-8 encoding
+         * md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07
+         *
+         * // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
+         * md5([]); // d41d8cd98f00b204e9800998ecf8427e
+         * md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e
+         */
+        root.md5 = exports;
+        if (AMD) {
+            define(function () {
+                return exports;
+            });
+        }
+    }
+})();

+ 807 - 0
lib/tqsdk/libs/core.js

@@ -0,0 +1,807 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory();
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define([], factory);
+	}
+	else {
+		// Global (browser)
+		root.CryptoJS = factory();
+	}
+}(this, function () {
+
+	/*globals window, global, require*/
+
+	/**
+	 * CryptoJS core components.
+	 */
+	var CryptoJS = CryptoJS || (function (Math, undefined) {
+
+	    var crypto;
+
+	    // Native crypto from window (Browser)
+	    if (typeof window !== 'undefined' && window.crypto) {
+	        crypto = window.crypto;
+	    }
+
+	    // Native crypto in web worker (Browser)
+	    if (typeof self !== 'undefined' && self.crypto) {
+	        crypto = self.crypto;
+	    }
+
+	    // Native crypto from worker
+	    if (typeof globalThis !== 'undefined' && globalThis.crypto) {
+	        crypto = globalThis.crypto;
+	    }
+
+	    // Native (experimental IE 11) crypto from window (Browser)
+	    if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
+	        crypto = window.msCrypto;
+	    }
+
+	    // Native crypto from global (NodeJS)
+	    if (!crypto && typeof global !== 'undefined' && global.crypto) {
+	        crypto = global.crypto;
+	    }
+
+	    // Native crypto import via require (NodeJS)
+	    if (!crypto && typeof require === 'function') {
+	        try {
+	            crypto = require('crypto');
+	        } catch (err) {}
+	    }
+
+	    /*
+	     * Cryptographically secure pseudorandom number generator
+	     *
+	     * As Math.random() is cryptographically not safe to use
+	     */
+	    var cryptoSecureRandomInt = function () {
+	        if (crypto) {
+	            // Use getRandomValues method (Browser)
+	            if (typeof crypto.getRandomValues === 'function') {
+	                try {
+	                    return crypto.getRandomValues(new Uint32Array(1))[0];
+	                } catch (err) {}
+	            }
+
+	            // Use randomBytes method (NodeJS)
+	            if (typeof crypto.randomBytes === 'function') {
+	                try {
+	                    return crypto.randomBytes(4).readInt32LE();
+	                } catch (err) {}
+	            }
+	        }
+
+	        throw new Error('Native crypto module could not be used to get secure random number.');
+	    };
+
+	    /*
+	     * Local polyfill of Object.create
+
+	     */
+	    var create = Object.create || (function () {
+	        function F() {}
+
+	        return function (obj) {
+	            var subtype;
+
+	            F.prototype = obj;
+
+	            subtype = new F();
+
+	            F.prototype = null;
+
+	            return subtype;
+	        };
+	    }());
+
+	    /**
+	     * CryptoJS namespace.
+	     */
+	    var C = {};
+
+	    /**
+	     * Library namespace.
+	     */
+	    var C_lib = C.lib = {};
+
+	    /**
+	     * Base object for prototypal inheritance.
+	     */
+	    var Base = C_lib.Base = (function () {
+
+
+	        return {
+	            /**
+	             * Creates a new object that inherits from this object.
+	             *
+	             * @param {Object} overrides Properties to copy into the new object.
+	             *
+	             * @return {Object} The new object.
+	             *
+	             * @static
+	             *
+	             * @example
+	             *
+	             *     var MyType = CryptoJS.lib.Base.extend({
+	             *         field: 'value',
+	             *
+	             *         method: function () {
+	             *         }
+	             *     });
+	             */
+	            extend: function (overrides) {
+	                // Spawn
+	                var subtype = create(this);
+
+	                // Augment
+	                if (overrides) {
+	                    subtype.mixIn(overrides);
+	                }
+
+	                // Create default initializer
+	                if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
+	                    subtype.init = function () {
+	                        subtype.$super.init.apply(this, arguments);
+	                    };
+	                }
+
+	                // Initializer's prototype is the subtype object
+	                subtype.init.prototype = subtype;
+
+	                // Reference supertype
+	                subtype.$super = this;
+
+	                return subtype;
+	            },
+
+	            /**
+	             * Extends this object and runs the init method.
+	             * Arguments to create() will be passed to init().
+	             *
+	             * @return {Object} The new object.
+	             *
+	             * @static
+	             *
+	             * @example
+	             *
+	             *     var instance = MyType.create();
+	             */
+	            create: function () {
+	                var instance = this.extend();
+	                instance.init.apply(instance, arguments);
+
+	                return instance;
+	            },
+
+	            /**
+	             * Initializes a newly created object.
+	             * Override this method to add some logic when your objects are created.
+	             *
+	             * @example
+	             *
+	             *     var MyType = CryptoJS.lib.Base.extend({
+	             *         init: function () {
+	             *             // ...
+	             *         }
+	             *     });
+	             */
+	            init: function () {
+	            },
+
+	            /**
+	             * Copies properties into this object.
+	             *
+	             * @param {Object} properties The properties to mix in.
+	             *
+	             * @example
+	             *
+	             *     MyType.mixIn({
+	             *         field: 'value'
+	             *     });
+	             */
+	            mixIn: function (properties) {
+	                for (var propertyName in properties) {
+	                    if (properties.hasOwnProperty(propertyName)) {
+	                        this[propertyName] = properties[propertyName];
+	                    }
+	                }
+
+	                // IE won't copy toString using the loop above
+	                if (properties.hasOwnProperty('toString')) {
+	                    this.toString = properties.toString;
+	                }
+	            },
+
+	            /**
+	             * Creates a copy of this object.
+	             *
+	             * @return {Object} The clone.
+	             *
+	             * @example
+	             *
+	             *     var clone = instance.clone();
+	             */
+	            clone: function () {
+	                return this.init.prototype.extend(this);
+	            }
+	        };
+	    }());
+
+	    /**
+	     * An array of 32-bit words.
+	     *
+	     * @property {Array} words The array of 32-bit words.
+	     * @property {number} sigBytes The number of significant bytes in this word array.
+	     */
+	    var WordArray = C_lib.WordArray = Base.extend({
+	        /**
+	         * Initializes a newly created word array.
+	         *
+	         * @param {Array} words (Optional) An array of 32-bit words.
+	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.lib.WordArray.create();
+	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+	         */
+	        init: function (words, sigBytes) {
+	            words = this.words = words || [];
+
+	            if (sigBytes != undefined) {
+	                this.sigBytes = sigBytes;
+	            } else {
+	                this.sigBytes = words.length * 4;
+	            }
+	        },
+
+	        /**
+	         * Converts this word array to a string.
+	         *
+	         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+	         *
+	         * @return {string} The stringified word array.
+	         *
+	         * @example
+	         *
+	         *     var string = wordArray + '';
+	         *     var string = wordArray.toString();
+	         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
+	         */
+	        toString: function (encoder) {
+	            return (encoder || Hex).stringify(this);
+	        },
+
+	        /**
+	         * Concatenates a word array to this word array.
+	         *
+	         * @param {WordArray} wordArray The word array to append.
+	         *
+	         * @return {WordArray} This word array.
+	         *
+	         * @example
+	         *
+	         *     wordArray1.concat(wordArray2);
+	         */
+	        concat: function (wordArray) {
+	            // Shortcuts
+	            var thisWords = this.words;
+	            var thatWords = wordArray.words;
+	            var thisSigBytes = this.sigBytes;
+	            var thatSigBytes = wordArray.sigBytes;
+
+	            // Clamp excess bits
+	            this.clamp();
+
+	            // Concat
+	            if (thisSigBytes % 4) {
+	                // Copy one byte at a time
+	                for (var i = 0; i < thatSigBytes; i++) {
+	                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+	                }
+	            } else {
+	                // Copy one word at a time
+	                for (var j = 0; j < thatSigBytes; j += 4) {
+	                    thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
+	                }
+	            }
+	            this.sigBytes += thatSigBytes;
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Removes insignificant bits.
+	         *
+	         * @example
+	         *
+	         *     wordArray.clamp();
+	         */
+	        clamp: function () {
+	            // Shortcuts
+	            var words = this.words;
+	            var sigBytes = this.sigBytes;
+
+	            // Clamp
+	            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+	            words.length = Math.ceil(sigBytes / 4);
+	        },
+
+	        /**
+	         * Creates a copy of this word array.
+	         *
+	         * @return {WordArray} The clone.
+	         *
+	         * @example
+	         *
+	         *     var clone = wordArray.clone();
+	         */
+	        clone: function () {
+	            var clone = Base.clone.call(this);
+	            clone.words = this.words.slice(0);
+
+	            return clone;
+	        },
+
+	        /**
+	         * Creates a word array filled with random bytes.
+	         *
+	         * @param {number} nBytes The number of random bytes to generate.
+	         *
+	         * @return {WordArray} The random word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.lib.WordArray.random(16);
+	         */
+	        random: function (nBytes) {
+	            var words = [];
+
+	            for (var i = 0; i < nBytes; i += 4) {
+	                words.push(cryptoSecureRandomInt());
+	            }
+
+	            return new WordArray.init(words, nBytes);
+	        }
+	    });
+
+	    /**
+	     * Encoder namespace.
+	     */
+	    var C_enc = C.enc = {};
+
+	    /**
+	     * Hex encoding strategy.
+	     */
+	    var Hex = C_enc.Hex = {
+	        /**
+	         * Converts a word array to a hex string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The hex string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var hexChars = [];
+	            for (var i = 0; i < sigBytes; i++) {
+	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                hexChars.push((bite >>> 4).toString(16));
+	                hexChars.push((bite & 0x0f).toString(16));
+	            }
+
+	            return hexChars.join('');
+	        },
+
+	        /**
+	         * Converts a hex string to a word array.
+	         *
+	         * @param {string} hexStr The hex string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
+	         */
+	        parse: function (hexStr) {
+	            // Shortcut
+	            var hexStrLength = hexStr.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < hexStrLength; i += 2) {
+	                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+	            }
+
+	            return new WordArray.init(words, hexStrLength / 2);
+	        }
+	    };
+
+	    /**
+	     * Latin1 encoding strategy.
+	     */
+	    var Latin1 = C_enc.Latin1 = {
+	        /**
+	         * Converts a word array to a Latin1 string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The Latin1 string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var latin1Chars = [];
+	            for (var i = 0; i < sigBytes; i++) {
+	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                latin1Chars.push(String.fromCharCode(bite));
+	            }
+
+	            return latin1Chars.join('');
+	        },
+
+	        /**
+	         * Converts a Latin1 string to a word array.
+	         *
+	         * @param {string} latin1Str The Latin1 string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+	         */
+	        parse: function (latin1Str) {
+	            // Shortcut
+	            var latin1StrLength = latin1Str.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < latin1StrLength; i++) {
+	                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+	            }
+
+	            return new WordArray.init(words, latin1StrLength);
+	        }
+	    };
+
+	    /**
+	     * UTF-8 encoding strategy.
+	     */
+	    var Utf8 = C_enc.Utf8 = {
+	        /**
+	         * Converts a word array to a UTF-8 string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The UTF-8 string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            try {
+	                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+	            } catch (e) {
+	                throw new Error('Malformed UTF-8 data');
+	            }
+	        },
+
+	        /**
+	         * Converts a UTF-8 string to a word array.
+	         *
+	         * @param {string} utf8Str The UTF-8 string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+	         */
+	        parse: function (utf8Str) {
+	            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+	        }
+	    };
+
+	    /**
+	     * Abstract buffered block algorithm template.
+	     *
+	     * The property blockSize must be implemented in a concrete subtype.
+	     *
+	     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+	     */
+	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+	        /**
+	         * Resets this block algorithm's data buffer to its initial state.
+	         *
+	         * @example
+	         *
+	         *     bufferedBlockAlgorithm.reset();
+	         */
+	        reset: function () {
+	            // Initial values
+	            this._data = new WordArray.init();
+	            this._nDataBytes = 0;
+	        },
+
+	        /**
+	         * Adds new data to this block algorithm's buffer.
+	         *
+	         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+	         *
+	         * @example
+	         *
+	         *     bufferedBlockAlgorithm._append('data');
+	         *     bufferedBlockAlgorithm._append(wordArray);
+	         */
+	        _append: function (data) {
+	            // Convert string to WordArray, else assume WordArray already
+	            if (typeof data == 'string') {
+	                data = Utf8.parse(data);
+	            }
+
+	            // Append
+	            this._data.concat(data);
+	            this._nDataBytes += data.sigBytes;
+	        },
+
+	        /**
+	         * Processes available data blocks.
+	         *
+	         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+	         *
+	         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+	         *
+	         * @return {WordArray} The processed data.
+	         *
+	         * @example
+	         *
+	         *     var processedData = bufferedBlockAlgorithm._process();
+	         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
+	         */
+	        _process: function (doFlush) {
+	            var processedWords;
+
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+	            var dataSigBytes = data.sigBytes;
+	            var blockSize = this.blockSize;
+	            var blockSizeBytes = blockSize * 4;
+
+	            // Count blocks ready
+	            var nBlocksReady = dataSigBytes / blockSizeBytes;
+	            if (doFlush) {
+	                // Round up to include partial blocks
+	                nBlocksReady = Math.ceil(nBlocksReady);
+	            } else {
+	                // Round down to include only full blocks,
+	                // less the number of blocks that must remain in the buffer
+	                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+	            }
+
+	            // Count words ready
+	            var nWordsReady = nBlocksReady * blockSize;
+
+	            // Count bytes ready
+	            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+	            // Process blocks
+	            if (nWordsReady) {
+	                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+	                    // Perform concrete-algorithm logic
+	                    this._doProcessBlock(dataWords, offset);
+	                }
+
+	                // Remove processed words
+	                processedWords = dataWords.splice(0, nWordsReady);
+	                data.sigBytes -= nBytesReady;
+	            }
+
+	            // Return processed words
+	            return new WordArray.init(processedWords, nBytesReady);
+	        },
+
+	        /**
+	         * Creates a copy of this object.
+	         *
+	         * @return {Object} The clone.
+	         *
+	         * @example
+	         *
+	         *     var clone = bufferedBlockAlgorithm.clone();
+	         */
+	        clone: function () {
+	            var clone = Base.clone.call(this);
+	            clone._data = this._data.clone();
+
+	            return clone;
+	        },
+
+	        _minBufferSize: 0
+	    });
+
+	    /**
+	     * Abstract hasher template.
+	     *
+	     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+	     */
+	    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+	        /**
+	         * Configuration options.
+	         */
+	        cfg: Base.extend(),
+
+	        /**
+	         * Initializes a newly created hasher.
+	         *
+	         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+	         *
+	         * @example
+	         *
+	         *     var hasher = CryptoJS.algo.SHA256.create();
+	         */
+	        init: function (cfg) {
+	            // Apply config defaults
+	            this.cfg = this.cfg.extend(cfg);
+
+	            // Set initial values
+	            this.reset();
+	        },
+
+	        /**
+	         * Resets this hasher to its initial state.
+	         *
+	         * @example
+	         *
+	         *     hasher.reset();
+	         */
+	        reset: function () {
+	            // Reset data buffer
+	            BufferedBlockAlgorithm.reset.call(this);
+
+	            // Perform concrete-hasher logic
+	            this._doReset();
+	        },
+
+	        /**
+	         * Updates this hasher with a message.
+	         *
+	         * @param {WordArray|string} messageUpdate The message to append.
+	         *
+	         * @return {Hasher} This hasher.
+	         *
+	         * @example
+	         *
+	         *     hasher.update('message');
+	         *     hasher.update(wordArray);
+	         */
+	        update: function (messageUpdate) {
+	            // Append
+	            this._append(messageUpdate);
+
+	            // Update the hash
+	            this._process();
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Finalizes the hash computation.
+	         * Note that the finalize operation is effectively a destructive, read-once operation.
+	         *
+	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+	         *
+	         * @return {WordArray} The hash.
+	         *
+	         * @example
+	         *
+	         *     var hash = hasher.finalize();
+	         *     var hash = hasher.finalize('message');
+	         *     var hash = hasher.finalize(wordArray);
+	         */
+	        finalize: function (messageUpdate) {
+	            // Final message update
+	            if (messageUpdate) {
+	                this._append(messageUpdate);
+	            }
+
+	            // Perform concrete-hasher logic
+	            var hash = this._doFinalize();
+
+	            return hash;
+	        },
+
+	        blockSize: 512/32,
+
+	        /**
+	         * Creates a shortcut function to a hasher's object interface.
+	         *
+	         * @param {Hasher} hasher The hasher to create a helper for.
+	         *
+	         * @return {Function} The shortcut function.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+	         */
+	        _createHelper: function (hasher) {
+	            return function (message, cfg) {
+	                return new hasher.init(cfg).finalize(message);
+	            };
+	        },
+
+	        /**
+	         * Creates a shortcut function to the HMAC's object interface.
+	         *
+	         * @param {Hasher} hasher The hasher to use in this HMAC helper.
+	         *
+	         * @return {Function} The shortcut function.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+	         */
+	        _createHmacHelper: function (hasher) {
+	            return function (message, key) {
+	                return new C_algo.HMAC.init(hasher, key).finalize(message);
+	            };
+	        }
+	    });
+
+	    /**
+	     * Algorithm namespace.
+	     */
+	    var C_algo = C.algo = {};
+
+	    return C;
+	}(Math));
+
+
+	return CryptoJS;
+
+}));

+ 18 - 0
lib/tqsdk/libs/hmac-sha256.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha256", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA256;
+
+}));

+ 143 - 0
lib/tqsdk/libs/hmac.js

@@ -0,0 +1,143 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var C_enc = C.enc;
+	    var Utf8 = C_enc.Utf8;
+	    var C_algo = C.algo;
+
+	    /**
+	     * HMAC algorithm.
+	     */
+	    var HMAC = C_algo.HMAC = Base.extend({
+	        /**
+	         * Initializes a newly created HMAC.
+	         *
+	         * @param {Hasher} hasher The hash algorithm to use.
+	         * @param {WordArray|string} key The secret key.
+	         *
+	         * @example
+	         *
+	         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
+	         */
+	        init: function (hasher, key) {
+	            // Init hasher
+	            hasher = this._hasher = new hasher.init();
+
+	            // Convert string to WordArray, else assume WordArray already
+	            if (typeof key == 'string') {
+	                key = Utf8.parse(key);
+	            }
+
+	            // Shortcuts
+	            var hasherBlockSize = hasher.blockSize;
+	            var hasherBlockSizeBytes = hasherBlockSize * 4;
+
+	            // Allow arbitrary length keys
+	            if (key.sigBytes > hasherBlockSizeBytes) {
+	                key = hasher.finalize(key);
+	            }
+
+	            // Clamp excess bits
+	            key.clamp();
+
+	            // Clone key for inner and outer pads
+	            var oKey = this._oKey = key.clone();
+	            var iKey = this._iKey = key.clone();
+
+	            // Shortcuts
+	            var oKeyWords = oKey.words;
+	            var iKeyWords = iKey.words;
+
+	            // XOR keys with pad constants
+	            for (var i = 0; i < hasherBlockSize; i++) {
+	                oKeyWords[i] ^= 0x5c5c5c5c;
+	                iKeyWords[i] ^= 0x36363636;
+	            }
+	            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
+
+	            // Set initial values
+	            this.reset();
+	        },
+
+	        /**
+	         * Resets this HMAC to its initial state.
+	         *
+	         * @example
+	         *
+	         *     hmacHasher.reset();
+	         */
+	        reset: function () {
+	            // Shortcut
+	            var hasher = this._hasher;
+
+	            // Reset
+	            hasher.reset();
+	            hasher.update(this._iKey);
+	        },
+
+	        /**
+	         * Updates this HMAC with a message.
+	         *
+	         * @param {WordArray|string} messageUpdate The message to append.
+	         *
+	         * @return {HMAC} This HMAC instance.
+	         *
+	         * @example
+	         *
+	         *     hmacHasher.update('message');
+	         *     hmacHasher.update(wordArray);
+	         */
+	        update: function (messageUpdate) {
+	            this._hasher.update(messageUpdate);
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Finalizes the HMAC computation.
+	         * Note that the finalize operation is effectively a destructive, read-once operation.
+	         *
+	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+	         *
+	         * @return {WordArray} The HMAC.
+	         *
+	         * @example
+	         *
+	         *     var hmac = hmacHasher.finalize();
+	         *     var hmac = hmacHasher.finalize('message');
+	         *     var hmac = hmacHasher.finalize(wordArray);
+	         */
+	        finalize: function (messageUpdate) {
+	            // Shortcut
+	            var hasher = this._hasher;
+
+	            // Compute HMAC
+	            var innerHash = hasher.finalize(messageUpdate);
+	            hasher.reset();
+	            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
+
+	            return hmac;
+	        }
+	    });
+	}());
+
+
+}));

+ 199 - 0
lib/tqsdk/libs/sha256.js

@@ -0,0 +1,199 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (Math) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var Hasher = C_lib.Hasher;
+	    var C_algo = C.algo;
+
+	    // Initialization and round constants tables
+	    var H = [];
+	    var K = [];
+
+	    // Compute constants
+	    (function () {
+	        function isPrime(n) {
+	            var sqrtN = Math.sqrt(n);
+	            for (var factor = 2; factor <= sqrtN; factor++) {
+	                if (!(n % factor)) {
+	                    return false;
+	                }
+	            }
+
+	            return true;
+	        }
+
+	        function getFractionalBits(n) {
+	            return ((n - (n | 0)) * 0x100000000) | 0;
+	        }
+
+	        var n = 2;
+	        var nPrime = 0;
+	        while (nPrime < 64) {
+	            if (isPrime(n)) {
+	                if (nPrime < 8) {
+	                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+	                }
+	                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+	                nPrime++;
+	            }
+
+	            n++;
+	        }
+	    }());
+
+	    // Reusable object
+	    var W = [];
+
+	    /**
+	     * SHA-256 hash algorithm.
+	     */
+	    var SHA256 = C_algo.SHA256 = Hasher.extend({
+	        _doReset: function () {
+	            this._hash = new WordArray.init(H.slice(0));
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcut
+	            var H = this._hash.words;
+
+	            // Working variables
+	            var a = H[0];
+	            var b = H[1];
+	            var c = H[2];
+	            var d = H[3];
+	            var e = H[4];
+	            var f = H[5];
+	            var g = H[6];
+	            var h = H[7];
+
+	            // Computation
+	            for (var i = 0; i < 64; i++) {
+	                if (i < 16) {
+	                    W[i] = M[offset + i] | 0;
+	                } else {
+	                    var gamma0x = W[i - 15];
+	                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
+	                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
+	                                   (gamma0x >>> 3);
+
+	                    var gamma1x = W[i - 2];
+	                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+	                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
+	                                   (gamma1x >>> 10);
+
+	                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+	                }
+
+	                var ch  = (e & f) ^ (~e & g);
+	                var maj = (a & b) ^ (a & c) ^ (b & c);
+
+	                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+	                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));
+
+	                var t1 = h + sigma1 + ch + K[i] + W[i];
+	                var t2 = sigma0 + maj;
+
+	                h = g;
+	                g = f;
+	                f = e;
+	                e = (d + t1) | 0;
+	                d = c;
+	                c = b;
+	                b = a;
+	                a = (t1 + t2) | 0;
+	            }
+
+	            // Intermediate hash value
+	            H[0] = (H[0] + a) | 0;
+	            H[1] = (H[1] + b) | 0;
+	            H[2] = (H[2] + c) | 0;
+	            H[3] = (H[3] + d) | 0;
+	            H[4] = (H[4] + e) | 0;
+	            H[5] = (H[5] + f) | 0;
+	            H[6] = (H[6] + g) | 0;
+	            H[7] = (H[7] + h) | 0;
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+	            data.sigBytes = dataWords.length * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Return final computed hash
+	            return this._hash;
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+	            clone._hash = this._hash.clone();
+
+	            return clone;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA256('message');
+	     *     var hash = CryptoJS.SHA256(wordArray);
+	     */
+	    C.SHA256 = Hasher._createHelper(SHA256);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA256(message, key);
+	     */
+	    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+	}(Math));
+
+
+	return CryptoJS.SHA256;
+
+}));

+ 8 - 0
lib/tqsdk/tq-game-config.js

@@ -0,0 +1,8 @@
+// 动态请求后端的数据 do = getTqConf
+module.exports = {
+  tq_appid: '',
+  tq_game_secret: '',
+
+  tb_cloudAppId: 57555, // 渠道方提供,淘宝小游戏专属,cloudAppId 为域名白名单配置后获取,在配置处查看具体参数。
+};
+

+ 130 - 0
lib/tqsdk/tq-lib.js

@@ -0,0 +1,130 @@
+const HmacSHA256 = require('./libs/hmac-sha256.js');
+const CryptoJS = require('./libs/core.js');
+const config = require('./tq-game-config.js');
+const payOrderApi = `https://sdk.tqhd123.cn/client/pay/order`; // 支付上报
+const payTypeApi = `https://sdk.tqhd123.cn/client/pay/channel`; // 支付类型
+const payResultApi = `https://sdk.tqhd123.cn/client/pay/order-result`; // 获取订单结果
+const payUrlApi = `https://sdk.tqhd123.cn/client/pay/exists-order-pay`; // 已创建订单接口,重新获取支付链接
+
+class TQ_LIB {
+  request = null;
+
+  constructor(props) {
+    this.request = props.request;
+  }
+
+  // 请求验签接口
+  requestSignApi = (parmas, api, cb) => {
+    const timestamp = new Date().getTime();
+    const nonce = randomString32();
+    const requestSign = getSign(parmas, config.tq_appid, timestamp, nonce);
+
+    if (!requestSign) {
+      cb({ status: 0, message: 'error' });
+      return;
+    }
+
+    if (!this.request) {
+      console.error('SDK 初始化错误【request】');
+      return;
+    }
+
+    this.request({
+      url: api,
+      data: parmas,
+      header: { sign: requestSign, timestamp: timestamp, nonce: nonce },
+      success: function (r) {
+        if (r.ret == 1) {
+          cb({ status: 1, message: 'success', data: r.content });
+        } else {
+          cb({ status: 0, message: r.msg });
+        }
+      },
+      fail: function (e) {
+        cb({ status: 0, message: e });
+      },
+    });
+  };
+
+  // 支付类型
+  getPayType = (cb) => {
+    const jOrderData = {
+      tq_app_id: config.tq_appid,
+    };
+
+    this.requestSignApi(jOrderData, payTypeApi, cb);
+  };
+
+  // 已创建订单接口,重新获取支付链接
+  getPayUrl = (orderInfo, cb) => {
+    const jOrderData = {
+      tq_app_id: config.tq_appid,
+      tq_order_sn: orderInfo.tq_order_sn,
+      ...orderInfo,
+    };
+
+    this.requestSignApi(jOrderData, payUrlApi, cb);
+  };
+
+  // 获取支付结果
+  getPayReult = (orderInfo, cb) => {
+    const jOrderData = {
+      tq_app_id: config.tq_appid,
+      tq_order_sn: orderInfo.tq_order_sn,
+      ...orderInfo,
+    };
+
+    this.requestSignApi(jOrderData, payResultApi, cb);
+  };
+
+  // 支付上报
+  showOrder = (orderInfo, cb) => {
+    const jOrderData = {
+      tq_app_id: config.tq_appid,
+      os: orderInfo.os || '',
+      game_order_sn: orderInfo.gameOrderId || '',
+      user_id: orderInfo.userId || '',
+      role_id: orderInfo.roleId || '',
+      role_name: orderInfo.roleName || '',
+      product_id: orderInfo.productId || '',
+      product_name: orderInfo.productName || '',
+      server_id: orderInfo.serverId || '',
+      server_name: orderInfo.serverName || '',
+      money: orderInfo.zfAmount || '',
+      extra: orderInfo.tp || '',
+      pay_channel_id: orderInfo.payChannelId || '',
+      company_order_sn: orderInfo.companyOrderId || '',
+      company_notify_url: orderInfo.companyNotifyUrl || '',
+      expire_timestamp_millis: orderInfo.expireTimestampMillis || '',
+      sync_notify_url: orderInfo.syncNotifyUrl || '',
+      cancel_url: orderInfo.cancelUrl || '',
+      use_company_order: orderInfo.useCompanyOrder || '',
+      ...orderInfo,
+    };
+
+    this.requestSignApi(jOrderData, payOrderApi, cb);
+  };
+}
+
+// 验签 - 随机生成 32 位字符串数字组合
+const randomString32 = () => {
+  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+  let result = '';
+  for (let i = 0; i < 32; i++) {
+    result += chars.charAt(Math.floor(Math.random() * chars.length));
+  }
+  return result;
+};
+
+// 验签 - 生成签名
+const getSign = (params, tq_app_id, timestamp, nonce) => {
+  try {
+    const paramsStr = JSON.stringify(params);
+
+    return HmacSHA256(paramsStr + tq_app_id + timestamp + nonce, config.tq_game_secret).toString(CryptoJS.enc.Hex);
+  } catch (error) {
+    console.log(error);
+  }
+};
+
+module.exports = { TQ_LIB };

+ 26 - 0
lib/tqsdk/weixin-tq-game.js

@@ -0,0 +1,26 @@
+const { TQ_LIB } = require('./tq-lib');
+
+const request = ({ url, data, success, fail, method, header }) => {
+  console.log('-----start request------');
+
+  wx.request({
+    url: url,
+    data: JSON.stringify(data),
+    method: method || 'POST',
+    header: { 'Content-Type': 'application/json', ...header } || { 'Content-Type': 'application/json' },
+    success: function (e) {
+      if (e.statusCode == 200) {
+        success && success(e.data);
+      } else {
+        fail && fail(e);
+      }
+    },
+    fail: function (e) {
+      fail && fail(e);
+    },
+  });
+};
+
+const tqLib = new TQ_LIB({ request });
+
+module.exports = tqLib;

+ 26 - 0
model/GzhPayConfigModel.js

@@ -0,0 +1,26 @@
+import base from './base.js'
+
+class GzhPayConfigModel extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'gzhPayConfig'
+    this.defaultInfo = {
+        sessionFrom: '',
+        showMessageCard: true,
+        sendMessageImg:'',
+        sendMessageTitle:'',
+        sendMessagePath:'',
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!GzhPayConfigModel.instance) {
+        GzhPayConfigModel.instance = new GzhPayConfigModel(config)
+      return GzhPayConfigModel.instance
+    }
+    return GzhPayConfigModel.instance
+  }
+}
+
+export default GzhPayConfigModel

+ 23 - 0
model/IpInfoModel.js

@@ -0,0 +1,23 @@
+import base from './base.js'
+
+class IpInfoModel extends base{
+    constructor(config) {
+        super();
+        this.storageKey = 'ip';
+        this.defaultInfo = {
+            'ipv4': '',
+            'ipv6': '',
+        }
+        this.load(config)
+    }
+
+    static getInstance(config) {
+      if (!IpInfoModel.instance) {
+        IpInfoModel.instance = new IpInfoModel(config)
+        return IpInfoModel.instance
+      }
+      return IpInfoModel.instance
+    }
+}
+
+export default IpInfoModel;

+ 26 - 0
model/MidasPayConfigModel.js

@@ -0,0 +1,26 @@
+import base from './base.js'
+
+class MidasPayConfigModel extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'midasPayConfig'
+    this.defaultInfo = {
+      offerId: '',
+      env: 1, //0正式环境,1测试环境
+      rate: '',
+      zoneId: 0,
+      buyQuantity: '',
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!MidasPayConfigModel.instance) {
+      MidasPayConfigModel.instance = new MidasPayConfigModel(config)
+      return MidasPayConfigModel.instance
+    }
+    return MidasPayConfigModel.instance
+  }
+}
+
+export default MidasPayConfigModel

+ 29 - 0
model/OrderInfoModel.js

@@ -0,0 +1,29 @@
+import base from './base.js'
+
+class OrderInfoModel extends base{
+    constructor(config) {
+        super();
+        this.storageKey = 'orderInfo';
+        this.defaultInfo = {
+            'order_no': '',
+            'ext':'',
+            'amt':0, //金额
+            'buy_quantity':'',
+            'pay_type' : '',
+            'pop_content' : '',
+            'pop_title' : '',
+            'ios_pay_type' : '',
+        }
+        this.load(config)
+    }
+
+    static getInstance(config) {
+      if (!OrderInfoModel.instance) {
+        OrderInfoModel.instance = new OrderInfoModel(config)
+        return OrderInfoModel.instance
+      }
+      return OrderInfoModel.instance
+    }
+}
+
+export default OrderInfoModel;

+ 34 - 0
model/SdkLoginReUserInfoModel.js

@@ -0,0 +1,34 @@
+import base from './base.js'
+
+class SdkLoginReUserInfoModel extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'sdkLoginReUserInfo'
+    this.defaultInfo = {
+      access_token: '',
+      head_img_url: '',
+      nickname: '',
+      username: '',
+      fcm: 0,
+      uid: 0,
+      openid: '',
+      bind_phone:0, // 0 没绑定手机,1绑定手机
+      cp_appid: 0, //主包appid,研发校验登录态会用
+      appid:0, //子包appid,根据platform判断
+      mobile: '', //绑定手机号
+      pop_content: '', //弹窗内容
+      pop_title: '', //弹窗标题
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!SdkLoginReUserInfoModel.instance) {
+      SdkLoginReUserInfoModel.instance = new SdkLoginReUserInfoModel(config)
+      return SdkLoginReUserInfoModel.instance
+    }
+    return SdkLoginReUserInfoModel.instance
+  }
+}
+
+export default SdkLoginReUserInfoModel

+ 25 - 0
model/ShareConfigModel.js

@@ -0,0 +1,25 @@
+import base from './base.js'
+
+class ShareConfigModel extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'shareConfig'
+    this.defaultInfo = {
+      title: '',
+      imageUrl: '',
+      query: '',
+      share_ext : '', //服务端需要拼接的参数
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!ShareConfigModel.instance) {
+      ShareConfigModel.instance = new ShareConfigModel(config)
+      return ShareConfigModel.instance
+    }
+    return ShareConfigModel.instance
+  }
+}
+
+export default ShareConfigModel

+ 23 - 0
model/SubscribeConfigModel.js

@@ -0,0 +1,23 @@
+import base from './base.js'
+
+class SubscribeConfig extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'subscribeConfig'
+    this.defaultInfo = {
+      pay: [],
+      login:[],
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!SubscribeConfig.instance) {
+      SubscribeConfig.instance = new SubscribeConfig(config)
+      return SubscribeConfig.instance
+    }
+    return SubscribeConfig.instance
+  }
+}
+
+export default SubscribeConfig

+ 25 - 0
model/XcxPayConfigModel.js

@@ -0,0 +1,25 @@
+import base from './base.js'
+
+class XcxPayConfig extends base {
+  constructor(config) {
+    super()
+    this.storageKey = 'xcxPayConfig'
+    this.defaultInfo = {
+      xcxAppid: '',
+      path:'',
+      extraData:{},//需要传递给目标小程序的数据
+      envVersion:'',
+    }
+    this.load(config)
+  }
+
+  static getInstance(config) {
+    if (!XcxPayConfig.instance) {
+      XcxPayConfig.instance = new XcxPayConfig(config)
+      return XcxPayConfig.instance
+    }
+    return XcxPayConfig.instance
+  }
+}
+
+export default XcxPayConfig

+ 105 - 0
model/base.js

@@ -0,0 +1,105 @@
+import {
+  getStorage,
+  setStorage,
+  removeStorage
+} from '../utils/index.js'
+
+class base {
+  constructor() {
+    this.storageKey = '';
+    this.storageInfo = {};
+    this.defaultInfo = {};
+  }
+
+  /**
+   * 装载属性,只会压入配置过的属性
+   * @param {*} obj 
+   */
+  load(obj) {
+    let info = {};
+    //合并,后覆盖前,所以必定有默认key
+    Object.assign(info, this.defaultInfo, obj)
+    for (let key in this.defaultInfo) {
+      if (typeof (info[key]) !== 'undefined') {
+        this.storageInfo[key] = info[key];
+      }
+    }
+  }
+
+  /**
+   * 追加
+   * @param {*} obj 
+   */
+  addInfo(obj) {
+    let info = {};
+    Object.assign(info, this.defaultInfo, this.storageInfo, obj)
+    for (let key in this.defaultInfo) {
+      if (typeof (info[key]) !== 'undefined') {
+        this.storageInfo[key] = info[key];
+      }
+    }
+  }
+
+  //获取类里面的属性
+  getInfo(key) {
+    if (key && (key in this.storageInfo)) {
+      return this.storageInfo[key]
+    } else {
+      return this.storageInfo
+    }
+  }
+
+  //保存到缓存,传进来>默认值
+  setStorage(obj) {
+    if (obj) {
+      this.load(obj);
+    }
+    if (!this.storageKey) {
+      return false;
+    }
+    if (Object.getOwnPropertyNames(this.storageInfo).length === 0) {
+      return false;
+    }
+
+    console.log('11111=>', this.storageKey)
+    console.log('22222=>', this.storageInfo)
+    setStorage(this.storageKey, this.storageInfo);
+  }
+
+  //追加到缓存,传进来>缓存>默认值
+  addStorage(obj) {
+    if (!this.storageKey) {
+      return false;
+    }
+    let info = {};
+    let curStorageInfo = getStorage(this.storageKey);
+    Object.assign(info, curStorageInfo, obj)
+    this.load(obj);
+    setStorage(this.storageKey, this.storageInfo);
+  }
+
+  //获取缓存的属性
+  getStorage(key) {
+    if (!this.storageKey) {
+      return false;
+    }
+    let info = getStorage(this.storageKey);
+    Object.assign(this.storageInfo, info)
+    if (key && (key in this.storageInfo)) {
+      return this.storageInfo[key]
+    } else {
+      return this.storageInfo
+    }
+  }
+
+  //销毁缓存的属性
+  destroyStorage() {
+    if (!this.storageKey) {
+      return false;
+    }
+    removeStorage(this.storageKey)
+    this.load();
+  }
+}
+
+export default base;

+ 2055 - 0
package-lock.json

@@ -0,0 +1,2055 @@
+{
+  "name": "wxxyx-ruiyu",
+  "version": "1.0.8",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "wxxyx-ruiyu",
+      "version": "1.0.8",
+      "license": "ISC",
+      "dependencies": {
+        "webpack": "^5.74.0",
+        "webpack-cli": "^4.10.0"
+      }
+    },
+    "node_modules/@discoveryjs/json-ext": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+      "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+      "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+      "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.17",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+      "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
+      }
+    },
+    "node_modules/@types/eslint": {
+      "version": "8.4.7",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz",
+      "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==",
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "node_modules/@types/eslint-scope": {
+      "version": "3.7.4",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
+      "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
+      "dependencies": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "0.0.51",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+      "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
+    },
+    "node_modules/@types/node": {
+      "version": "18.11.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
+      "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A=="
+    },
+    "node_modules/@webassemblyjs/ast": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+      "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+      "dependencies": {
+        "@webassemblyjs/helper-numbers": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+      "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ=="
+    },
+    "node_modules/@webassemblyjs/helper-api-error": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+      "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg=="
+    },
+    "node_modules/@webassemblyjs/helper-buffer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+      "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA=="
+    },
+    "node_modules/@webassemblyjs/helper-numbers": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+      "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+      "dependencies": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+      "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q=="
+    },
+    "node_modules/@webassemblyjs/helper-wasm-section": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+      "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/ieee754": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+      "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+      "dependencies": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "node_modules/@webassemblyjs/leb128": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+      "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+      "dependencies": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/utf8": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+      "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ=="
+    },
+    "node_modules/@webassemblyjs/wasm-edit": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+      "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/helper-wasm-section": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-opt": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "@webassemblyjs/wast-printer": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-gen": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+      "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-opt": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+      "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+      "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-printer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+      "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+      "dependencies": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webpack-cli/configtest": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+      "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+      "peerDependencies": {
+        "webpack": "4.x.x || 5.x.x",
+        "webpack-cli": "4.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/info": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+      "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+      "dependencies": {
+        "envinfo": "^7.7.3"
+      },
+      "peerDependencies": {
+        "webpack-cli": "4.x.x"
+      }
+    },
+    "node_modules/@webpack-cli/serve": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+      "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+      "peerDependencies": {
+        "webpack-cli": "4.x.x"
+      },
+      "peerDependenciesMeta": {
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+    },
+    "node_modules/@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+    },
+    "node_modules/acorn": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+      "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-import-assertions": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+      "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
+      "peerDependencies": {
+        "acorn": "^8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.21.4",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+      "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        }
+      ],
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001400",
+        "electron-to-chromium": "^1.4.251",
+        "node-releases": "^2.0.6",
+        "update-browserslist-db": "^1.0.9"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001423",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz",
+      "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        }
+      ]
+    },
+    "node_modules/chrome-trace-event": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
+      "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "dependencies": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/colorette": {
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+      "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.4.284",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
+      "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
+      "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/envinfo": {
+      "version": "7.8.1",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+      "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
+      "bin": {
+        "envinfo": "dist/cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/es-module-lexer": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+      "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ=="
+    },
+    "node_modules/escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/events": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+      "engines": {
+        "node": ">=0.8.x"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+    },
+    "node_modules/fastest-levenshtein": {
+      "version": "1.0.16",
+      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+      "engines": {
+        "node": ">= 4.9.1"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+    },
+    "node_modules/glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.10",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+      "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/import-local": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+      "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+      "dependencies": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      },
+      "bin": {
+        "import-local-fixture": "fixtures/cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/interpret": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+      "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+      "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "dependencies": {
+        "isobject": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+    },
+    "node_modules/isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "dependencies": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      }
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+    },
+    "node_modules/kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+      "engines": {
+        "node": ">=6.11.5"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+      "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/rechoir": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+      "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+      "dependencies": {
+        "resolve": "^1.9.0"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "dependencies": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "dependencies": {
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/schema-utils": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+      "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "dependencies": {
+        "kind-of": "^6.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tapable": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.15.1",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
+      "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.2",
+        "acorn": "^8.5.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/terser-webpack-plugin": {
+      "version": "5.3.6",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz",
+      "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==",
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.14",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^3.1.1",
+        "serialize-javascript": "^6.0.0",
+        "terser": "^5.14.1"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.1.0"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "esbuild": {
+          "optional": true
+        },
+        "uglify-js": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+      "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "browserslist-lint": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/watchpack": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+      "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+      "dependencies": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack": {
+      "version": "5.74.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
+      "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+      "dependencies": {
+        "@types/eslint-scope": "^3.7.3",
+        "@types/estree": "^0.0.51",
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/wasm-edit": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "acorn": "^8.7.1",
+        "acorn-import-assertions": "^1.7.6",
+        "browserslist": "^4.14.5",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.10.0",
+        "es-module-lexer": "^0.9.0",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.9",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.1.0",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.1.3",
+        "watchpack": "^2.4.0",
+        "webpack-sources": "^3.2.3"
+      },
+      "bin": {
+        "webpack": "bin/webpack.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependenciesMeta": {
+        "webpack-cli": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli": {
+      "version": "4.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+      "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+      "dependencies": {
+        "@discoveryjs/json-ext": "^0.5.0",
+        "@webpack-cli/configtest": "^1.2.0",
+        "@webpack-cli/info": "^1.5.0",
+        "@webpack-cli/serve": "^1.7.0",
+        "colorette": "^2.0.14",
+        "commander": "^7.0.0",
+        "cross-spawn": "^7.0.3",
+        "fastest-levenshtein": "^1.0.12",
+        "import-local": "^3.0.2",
+        "interpret": "^2.2.0",
+        "rechoir": "^0.7.0",
+        "webpack-merge": "^5.7.3"
+      },
+      "bin": {
+        "webpack-cli": "bin/cli.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "4.x.x || 5.x.x"
+      },
+      "peerDependenciesMeta": {
+        "@webpack-cli/generators": {
+          "optional": true
+        },
+        "@webpack-cli/migrate": {
+          "optional": true
+        },
+        "webpack-bundle-analyzer": {
+          "optional": true
+        },
+        "webpack-dev-server": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-cli/node_modules/commander": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+      "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/webpack-merge": {
+      "version": "5.8.0",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
+      "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
+      "dependencies": {
+        "clone-deep": "^4.0.1",
+        "wildcard": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wildcard": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+      "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw=="
+    }
+  },
+  "dependencies": {
+    "@discoveryjs/json-ext": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+      "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="
+    },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+      "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+      "requires": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
+    },
+    "@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
+    },
+    "@jridgewell/source-map": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+      "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+      "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.17",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+      "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+      "requires": {
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
+      }
+    },
+    "@types/eslint": {
+      "version": "8.4.7",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz",
+      "integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==",
+      "requires": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "@types/eslint-scope": {
+      "version": "3.7.4",
+      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
+      "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
+      "requires": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "0.0.51",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+      "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
+    },
+    "@types/json-schema": {
+      "version": "7.0.11",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
+    },
+    "@types/node": {
+      "version": "18.11.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
+      "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A=="
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+      "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+      "requires": {
+        "@webassemblyjs/helper-numbers": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+      "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ=="
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+      "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg=="
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+      "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA=="
+    },
+    "@webassemblyjs/helper-numbers": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+      "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+      "requires": {
+        "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+      "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q=="
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+      "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+      "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+      "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+      "requires": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+      "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ=="
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+      "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/helper-wasm-section": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-opt": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "@webassemblyjs/wast-printer": "1.11.1"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+      "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+      "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-buffer": "1.11.1",
+        "@webassemblyjs/wasm-gen": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+      "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/helper-api-error": "1.11.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+        "@webassemblyjs/ieee754": "1.11.1",
+        "@webassemblyjs/leb128": "1.11.1",
+        "@webassemblyjs/utf8": "1.11.1"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+      "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+      "requires": {
+        "@webassemblyjs/ast": "1.11.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webpack-cli/configtest": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+      "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+      "requires": {}
+    },
+    "@webpack-cli/info": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+      "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+      "requires": {
+        "envinfo": "^7.7.3"
+      }
+    },
+    "@webpack-cli/serve": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+      "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+      "requires": {}
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+    },
+    "@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+    },
+    "acorn": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+      "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
+    },
+    "acorn-import-assertions": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+      "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
+      "requires": {}
+    },
+    "ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "requires": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "requires": {}
+    },
+    "browserslist": {
+      "version": "4.21.4",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+      "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
+      "requires": {
+        "caniuse-lite": "^1.0.30001400",
+        "electron-to-chromium": "^1.4.251",
+        "node-releases": "^2.0.6",
+        "update-browserslist-db": "^1.0.9"
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "caniuse-lite": {
+      "version": "1.0.30001423",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz",
+      "integrity": "sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ=="
+    },
+    "chrome-trace-event": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
+      "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
+    },
+    "clone-deep": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+      "requires": {
+        "is-plain-object": "^2.0.4",
+        "kind-of": "^6.0.2",
+        "shallow-clone": "^3.0.0"
+      }
+    },
+    "colorette": {
+      "version": "2.0.19",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+      "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="
+    },
+    "commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+    },
+    "cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "requires": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      }
+    },
+    "electron-to-chromium": {
+      "version": "1.4.284",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
+      "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
+    },
+    "enhanced-resolve": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
+      "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
+      "requires": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      }
+    },
+    "envinfo": {
+      "version": "7.8.1",
+      "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+      "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw=="
+    },
+    "es-module-lexer": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+      "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ=="
+    },
+    "escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
+    },
+    "eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "requires": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "requires": {
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
+        }
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
+    },
+    "events": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
+    },
+    "fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+    },
+    "fastest-levenshtein": {
+      "version": "1.0.16",
+      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+    },
+    "glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+    },
+    "graceful-fs": {
+      "version": "4.2.10",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+      "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+    },
+    "import-local": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+      "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+      "requires": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      }
+    },
+    "interpret": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+      "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw=="
+    },
+    "is-core-module": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+      "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-plain-object": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+      "requires": {
+        "isobject": "^3.0.1"
+      }
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+    },
+    "isobject": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+      "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
+    },
+    "jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "requires": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      }
+    },
+    "json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+    },
+    "kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+    },
+    "loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
+    "merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+    },
+    "mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+    },
+    "mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "requires": {
+        "mime-db": "1.52.0"
+      }
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+    },
+    "node-releases": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+      "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+    },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+    },
+    "path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "requires": {
+        "find-up": "^4.0.0"
+      }
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "rechoir": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+      "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+      "requires": {
+        "resolve": "^1.9.0"
+      }
+    },
+    "resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "requires": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "requires": {
+        "resolve-from": "^5.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+    },
+    "schema-utils": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+      "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+      "requires": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      }
+    },
+    "serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "shallow-clone": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+      "requires": {
+        "kind-of": "^6.0.2"
+      }
+    },
+    "shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "requires": {
+        "shebang-regex": "^3.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+    },
+    "source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "requires": {
+        "has-flag": "^4.0.0"
+      }
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+    },
+    "tapable": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
+    },
+    "terser": {
+      "version": "5.15.1",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
+      "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
+      "requires": {
+        "@jridgewell/source-map": "^0.3.2",
+        "acorn": "^8.5.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "5.3.6",
+      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz",
+      "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==",
+      "requires": {
+        "@jridgewell/trace-mapping": "^0.3.14",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^3.1.1",
+        "serialize-javascript": "^6.0.0",
+        "terser": "^5.14.1"
+      }
+    },
+    "update-browserslist-db": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+      "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+      "requires": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      }
+    },
+    "uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "watchpack": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+      "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+      "requires": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      }
+    },
+    "webpack": {
+      "version": "5.74.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
+      "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+      "requires": {
+        "@types/eslint-scope": "^3.7.3",
+        "@types/estree": "^0.0.51",
+        "@webassemblyjs/ast": "1.11.1",
+        "@webassemblyjs/wasm-edit": "1.11.1",
+        "@webassemblyjs/wasm-parser": "1.11.1",
+        "acorn": "^8.7.1",
+        "acorn-import-assertions": "^1.7.6",
+        "browserslist": "^4.14.5",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.10.0",
+        "es-module-lexer": "^0.9.0",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.9",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.1.0",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.1.3",
+        "watchpack": "^2.4.0",
+        "webpack-sources": "^3.2.3"
+      }
+    },
+    "webpack-cli": {
+      "version": "4.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+      "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+      "requires": {
+        "@discoveryjs/json-ext": "^0.5.0",
+        "@webpack-cli/configtest": "^1.2.0",
+        "@webpack-cli/info": "^1.5.0",
+        "@webpack-cli/serve": "^1.7.0",
+        "colorette": "^2.0.14",
+        "commander": "^7.0.0",
+        "cross-spawn": "^7.0.3",
+        "fastest-levenshtein": "^1.0.12",
+        "import-local": "^3.0.2",
+        "interpret": "^2.2.0",
+        "rechoir": "^0.7.0",
+        "webpack-merge": "^5.7.3"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+          "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
+        }
+      }
+    },
+    "webpack-merge": {
+      "version": "5.8.0",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
+      "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
+      "requires": {
+        "clone-deep": "^4.0.1",
+        "wildcard": "^2.0.0"
+      }
+    },
+    "webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w=="
+    },
+    "which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "wildcard": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+      "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw=="
+    }
+  }
+}

+ 27 - 0
package.json

@@ -0,0 +1,27 @@
+{
+  "name": "wxxyx-ruiyu",
+  "version": "1.0.3",
+  "description": "ry xyx sdk",
+  "scripts": {
+    "dev": "cross-env TQ_SDK=false webpack  --mode production --watch --progress",
+    "dev:tq": "cross-env TQ_SDK=true webpack  --mode production --watch --progress",
+    "build": "cross-env TQ_SDK=false webpack --mode production --progress",
+    "build:tq": "cross-env TQ_SDK=true webpack --mode production --progress"
+  },
+  "author": "",
+  "license": "ISC",
+  "directories": {
+    "lib": "lib"
+  },
+  "dependencies": {
+    "webpack": "^5.74.0",
+    "webpack-cli": "^4.10.0"
+  },
+  "devDependencies": {
+    "cross-env": "^7.0.3"
+  },
+  "volta": {
+    "node": "16.17.0",
+    "npm": "8.15.0"
+  }
+}

+ 82 - 0
project.config.json

@@ -0,0 +1,82 @@
+{
+  "description": "项目配置文件",
+  "setting": {
+    "urlCheck": false,
+    "es6": true,
+    "enhance": true,
+    "postcss": true,
+    "preloadBackgroundData": false,
+    "minified": false,
+    "newFeature": false,
+    "coverView": true,
+    "nodeModules": true,
+    "autoAudits": false,
+    "showShadowRootInWxmlPanel": true,
+    "scopeDataCheck": false,
+    "uglifyFileName": false,
+    "checkInvalidKey": true,
+    "checkSiteMap": true,
+    "uploadWithSourceMap": true,
+    "compileHotReLoad": false,
+    "lazyloadPlaceholderEnable": false,
+    "useMultiFrameRuntime": true,
+    "useApiHook": true,
+    "useApiHostProcess": true,
+    "babelSetting": {
+      "ignore": [],
+      "disablePlugins": [],
+      "outputPath": ""
+    },
+    "useIsolateContext": true,
+    "userConfirmedUseIsolateContext": true,
+    "userConfirmedBundleSwitch": false,
+    "packNpmManually": true,
+    "packNpmRelationList": [
+      {
+        "packageJsonPath": "./package.json",
+        "miniprogramNpmDistDir": "./"
+      }
+    ],
+    "minifyWXSS": true,
+    "disableUseStrict": false,
+    "minifyWXML": true,
+    "showES6CompileOption": false,
+    "useCompilerPlugins": false,
+    "ignoreUploadUnusedFiles": true,
+    "condition": false,
+    "compileWorklet": false,
+    "localPlugins": false,
+    "swc": false,
+    "disableSWC": true
+  },
+  "compileType": "game",
+  "cloudfunctionTemplateRoot": "",
+  "simulatorType": "wechat",
+  "simulatorPluginLibVersion": {},
+  "editorSetting": {
+    "tabIndent": "insertSpaces",
+    "tabSize": 2
+  },
+  "libVersion": "2.26.2",
+  "packOptions": {
+    "ignore": [],
+    "include": []
+  },
+  "appid": "wxa0167e87cc5efae3",
+  "projectname": "minigame-1",
+  "condition": {
+    "plugin": {
+      "list": []
+    },
+    "game": {
+      "list": []
+    },
+    "gamePlugin": {
+      "list": []
+    },
+    "miniprogram": {
+      "list": []
+    }
+  },
+  "isGameTourist": false
+}

+ 42 - 0
project.private.config.json

@@ -0,0 +1,42 @@
+{
+  "setting": {
+    "urlCheck": false,
+    "coverView": true,
+    "lazyloadPlaceholderEnable": false,
+    "skylineRenderEnable": false,
+    "preloadBackgroundData": false,
+    "autoAudits": false,
+    "useApiHook": true,
+    "useApiHostProcess": true,
+    "showShadowRootInWxmlPanel": true,
+    "useStaticServer": false,
+    "useLanDebug": false,
+    "showES6CompileOption": false,
+    "compileHotReLoad": false,
+    "checkInvalidKey": true,
+    "ignoreDevUnusedFiles": true,
+    "bigPackageSizeSupport": false,
+    "useIsolateContext": true
+  },
+  "condition": {
+    "game": {
+      "list": [
+        {
+          "pathName": "",
+          "name": "ceshi",
+          "query": "agent_id=1000&site_id=1000&gdt_vid=asdasd&weixinadinfo=asdasd",
+          "scene": null
+        },
+        {
+          "pathName": "",
+          "name": "dev",
+          "query": "xiaolin=123456789&xl=12345678",
+          "scene": 1011
+        }
+      ]
+    }
+  },
+  "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
+  "libVersion": "2.26.2",
+  "projectname": "wxxyx-sdk%EF%BC%88ry%EF%BC%89"
+}

+ 459 - 0
src/ad.js

@@ -0,0 +1,459 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-12 12:09:56
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-26 18:09:45
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\ad.js
+ */
+import request from "../utils/request.js"
+import {randomString} from "../utils/index.js"
+
+/**
+ * @description: 创建广告
+ * @return {*}
+ */
+let ad_life_id = null
+export const createAd = async (data) => {
+  try {
+    console.log("createAd入参" + JSON.stringify(data))
+    const res = await request.api("COMMON", {
+      do: "getWxGameAd",
+      ...data,
+    })
+    ad_life_id = randomString(16)
+    switch (res.ad_type) {
+      case "video":
+        //激励视频广告
+        await createRewardedVideoAd(res)
+        break
+      case "interstitial":
+        //插屏广告
+        await createInterstitialAd(res)
+        break
+      case "grid":
+        //(格子) 广告
+        await createGridAd(res)
+        break
+      case "custom":
+        //原生模板广告
+        await createCustomAd(res)
+        break
+      case "banner":
+      default:
+        //banner 广告
+        await createBannerAd(res)
+        break
+    }
+    return Promise.resolve(res)
+  } catch (error) {
+    return Promise.reject(error)
+  }
+}
+//激励视频广告
+const createRewardedVideoAd = (res) => {
+  return new Promise((resolve, reject) => {
+    let rewardedVideoAd = wx.createRewardedVideoAd({
+      adUnitId: res.ad_unit_id,
+    })
+    rewardedVideoAd
+      .show()
+      .then(() => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10003,
+          content: "",
+          ad_life_id: ad_life_id,
+        })
+        // resolve();
+      })
+      .catch((error) => {
+        rewardedVideoAd.load()
+          .then(() => {
+            rewardedVideoAd.show().then(() => {
+              upWxGameAdLog({
+                ad_unit_id: res.ad_unit_id,
+                ad_type: res.ad_type,
+                result: 1,
+                code: 10003,
+                content: "",
+                ad_life_id: ad_life_id,
+              })
+            }).catch((error) => {
+              upWxGameAdLog({
+                ad_unit_id: res.ad_unit_id,
+                ad_type: res.ad_type,
+                result: 0,
+                code: 10004,
+                content: JSON.stringify(error),
+                ad_life_id: ad_life_id,
+              })
+              // rewardedVideoAd.load();
+              reject(error)
+            })
+          })
+      })
+    // 此处有毒,千万别按微信文档上方法,不然onLoad会多次叠加,需要用offLoad消除事件
+    if (rewardedVideoAd.loadHandler) {
+      rewardedVideoAd.offLoad(rewardedVideoAd.loadHandler)
+    }
+    rewardedVideoAd.loadHandler = function () {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10001,
+        content: "",
+        ad_life_id: ad_life_id,
+      })
+    }
+    rewardedVideoAd.onLoad(rewardedVideoAd.loadHandler)
+
+    rewardedVideoAd.onError((error) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10002,
+        content: JSON.stringify(error),
+        ad_life_id: ad_life_id,
+      })
+      rewardedVideoAd.offError()
+      reject(error)
+    })
+
+    // 此处有毒,千万别按微信文档上方法,不然onClose会多次叠加,需要用offClose消除事件
+    if (rewardedVideoAd.closeHandler) {
+      rewardedVideoAd.offClose(rewardedVideoAd.closeHandler)
+    }
+    rewardedVideoAd.closeHandler = function (rest) {
+      console.log(rest)
+      // 用户点击了【关闭广告】按钮
+      if (rest && rest.isEnded || rest === undefined) {
+        // 正常播放结束,可以下发奖励
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10005,
+          content: JSON.stringify({
+            msg: '正常播放结束'
+          }),
+          ad_life_id: ad_life_id,
+        })
+        resolve(rest)
+      } else {
+        //提前关闭小程序
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10005,
+          content: JSON.stringify({
+            msg: '提前关闭'
+          }),
+          ad_life_id: ad_life_id,
+        })
+        reject(rest)
+      }
+    }
+    rewardedVideoAd.onClose(rewardedVideoAd.closeHandler)
+  })
+}
+//插屏广告
+const createInterstitialAd = (res) => {
+  return new Promise((resolve, reject) => {
+    let interstitialAd = wx.createInterstitialAd({
+      adUnitId: res.ad_unit_id,
+    })
+    interstitialAd
+      .show()
+      .then(() => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10003,
+          content: "",
+          ad_life_id: ad_life_id,
+        })
+        resolve()
+      })
+      .catch((error) => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 0,
+          code: 10004,
+          content: JSON.stringify(error),
+          ad_life_id: ad_life_id,
+        })
+        reject(error)
+      })
+
+    interstitialAd.onLoad(() => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10001,
+        content: "",
+        ad_life_id: ad_life_id,
+      })
+    })
+    interstitialAd.onError((error) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10002,
+        content: JSON.stringify(error),
+        ad_life_id: ad_life_id,
+      })
+      interstitialAd.offError()
+      reject(error)
+    })
+    interstitialAd.onClose(rest => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 1,
+        code: 10005,
+        content: JSON.stringify(rest),
+        ad_life_id: ad_life_id,
+      })
+    })
+  })
+}
+//(格子) 广告
+const createGridAd = (res) => {
+  return new Promise((resolve, reject) => {
+    let GridAd = wx.createGridAd({
+      adUnitId: res.ad_unit_id,
+      adTheme: res.adTheme,
+      gridCount: res.gridCount,
+      style: {
+        left: res.left,
+        top: res.top,
+        width: res.width,
+        opacity: res.opacity,
+      },
+    })
+    GridAd.show()
+      .then(() => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10003,
+          content: "",
+          ad_life_id: ad_life_id,
+        })
+        resolve()
+      })
+      .catch((error) => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 0,
+          code: 10004,
+          content: JSON.stringify(error),
+          ad_life_id: ad_life_id,
+        })
+        reject(error)
+      })
+    GridAd.onLoad(() => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10001,
+        content: "",
+        ad_life_id: ad_life_id,
+      })
+    })
+    GridAd.onError((error) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10002,
+        content: JSON.stringify(error),
+        ad_life_id: ad_life_id,
+      })
+      GridAd.offError()
+      reject(error)
+    })
+    GridAd.onResize((resq) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 1,
+        code: 10006,
+        content: JSON.stringify({
+          width: resq.width,
+          height: resq.height
+        }),
+        ad_life_id: ad_life_id,
+      })
+    })
+  })
+}
+
+//原生模板广告
+const createCustomAd = (res) => {
+  return new Promise((resolve, reject) => {
+    let customAd = wx.createCustomAd({
+      adUnitId: res.ad_unit_id,
+      style: {
+        left: res.left,
+        top: res.top,
+        width: res.width, // 用于设置组件宽度,只有部分模板才支持,如矩阵格子模板
+        fixed: true, // fixed 只适用于小程序环境
+      },
+    })
+    customAd
+      .show()
+      .then(() => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10003,
+          content: "",
+          ad_life_id: ad_life_id,
+        })
+        resolve()
+      })
+      .catch((error) => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 0,
+          code: 10004,
+          content: JSON.stringify(error),
+          ad_life_id: ad_life_id,
+        })
+        reject(error)
+      })
+    customAd.onLoad(() => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10001,
+        content: "",
+        ad_life_id: ad_life_id,
+      })
+    })
+    customAd.onError((error) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10002,
+        content: JSON.stringify(error),
+        ad_life_id: ad_life_id,
+      })
+      customAd.offError()
+      reject(error)
+    })
+    customAd.onClose(rest => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 1,
+        code: 10005,
+        content: JSON.stringify(rest),
+        ad_life_id: ad_life_id,
+      })
+    })
+  })
+}
+//banner 广告
+const createBannerAd = (res) => {
+  return new Promise((resolve, reject) => {
+    let bannerAd = wx.createBannerAd({
+      adUnitId: res.ad_unit_id,
+      style: {
+        left: res.left,
+        top: res.top,
+        width: res.width,
+      },
+    })
+    bannerAd
+      .show()
+      .then(() => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 1,
+          code: 10003,
+          content: "",
+          ad_life_id: ad_life_id,
+        })
+        resolve()
+      })
+      .catch((error) => {
+        upWxGameAdLog({
+          ad_unit_id: res.ad_unit_id,
+          ad_type: res.ad_type,
+          result: 0,
+          code: 10004,
+          content: JSON.stringify(error),
+          ad_life_id: ad_life_id,
+        })
+        reject(error)
+      })
+    bannerAd.onLoad(() => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10001,
+        content: "",
+        ad_life_id: ad_life_id,
+      })
+    })
+    bannerAd.onError((error) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 0,
+        code: 10002,
+        content: JSON.stringify(error),
+        ad_life_id: ad_life_id,
+      })
+      bannerAd.offError()
+      reject(error)
+    })
+    bannerAd.onResize((resq) => {
+      upWxGameAdLog({
+        ad_unit_id: res.ad_unit_id,
+        ad_type: res.ad_type,
+        result: 1,
+        code: 10006,
+        content: JSON.stringify({
+          width: resq.width,
+          height: resq.height
+        }),
+        ad_life_id: ad_life_id,
+      })
+    })
+  })
+}
+
+// 流量变现打点日志
+export const upWxGameAdLog = async (data) => {
+  try {
+    const res = await request.api("COMMON", {
+      do: "upWxGameAdLog",
+      ...data,
+    })
+    return Promise.resolve(res)
+  } catch (error) {
+    return Promise.reject(error)
+  }
+}

+ 68 - 0
src/bindPhone.js

@@ -0,0 +1,68 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-12 12:09:56
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 15:38:28
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\bindPhone.js
+ */
+import request from "../utils/request.js";
+import { checkLoginStatus } from "../src/login.js";
+
+/**
+ * @description: 绑定手机号
+ * @param {
+      phone: "1341341340",
+      code: "123456"
+    } data
+ * @return {*}
+ */
+export const bindPhone = async (data) => {
+    console.log("bindPhone入参"+JSON.stringify(data));
+    try {
+        const needValus = ["phone", "code"];
+        needValus.forEach((value) => {
+            if (data[value] === undefined) {
+                return Promise.reject({
+                    msg: `invalid ${value}`,
+                });
+            }
+        });
+        const res = await request.api("COMMON", {
+            do: "bindPhone",
+            phone: data.phone,
+            code: data.code,
+        });
+        //要重新获取一次用户信息
+        await checkLoginStatus();
+        return Promise.resolve(res);
+    } catch (error) {
+        return Promise.reject(error);
+    }
+};
+
+/**
+ * @description: 获取手机验证码
+ * @param {
+      phone: "1341341340"
+    } data
+ * @return {*}
+ */
+export const getBindPhoneCode = async (data) => {
+    console.log("getBindPhoneCode入参"+JSON.stringify(data));
+    try {
+        const needValus = ["phone"];
+        needValus.forEach((value) => {
+            if (data[value] === undefined) {
+                return Promise.reject(`invalid ${value}`);
+            }
+        });
+        const res = await request.api("COMMON", {
+            do: "getBindPhoneCode",
+            phone: data.phone,
+        });
+        return Promise.resolve(res);
+    } catch (error) {
+        return Promise.reject(error);
+    }
+};

+ 108 - 0
src/dataReport.js

@@ -0,0 +1,108 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-21 12:21:57
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 15:40:56
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\dataReport.js
+ */
+import request from "../utils/request.js";
+import { getSystem } from "../utils/index.js";
+import gameConfig from "../config/game.js";
+import SdkLoginReUserInfoModel from "../model/SdkLoginReUserInfoModel.js";
+import DnSdk from "../lib/DnSdk.js";
+
+/**
+ * @description:数据上报 
+ * @param {
+      'data_type': 3,
+      'server_id': 1,
+      'server_name': '测试1服',
+      'role_id': '10000111',
+      'role_name': '小威',
+      'role_level': 1,
+      'role_currency': 1000,
+    } data
+ * @return {*}
+ */
+export const dataReport = async (data) => {
+  console.log("dataReport入参" + JSON.stringify(data));
+  try {
+    // 对必须参数进行验证
+    const needValus = [
+      "data_type",
+      "server_id",
+      "server_name",
+      "role_id",
+      "role_name",
+      "role_level",
+      "role_currency",
+    ];
+    needValus.forEach((value) => {
+      if (data[value] === undefined) {
+        return Promise.reject({
+          msg: `invalid ${value}`,
+        });
+      }
+    });
+    if (data.data_type == 2) {
+      // 腾讯广告小游戏SDK上报
+      DnSdk.getInstance().onCreateRole();
+    }
+    if (data.data_type == 6 && data.event_type == "tutorial_finish") {
+      // 腾讯广告小游戏SDK上报
+      DnSdk.getInstance().onTutorialFinish();
+    }
+    // 获取系统信息
+    const systemInfo = await getSystem();
+    // 定义数据上报公共参数
+    let userInfo = SdkLoginReUserInfoModel.getInstance().getInfo();
+    const reportData = {
+      mtype: gameConfig.MTYPE,
+      userid: userInfo.uid,
+      dataType: data.data_type,
+      serverID: data.server_id,
+      serverName: data.server_name,
+      roleID: data.role_id,
+      roleName: data.role_name,
+      roleLevel: data.role_level,
+      role_create_time:
+        typeof data.role_create_time === "undefined"
+          ? ""
+          : data.role_create_time,
+      event_type: typeof data.event_type === "undefined" ? "" : data.event_type,
+      additional_parameters:
+        typeof data.additional_parameters === "undefined"
+          ? ""
+          : data.additional_parameters,
+      moneyNum:
+        typeof data.role_currency === "undefined" ? "" : data.role_currency,
+      time: typeof data.time === "undefined" ? "" : data.time,
+    };
+    // 定义额外上报数据及上报数据地址
+    let extData = {};
+    let reportUrl = "";
+    // 根据不同平台进行不同上报处理
+    reportData.appid = userInfo.appid;
+    switch (systemInfo.platform) {
+      case "ios":
+        extData.os = "ios";
+        reportUrl = "IOS_REPORT";
+        break;
+      case "android":
+      case "devtools":
+      default:
+        extData.os = "android";
+        reportUrl = "ANDROID_REPORT";
+        break;
+    }
+    // 合并请求参数并调用接口上报数据
+    Object.assign(reportData, extData);
+    // 执行数据上报
+    const res = await request.api(reportUrl, reportData, "post");
+    console.log("执行数据上报", res)
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};

+ 66 - 0
src/gameClub.js

@@ -0,0 +1,66 @@
+import GameClubModel from "../model/gameClubModel.js";
+import { compareVersion } from "../utils/index.js";
+const gameClubModel = new GameClubModel();
+export const createGameClubButton = async (config) => {
+  gameClubModel.createGameClubButton(config);
+};
+
+export const destroyGameClubButton = async () => {
+  gameClubModel.destroyGameClubButton();
+};
+
+export const hideGameClubButton = async () => {
+  gameClubModel.hideGameClubButton();
+};
+
+export const showGameClubButton = async () => {
+  gameClubModel.showGameClubButton();
+};
+
+export const onGameClubButtonTap = async (callback) => {
+  gameClubModel.onGameClubButtonTap(callback);
+};
+
+export const offGameClubButtonTap = async (callback) => {
+  gameClubModel.offGameClubButtonTap(callback);
+};
+
+// 推荐到游戏圈
+export const recommendToGameClub = async (config) => {
+  return new Promise((resolve, reject) => {
+    const { openlink } = config;
+    if (!openlink) {
+      wx.showToast({
+        title: "openlink参数缺失",
+        icon: "none",
+      });
+      reject("openlink参数缺失");
+    }
+    // 基础库版本判断
+    if (compareVersion(wx.getAppBaseInfo().SDKVersion, "3.7.6") < 0) {
+      wx.showToast({
+        title: "当前基础库版本暂不支持。",
+        icon: "none",
+      });
+      reject("当前基础库版本暂不支持。");
+    }
+    const pageManager = wx.createPageManager();
+    pageManager
+      .load({
+        openlink: openlink, // 由不同渠道获得的OPENLINK值
+      })
+      .then((res) => {
+        // 加载成功,res 可能携带不同活动、功能返回的特殊回包信息(具体请参阅渠道说明)
+        console.log(res);
+
+        // 加载成功后按需显示
+        pageManager.show();
+        resolve();
+      })
+      .catch((err) => {
+        // 加载失败,请查阅 err 给出的错误信息
+        console.error(err);
+        reject(err);
+      });
+  });
+};

+ 119 - 0
src/init.js

@@ -0,0 +1,119 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-12 12:09:56
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 15:46:42
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\init.js
+ */
+import { setStorage, getStorage } from "../utils/index.js";
+import { showShareMenu } from "./share.js";
+import { silentGetUserInfo, serverLogin, getWeChatUserInfo } from "./login.js";
+import { getIpInfo } from "./ip";
+import request from "../utils/request.js";
+import DnSdk from "../lib/DnSdk.js";
+import checkOrderToReport from "../lib/checkOrderToReport.js";
+// import tqGameConfig from "../lib/tqsdk/tq-game-config.js";
+
+/**
+ * @description: 初始化研发透传信息,
+ * @param {
+  app_version: '1.0.1',
+  config_id: 'wxc3b09871597c6102',
+  game_name: '心动女友'
+} config
+ * @param {*} buttonStyle //授权登录的样式,具体看文档,某些授权下才会使用
+ * @return {*}
+ */
+export const init = async (config, buttonStyle) => {
+  console.log("init入参" + JSON.stringify(config));
+  try {
+    // 检查小游戏启动参数
+    const needValues = ["config_id", "game_name", "app_version"];
+    for (var k in needValues) {
+      if (config[needValues[k]] === undefined) {
+        return Promise.reject(`缺少参数:${needValues[k]}`);
+      }
+    }
+
+    //获取到进入小游戏url上的参数
+    let launchOptions = wx.getEnterOptionsSync();
+    let query = launchOptions.query;
+    let scene = launchOptions.scene;
+
+    // 当有获取到广告数据时储存
+    setStorage("urlQuery", {
+      agent_id: query.agent_id || 0,
+      site_id: query.site_id || 0,
+      gdt_vid: query.gdt_vid || "",
+      weixinadinfo: query.weixinadinfo || "",
+      queryStr: JSON.stringify(query),
+    });
+    setStorage("launchScene", scene ? scene : 0);
+    setStorage("rySdkConfig", {
+      config_id: config.config_id,
+      game_name: config.game_name,
+      app_version: config.app_version,
+    });
+
+    // 获取腾讯广告小游戏SDK初始化参数
+    let dnSdkConfig = {};
+    const dnSdkRes = await request.api("COMMON", {
+      do: "getDnSdkConfig",
+    });
+
+    // 判断是否是 TQ_SDK
+    const isTQ_SDK = process.env.TQ_SDK === 'true';
+    // 获取 tqsdk 配置
+    if (isTQ_SDK) {
+      const tqConfRes = await request.api("COMMON", {
+        do: "getTqConf",
+      });
+
+      console.log("tqConfRes", tqConfRes);
+
+      if (tqConfRes) {
+        const tqGameConfig = require("../lib/tqsdk/tq-game-config.js");
+        if (tqConfRes.tq_appid) tqGameConfig.tq_appid = tqConfRes.tq_appid;
+        if (tqConfRes.tq_game_secret) tqGameConfig.tq_game_secret = tqConfRes.tq_game_secret;
+      }
+    }
+
+    if (dnSdkRes) {
+      dnSdkConfig.user_action_set_id = dnSdkRes.user_action_set_id;
+      dnSdkConfig.secret_key = dnSdkRes.secret_key;
+      setStorage("dnSdkConfig", dnSdkConfig);
+    } else {
+      const c = getStorage("dnSdkConfig");
+      // 网络请求失败,有缓存优先用缓存,否则使用默认值
+      dnSdkConfig.user_action_set_id = c?.user_action_set_id || 1208140076;
+      dnSdkConfig.secret_key =
+        c?.secret_key || "58e5d7e9539d3e54e352609000f31738";
+    }
+    // 腾讯广告小游戏SDK要求尽早初始化
+    DnSdk.init({
+      user_action_set_id: dnSdkConfig.user_action_set_id,
+      secret_key: dnSdkConfig.secret_key,
+      appid: config.config_id,
+    });
+
+    // 获取ip信息
+    // await getIpInfo()
+    // let res
+    // // //根据不同授权方式进入游戏,实现微信授权和用户服务端登录
+    // if (buttonStyle) {
+    //     //点击按钮授权
+    //     res = await getWeChatUserInfo(buttonStyle)
+    // } else {
+    //     //静默授权
+    //     res = await silentGetUserInfo()
+    // }
+    // let loginInfo = await serverLogin(res)
+    await showShareMenu(); // 开启系统分享
+    // checkOrderToReport.getInstance().run() // 检查是否有订单需要上报到腾讯广告小游戏SDK
+    // return Promise.resolve(loginInfo)
+    return Promise.resolve();
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};

+ 28 - 0
src/ip.js

@@ -0,0 +1,28 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-12 12:09:56
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 15:48:14
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\login.js
+ */
+import request from '../utils/request.js'
+import IpInfoModel from '../model/IpInfoModel'
+
+/**
+ * @description 获取ip信息
+ * @return {*}
+ */
+export const getIpInfo = async () => {
+  try {
+    const v4res = await request.api("IPV4", {})
+    const v6res = await request.api("IPV6", {})
+    IpInfoModel.getInstance().setStorage({
+      ipv4: v4res.ipv4,
+      ipv6: v6res.ipv6
+    })
+    return Promise.resolve(res)
+  } catch (error) {
+    return Promise.reject(error)
+  }
+}

+ 281 - 0
src/login.js

@@ -0,0 +1,281 @@
+/*
+ * @Author: xiaolin
+ * @Date: 2022-10-12 12:09:56
+ * @LastEditors: xiaolin
+ * @LastEditTime: 2022-10-21 15:48:14
+ * @Description: file content
+ * @FilePath: \image.platform.com\xyxJsSdkV2\src\login.js
+ */
+import request from '../utils/request.js'
+import SdkLoginReUserInfoModel from '../model/SdkLoginReUserInfoModel'
+import {to,getStorage} from "../utils/index.js"
+import DnSdk from "../lib/DnSdk.js"
+import checkOrderToReport from '../lib/checkOrderToReport.js'
+
+/**
+ * @description: 获取登录态信息,进入游戏后才能获取
+ * @return {*}
+ */
+export const loginUserInfo = async () => {
+  try {
+    let userInfo = SdkLoginReUserInfoModel.getInstance().getStorage();
+    let launchOptions = wx.getLaunchOptionsSync()
+    let query = launchOptions.query;
+    const share_ext = query.share_ext;
+    userInfo.share_ext = share_ext ? share_ext : ''
+    return Promise.resolve(userInfo)
+  } catch (error) {
+    return Promise.reject(err);
+  }
+}
+
+/**
+ * @description: 获取本地存储登录态
+ * @return {*}
+ */
+export const checkLoginStatus = async () => {
+  try {
+    let userInfo = SdkLoginReUserInfoModel.getInstance().getStorage();
+    if (
+      Object.getOwnPropertyNames(userInfo).length === 0 ||
+      userInfo.uid === 0 ||
+      userInfo.uid === ''
+    ) {
+      return Promise.reject({
+        msg: '获取不到本地登录态.'
+      })
+    } else {
+      // 本地有登录态,检查服务端登录态
+      const res = await request.api('COMMON', {
+        do: 'checkLoginStatus',
+      })
+      
+      if(res){
+        let loginUserInfo = JSON.parse(JSON.stringify(res))
+        loginUserInfo.bind_phone = res.mobile ? 1:0;
+        SdkLoginReUserInfoModel.getInstance().setStorage(loginUserInfo);
+      }else{
+        SdkLoginReUserInfoModel.getInstance().setStorage(res);
+      }
+      
+      return Promise.resolve(res)
+    }
+  } catch (error) {
+    return Promise.reject(err);
+  }
+}
+
+/**
+ * @description: 微信静态授权
+ * @return {*}
+ */
+export const silentGetUserInfo = () => {
+  return new Promise((resolve, reject) => {
+    // 执行微信登录
+    wx.login({
+      success(loginRes) {
+        let wxLoginReUserInfo = {
+          code: loginRes.code,
+          avatarUrl: '',
+          nickName: '',
+          iv: '',
+          encryptedData: '',
+        }
+        resolve(wxLoginReUserInfo)
+      },
+      fail(error) {
+        // 微信登录失败异常
+        reject(error.errMsg)
+      },
+    })
+  })
+}
+
+/**
+ * @description: 判断登录是否过期
+ * @return {*}
+ */
+export const checkLoginStatusAndReLogin = async () => {
+  let err, res;
+  [err, res] = await to(checkLoginStatus());
+  if (err === null) {
+    return Promise.resolve()
+  }
+  if (err.code === 10001) {
+    //静默授权
+    [err, res] = await to(silentGetUserInfo())
+    if (err) {
+      return Promise.reject(err)
+    };
+    [err, res] = await to(serverLogin(res))
+    if (err) {
+      return Promise.reject(err)
+    }
+    return Promise.resolve()
+  }
+  return Promise.reject(err)
+}
+
+/**
+ * @description:服务端登录 
+ * @param {*} wxLoginReUserInfo
+ * @return {*}
+ */
+export const serverLogin = (wxLoginReUserInfo) => {
+  return new Promise((resolve, reject) => {
+    const query = getStorage('urlQuery')
+    let params = {
+      do: 'login',
+      code: wxLoginReUserInfo.code,
+      avatar: wxLoginReUserInfo.avatarUrl,
+      nickName: wxLoginReUserInfo.nickName,
+      iv: wxLoginReUserInfo.iv,
+      encryptedData: wxLoginReUserInfo.encryptedData,
+      gdt_vid: query.gdt_vid,
+      weixinadinfo: query.weixinadinfo,
+      //queryStr:JSON.stringify(query.queryStr)
+    }
+    request
+      .api('COMMON', params)
+      .then((res) => {
+        let loginUserInfo = JSON.parse(JSON.stringify(res))
+        loginUserInfo.bind_phone = res.mobile ? 1:0;
+        //用户态存缓存下次进游戏可以直接拿
+        SdkLoginReUserInfoModel.getInstance().setStorage(loginUserInfo);
+        //判断有没有游戏弹窗,有就展示
+        if (res.pop_content) {
+          wx.showModal({
+            title: res.pop_title ? res.pop_title : '登录提示',
+            content: res.pop_content,
+            complete(res) {
+              console.log(res)
+            }
+          });
+        }
+        // 腾讯广告小游戏SDK设置openid
+        const dSdk = DnSdk.getInstance()
+        dSdk.setOpenId(res.openid)
+        if (res.is_register_user) {
+            dSdk.onRegister()
+        } else if (res.is_reactive_user) {
+            dSdk.track('RE_ACTIVE')
+        }
+        resolve(loginUserInfo)
+      })
+      .catch((error) => {
+        reject(error)
+      })
+  })
+}
+
+/**
+ * @description: 获取微信用户登录信息如code,没有的进行授权登录
+ * @param {*} buttonStyle
+ * @return {*}
+ */
+export const getWeChatUserInfo = (buttonStyle) => {
+  return new Promise((resolve, reject) => {
+    // 执行微信登录
+    wx.login({
+      /**
+       * @param loginRes object {'code':用户登录凭证(有效期五分钟)}
+       */
+      success(loginRes) {
+        wx.getSetting({
+          /**
+           * https://developers.weixin.qq.com/minigame/dev/api/open-api/setting/wx.getSetting.html
+           */
+          success(setting) {
+            //判断用户有没有授权
+            if (setting.authSetting['scope.userInfo']) {
+              // 处理用户已授权,获取用户登录信息
+              wx.getUserInfo({
+                success(data) {
+                  let wxLoginReUserInfo = {
+                    code: loginRes.code,
+                    avatarUrl: data.userInfo.avatarUrl,
+                    nickName: data.userInfo.nickName,
+                    iv: data.iv,
+                    encryptedData: data.encryptedData,
+                  }
+                  resolve(wxLoginReUserInfo)
+                },
+                fail(error) {
+                  // 获取用户信息异常
+                  reject({
+                    code: 0,
+                    msg: error.errMsg + '---wx getUserInfo error'
+                  })
+                },
+              })
+            } else {
+              let button = wx.createUserInfoButton(buttonStyle)
+              // 按钮点击回调
+              button.onTap((data) => {
+                if (data.errMsg === 'getUserInfo:ok') {
+                  // 展示loading界面
+                  wx.showLoading({
+                    title: '登录中',
+                  })
+                  button.destroy()
+                  let wxLoginReUserInfo = {
+                    code: loginRes.code,
+                    avatarUrl: data.userInfo.avatarUrl,
+                    nickName: data.userInfo.nickName,
+                    iv: data.iv,
+                    encryptedData: data.encryptedData,
+                  }
+                  resolve(wxLoginReUserInfo)
+                } else {
+                  button.destroy()
+                  reject({
+                    code: 0,
+                    msg: data.errMsg + '---button onTap error'
+                  })
+                }
+              })
+            }
+          },
+          fail(error) {
+            // 获取用户权限设置异常
+            reject({
+              code: 0,
+              msg: error.errMsg + '---wx getSetting error'
+            })
+          },
+        })
+      },
+      fail(error) {
+        // 微信登录失败异常
+        reject({
+          code: 0,
+          msg: error.errMsg + '---wx login error'
+        })
+      },
+    })
+  })
+}
+
+/**
+ * @description: 微信登录
+ * @param {*} buttonStyle 
+ * @returns 
+ */
+export const login = async (buttonStyle)=>{
+  try {
+    let res
+    //根据不同授权方式进入游戏,实现微信授权和用户服务端登录
+    if (buttonStyle) {
+        //点击按钮授权
+        res = await getWeChatUserInfo(buttonStyle)
+    } else {
+        //静默授权
+        res = await silentGetUserInfo()
+    }
+    let loginInfo = await serverLogin(res)
+    checkOrderToReport.getInstance().run() // 检查是否有订单需要上报到腾讯广告小游戏SDK
+    return Promise.resolve(loginInfo)
+  } catch (error) {
+    return Promise.reject(error)
+  }
+}

+ 519 - 0
src/payment.js

@@ -0,0 +1,519 @@
+import request from "../utils/request.js";
+import {
+  getSystem,
+  requestMidasPayment,
+  setStorage,
+  to,
+  unixTimestamp,
+  assign,
+  throttle,
+  requestMidasPaymentGameItem,
+} from "../utils/index.js";
+import OrderInfoModel from "../model/OrderInfoModel.js";
+import SdkLoginReUserInfoModel from "../model/SdkLoginReUserInfoModel";
+import MidasPayConfigModel from "../model/MidasPayConfigModel.js";
+import XcxPayConfigModel from "../model/XcxPayConfigModel";
+import GzhPayConfigModel from "../model/GzhPayConfigModel";
+import SubscribeConfigModel from "../model/SubscribeConfigModel";
+
+
+import {
+  checkLoginStatus,
+  checkLoginStatusAndReLogin,
+  silentGetUserInfo,
+  serverLogin,
+} from "./login.js";
+
+// 判断是否是 TQ_SDK
+const isTQ_SDK = process.env.TQ_SDK === 'true';
+
+console.log('isTQ_SDK', isTQ_SDK)
+
+// 条件加载 tqsdk
+let tqsdk = null;
+if (isTQ_SDK) {
+  tqsdk = require("../lib/tqsdk/weixin-tq-game.js");
+}
+
+// 生成订单
+const makeOrder = async (orderParams) => {
+  try {
+    const params = {
+      do: "getOrder",
+      amt: orderParams.amt,
+      role_id: orderParams.role_id,
+      role_level: orderParams.role_level,
+      role_name: orderParams.role_name,
+      server_id: orderParams.server_id,
+      server_name: orderParams.server_name,
+      product_id: orderParams.product_id,
+      product_name: orderParams.product_name,
+      ext: orderParams.ext,
+    };
+    const res = await request.api("COMMON", params);
+    let orderInfoInstance = OrderInfoModel.getInstance();
+    let midasPayConfigInstance = MidasPayConfigModel.getInstance();
+    let xcxPayConfigInstance = XcxPayConfigModel.getInstance();
+    let gzhPayConfigInstance = GzhPayConfigModel.getInstance();
+    console.log("res====>", res);
+    // 注入orderInfo信息
+    orderInfoInstance.load(res);
+    // 注入米大使支付配置信息
+    midasPayConfigInstance.load(
+      typeof res.midas_pay_config !== "undefinded" ? res.midas_pay_config : {}
+    );
+    xcxPayConfigInstance.load(
+      typeof res.xcx_pay_config !== "undefinded" ? res.xcx_pay_config : {}
+    );
+    gzhPayConfigInstance.load(
+      typeof res.gzh_pay_config !== "undefinded" ? res.gzh_pay_config : {}
+    );
+
+    // 返回订单信息
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+// 生成微信二维码订单
+const makeWxQrOrder = async (orderParams) => {
+  try {
+    let loginInfo = SdkLoginReUserInfoModel.getInstance().getStorage();
+    const params = {
+      do: "wx_qr",
+      order_no: orderParams.order_no,
+    };
+    const res = await request.api("COMMON", params);
+    console.log("下单返回内容==>", res);
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+/**
+ * @description:拉起支付
+ * @return {*}
+ */
+const makePay = async (makeOrderRes) => {
+  // let curOrderInfo = OrderInfoModel.getInstance().getInfo();
+  let curOrderInfo = makeOrderRes;
+
+  let err, platform;
+  [err, platform] = await to(getSystem("platform"));
+
+  if (err) {
+    return Promise.reject(err);
+  }
+  if (curOrderInfo.pop_content) {
+    wx.showModal({
+      title: curOrderInfo.pop_title ? curOrderInfo.pop_title : "支付提示",
+      content: curOrderInfo.pop_content,
+      complete(res) {
+        console.log("serverLogin--支付弹窗");
+        console.log(res);
+      },
+    });
+  }
+
+  if (curOrderInfo.pay_type === "midas") {
+    if ("ios" === platform) {
+      // IOS 控制,研发控制启动、调用接口返回是否开启
+      wx.showModal({
+        title: "发起支付失败",
+        content: "由于政策影响,支付功能暂不可用",
+        showCancel: false,
+      });
+      return Promise.reject("由于政策影响,支付功能暂不可用");
+    } else {
+      //检查session是否过期,过期了重新登录
+      wx.checkSession({
+        success() {
+          return Promise.resolve();
+        },
+        fail() {
+          SdkLoginReUserInfoModel.getInstance().destroyStorage();
+          // 获取用户信息
+          silentGetUserInfo()
+            .then(function (wxLoginReUserInfo) {
+              serverLogin(wxLoginReUserInfo)
+                .then(function () {
+                  return Promise.resolve();
+                })
+                .catch((error) => {
+                  return Promise.reject(error);
+                });
+            })
+            .catch((error) => {
+              return Promise.reject(error);
+            });
+        },
+      });
+    }
+  } else if (curOrderInfo.pay_type === "w_gzh") {
+    // 客服方式
+    if (curOrderInfo.ios_pay_type === "kf") {
+      let gzhPayConfig = GzhPayConfigModel.getInstance().getInfo();
+      console.log(gzhPayConfig, 1);
+      // 定义客服消息参数
+      wx.showModal({
+        title: "提示",
+        content: "如果客服无法推送订单,则向客服回复任何消息并重试。",
+        success(res) {
+          // 拉起客服消息
+          wx.openCustomerServiceConversation({
+            sessionFrom: gzhPayConfig.sessionFrom,
+            showMessageCard: gzhPayConfig.showMessageCard,
+            sendMessagePath: gzhPayConfig.sendMessagePath,
+            sendMessageTitle: gzhPayConfig.sendMessageTitle,
+            sendMessageImg: gzhPayConfig.sendMessageImg,
+          });
+        },
+      });
+      return Promise.resolve("CUSTOMER");
+    } else {
+      // Todo 拉起支付二维码 ?
+      const res = await makeWxQrOrder(curOrderInfo);
+      console.log("makeWxQrOrder", res);
+      return Promise.resolve(res);
+    }
+  } else {
+    let xcxPayConfig = XcxPayConfigModel.getInstance().getInfo();
+    wx.navigateToMiniProgram({
+      appId: xcxPayConfig.xcxAppid,
+      path: xcxPayConfig.path,
+      extraData: xcxPayConfig.extraData,
+      envVersion: xcxPayConfig.envVersion,
+    });
+    return Promise.resolve("WXXCX");
+  }
+};
+
+
+/**
+ * @description: 将平台值映射为标准化的平台值
+ * @param {string} platform 原始平台值
+ * @return {string} 标准化后的平台值 (android|ios|harmony|pc)
+ */
+const normalizePlatform = (platform) => {
+  const platformMap = {
+    'ios': 'ios',
+    'android': 'android',
+    'ohos': 'harmony',
+    'ohos_pc': 'pc',
+    'windows': 'pc',
+    'mac': 'pc',
+    'devtools': 'pc'
+  };
+  
+  // 如果平台值在映射表中,返回映射后的值,否则默认返回 'pc'
+  return platformMap[platform] || 'pc';
+};
+
+const wxPay = async (makeOrderRes, cpOrderInfo) => {
+  const userInfo = SdkLoginReUserInfoModel.getInstance().getStorage();
+  // const curOrderInfo = OrderInfoModel.getInstance().getInfo();
+  console.log("makeOrderRes", makeOrderRes);
+  const curOrderInfo = makeOrderRes;
+  const midasPayConfig = MidasPayConfigModel.getInstance().getInfo();
+  let platform = await getSystem("platform");
+  // 标准化平台值,只接受 android|ios|harmony|pc
+  platform = normalizePlatform(platform);
+  try {
+    let res = {}
+
+    if (isTQ_SDK) {
+      // 入参以「支付接口文档」为准。
+      let openid = userInfo.openid;
+      var orderInfo = {
+        user_id: userInfo.uid,
+        game_order_sn: cpOrderInfo.ext || '', // cp游戏订单号
+        role_id: cpOrderInfo.role_id,
+        role_name: cpOrderInfo.role_name,
+        product_id: cpOrderInfo.product_id,
+        product_name: cpOrderInfo.product_name,
+        server_name: cpOrderInfo.server_name,
+        server_id: cpOrderInfo.server_id,
+        money: cpOrderInfo.amt * 100, // 转元
+        os:platform,
+        extra:JSON.stringify({"sand":midasPayConfig.env,"openid":openid,"wechat_product_id":curOrderInfo.xyx_product_id}),
+        pay_channel_id: 6,
+        company_notify_url: `https://app.hainanruiyu.cn/pm/notify/${curOrderInfo.pay_channel}`,
+        company_order_sn: curOrderInfo.order_no, // 我方订单号
+      };
+
+
+      tqsdk.showOrder(orderInfo, async function (payRes) {
+        console.log('tq pay res', res);
+
+        if (payRes.status === 1) {
+          // 上报成功后,根据不同支付类型,走不同的支付方式,具体按照下方「支付渠道详细说明」为准。
+          // 微信小游戏内购支付
+          const pay_data = payRes.data.pay_data;
+          await requestMidasPaymentGameItem({
+            signData:pay_data.signData,
+            paySig: pay_data.paySig,
+            signature: pay_data.signature,
+            amt: curOrderInfo.amt,
+          })
+
+        }
+      });
+    }else{
+      res = await requestMidasPayment({
+        mode: "game",
+        env: midasPayConfig.env,
+        offerId: midasPayConfig.offerId,
+        currencyType: "CNY",
+        platform: platform,
+        buyQuantity: midasPayConfig.buyQuantity,
+        amt: curOrderInfo.amt,
+        zoneId: midasPayConfig.zoneId,
+        outTradeNo: curOrderInfo.order_no,
+      });
+       // 支付回调
+        request.api("COMMON", {
+            do: "payCallback",
+            accessToken: userInfo.access_token,
+            order_no: curOrderInfo.order_no,
+            amt: curOrderInfo.amt,
+        });
+
+        //请求米大师日志
+        request.api("COMMON", {
+            do: "payLog",
+            msg: JSON.stringify(res),
+            env: midasPayConfig.env,
+            offerId: midasPayConfig.offerId,
+            buyQuantity: midasPayConfig.buyQuantity,
+            zoneId: midasPayConfig.zoneId,
+            order_no: curOrderInfo.order_no,
+            amt: curOrderInfo.amt,
+        });
+    }
+
+    return Promise.resolve();
+  } catch (error) {
+    //请求米大师日志
+    request.api("COMMON", {
+      do: "payLog",
+      msg: JSON.stringify(error),
+      env: midasPayConfig.env,
+      offerId: midasPayConfig.offerId,
+      buyQuantity: midasPayConfig.buyQuantity,
+      zoneId: midasPayConfig.zoneId,
+      order_no: curOrderInfo.order_no,
+      amt: curOrderInfo.amt,
+    });
+    return Promise.reject(error);
+  }
+};
+
+/**
+ * @description:获取IOS 支付配置
+ * @return {*}
+ */
+export const payConfig = async () => {
+  try {
+    // 获取预订单数据
+    const res = await request.api("COMMON", {
+      do: "getIosPayConfig",
+    });
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+/**
+ * @description: 内部支付函数
+ * @param {*} payParams
+ * @return {*}
+ */
+const _makePayment = async (payParams) => {
+  console.log("makePayment入参==>" + JSON.stringify(payParams));
+  try {
+    //判断登录是否过期,过期重新登录
+    await checkLoginStatusAndReLogin();
+    // 微信订阅pay
+    await triggerSubscribe("pay");
+    const orderInfo = {
+      amt: payParams.amt,
+      role_id: payParams.role_id,
+      role_name: payParams.role_name,
+      server_id: payParams.server_id,
+      server_name: payParams.server_name,
+      ext: payParams.ext ? payParams.ext : "",
+      role_level: payParams.role_level,
+      product_id: payParams.product_id,
+      product_name: payParams.product_name,
+    };
+    wx.showLoading({
+      title: "支付中...",
+      mask: true,
+    });
+    const cpOrderInfo = orderInfo;
+    // 下单
+    const makeOrderRes = await makeOrder(orderInfo);
+
+    // 非米大师支付使用本地定时器检查上报
+    const curOrderInfo = OrderInfoModel.getInstance().getInfo();
+
+    console.log("curOrderInfo", curOrderInfo);
+
+    if (curOrderInfo.pay_type != "midas") {
+      setStorage("extOrderToReport_" + curOrderInfo.ext, {
+        ext: curOrderInfo.ext,
+        amt: curOrderInfo.amt,
+        order_no: curOrderInfo.order_no,
+        timestamp: unixTimestamp(),
+        reportCount: 0,
+      });
+    }
+
+    const res = await makePay(makeOrderRes);
+    wx.hideLoading();
+
+    // 二维码+url 二合一
+    if (typeof res === "object") {
+      return Promise.resolve(res);
+    }
+    if (res === "CUSTOMER") {
+      //客服已经拉起成功
+      return Promise.resolve(null);
+    }
+    if (res === "MIDAS_IOS") {
+      //米大师ios没得支付,提示已弹出
+      return Promise.reject("米大师ios暂不支持支付");
+    }
+    // 小程序
+    if (res === "WXXCX") {
+      return Promise.resolve(null);
+    }
+    // 小游戏米大师
+    await wxPay(makeOrderRes, cpOrderInfo);
+
+    return Promise.resolve(null);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+/**
+ * @description:拉起支付(节流版本,避免短时间内重复点击)
+ * @param {*} payParams
+ * @return {*}
+ */
+export const makePayment = throttle(_makePayment, 2000);
+
+/**
+ * @description: 获取订阅配置
+ * @return {*}
+ */
+export const getSubscribeConfig = () => {
+  return new Promise((resolve, reject) => {
+    let params = {
+      do: "getSubscribeConfig",
+    };
+    request
+      .api("COMMON", params)
+      .then((res) => {
+        resolve(res);
+      })
+      .catch((errorMsg) => {
+        reject(errorMsg);
+      });
+  });
+};
+
+/**
+ * @description: 上报订阅记录
+ * @param {*} resStr
+ * @return {*}
+ */
+export const setSubscribeSuccessLog = (resStr) => {
+  return new Promise((resolve, reject) => {
+    let params = {
+      do: "setSubscribeSuccessLog",
+      res_str: resStr,
+    };
+    request
+      .api("COMMON", params)
+      .then((res) => {
+        resolve();
+      })
+      .catch((errorMsg) => {
+        reject(errorMsg);
+      });
+  });
+};
+
+export const requestSubscribeMessage = async () => {
+  try {
+    const res = await getSubscribeConfig();
+    //整合
+    let templateList = {};
+    for (let resKey in res) {
+      if (Array.isArray(res[resKey])) {
+        let tempArr = res[resKey];
+        let tempList = [];
+        for (let k in tempArr) {
+          if (typeof tempArr[k]["template_id"] !== "undefined") {
+            tempList.push(tempArr[k]["template_id"]);
+          }
+        }
+        templateList[resKey] = tempList;
+      }
+    }
+    let subscribeConfigM = SubscribeConfigModel.getInstance(templateList);
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+/**
+ * @description: 发起客服聊天
+ * @return {*}
+ */
+export const connectCustomer = async () => {
+  wx.openCustomerServiceConversation({
+    success: (res) => {
+      return Promise.resolve(res);
+    },
+    fail: (err) => {
+      return Promise.reject(err);
+    },
+  });
+};
+
+/**
+ * @description: 触发订阅
+ * @param {*} type
+ * @return {*}
+ */
+export const triggerSubscribe = async (type = "login") => {
+  console.log("triggerSubscribe入参" + JSON.stringify(type));
+  let xcxPayConfig = SubscribeConfigModel.getInstance().getInfo();
+  let curList = [];
+  if (Array.isArray(xcxPayConfig[type])) {
+    curList = xcxPayConfig[type];
+  }
+  if (curList.length != 0) {
+    wx.onTouchEnd(function () {
+      wx.requestSubscribeMessage({
+        tmplIds: curList,
+        success: (res) => {
+          //上报订阅结果
+          setSubscribeSuccessLog(JSON.stringify(res));
+        },
+        complete: (res) => {
+          console.log("订阅结果", res);
+          wx.offTouchEnd();
+        },
+      });
+    });
+  }
+  return Promise.resolve();
+};

+ 29 - 0
src/secCheck.js

@@ -0,0 +1,29 @@
+import request from "../utils/request.js";
+
+// 文本内容安全检测
+export const secCheckText = async ({ content, scene }) => {
+  try {
+    const res = await request.api("WX_API", {
+      do: "msgSecCheck",
+      content,
+      scene,
+    });
+    return Promise.resolve(res);
+  } catch (error) {
+    return Promise.reject(error);
+  }
+};
+
+// 多媒体内容安全识别
+export const secCheckMedia = ({ media_url, media_type, scene }) => {
+  return new Promise(async (resolve, reject) => {
+    const res = await request.api("COMMON", {
+      do: "secCheckMedia",
+      version: 2,
+      media_url,
+      media_type,
+      scene,
+    });
+    resolve(res);
+  });
+};

+ 155 - 0
src/share.js

@@ -0,0 +1,155 @@
+import request from "../utils/request.js";
+import ShareConfigModel from "../model/ShareConfigModel";
+import DnSdk from "../lib/DnSdk.js";
+
+/**
+ * @description:检查分享配置
+ * @return {*}
+ */
+const checkShareConfig = async () => {
+    try {
+        // 加载分享配置
+        let shareConfigInfo = ShareConfigModel.getInstance().getInfo();
+        if (Object.getOwnPropertyNames(shareConfigInfo).length === 0 || shareConfigInfo.title === "") {
+            // 获取服务端分享配置
+            const res = await request.api("COMMON", {
+                do: "getShareConfig",
+            });
+            res.imageUrl = res.image_url;
+            ShareConfigModel.getInstance().load(res);
+        }
+        return Promise.resolve();
+    } catch (error) {
+        return Promise.reject(error);
+    }
+};
+
+/**
+ * @description: 开启系统分享
+ * @return {*}
+ */
+export const showShareMenu = async () => {
+    try {
+        // 开启分享按钮
+        wx.showShareMenu({
+            withShareTicket: true,
+        });
+        await checkShareConfig();
+        let shareData = buildShareData({});
+        wx.onShareAppMessage(() => {
+            // 腾讯广告小游戏SDK上报
+            DnSdk.getInstance().track('SHARE', {
+                target: 'APP_MESSAGE'
+            });
+            return shareData;
+        });
+        wx.onShareTimeline(() => {
+            // 腾讯广告小游戏SDK上报
+            DnSdk.getInstance().track('SHARE', {
+                target: 'TIME_LINE'
+            });
+            return shareData;
+        });
+        wx.onCopyUrl(() => {
+            return {
+                query: shareData,
+            };
+        });
+        // 收藏
+        wx.onAddToFavorites(() => {
+            // 腾讯广告小游戏SDK上报
+            DnSdk.getInstance().track('ADD_TO_WISHLIST', {
+                //  普通收藏(default)
+                type: 'default',
+            })
+        })
+        return Promise.resolve();
+    } catch (error) {
+        return Promise.reject(error);
+    }
+};
+
+/**
+ * @description: 主动发起分享
+ * @param {*} data
+ * @return {*}
+ */
+export const shareAppMessage = async (data) => {
+    console.log("shareAppMessage入参"+JSON.stringify(data));
+    try {
+        await checkShareConfig();
+        // 发起分享
+        let shareData = buildShareData(data);
+        wx.shareAppMessage(shareData);
+        return Promise.resolve();
+    } catch (error) {
+        return Promise.reject(error);
+    }
+};
+
+const buildShareData = (data) => {
+    let shareConfigInfo = ShareConfigModel.getInstance().getInfo();
+    let shareData = {
+        title: shareConfigInfo.title,
+        imageUrl: shareConfigInfo.imageUrl,
+        query: shareConfigInfo.query,
+    };
+    let share_ext = "";
+    // 记录分享透传参数
+    if (data.hasOwnProperty("title") && data.title) shareData.title = data.title;
+    if (data.hasOwnProperty("imageUrl") && data.imageUrl) shareData.imageUrl = data.imageUrl;
+    if (data.hasOwnProperty("ext") && data.ext) share_ext = data.ext;
+
+    //前面这个share_ext是研发透传进来的,后面这个是服务端传进来的
+    shareData.query += shareConfigInfo.share_ext;
+    if (share_ext) {
+        shareData.query += `&share_ext=` + share_ext;
+    }
+    return shareData;
+};
+
+/**
+ * @description: 主动监听研发透传参数
+ * @param {*} data
+ * @return {*}
+ */
+export const onShareAppMessage = (data,menus=['shareAppMessage', 'shareTimeline']) => {
+    console.log("onShareAppMessage入参"+JSON.stringify(data));
+    //先off,再on
+    wx.offShareAppMessage();
+    wx.offShareTimeline();
+    wx.offCopyUrl();
+    wx.offAddToFavorites();
+    let shareData = buildShareData(data);
+    wx.showShareMenu({
+      withShareTicket: true,
+      menus:menus
+    })
+    wx.onShareAppMessage(() => {
+        // 腾讯广告小游戏SDK上报
+        DnSdk.getInstance().track('SHARE', {
+            target: 'APP_MESSAGE'
+        });
+        return shareData;
+    });
+    wx.onShareTimeline(() => {
+        // 腾讯广告小游戏SDK上报
+        DnSdk.getInstance().track('SHARE', {
+            target: 'TIME_LINE'
+        });
+        return shareData;
+    });
+    wx.onCopyUrl(() => {
+        return {
+            query: shareData.query,
+        };
+    });
+    // 收藏
+    wx.onAddToFavorites(() => {
+        // 腾讯广告小游戏SDK上报
+        DnSdk.getInstance().track('ADD_TO_WISHLIST', {
+            //  普通收藏(default)
+            type: 'default',
+        })
+    })
+};

+ 293 - 0
utils/index.js

@@ -0,0 +1,293 @@
+import DnSdk from "../lib/DnSdk";
+
+/**
+ * @description: 跳转小程序
+ */
+export const navigateToMiniProgram = (appId) => {
+  return new Promise((resolve, reject) => {
+    wx.navigateToMiniProgram({
+      appId: appId,
+      path: "",
+      extraData: {
+        foo: "bar",
+      },
+      envVersion: "develop",
+      success(res) {
+        resolve(res);
+      },
+      fail(error) {
+        reject(error);
+      },
+    });
+  });
+};
+
+/**
+ * @description: 获取手机相关配置,每次都直接取接口
+ * @param {string} key
+ * @return {*}
+ */
+export const getSystem = (key) => {
+  return new Promise((resolve, reject) => {
+    wx.getSystemInfo({
+      success: (res) => {
+        if (key && key in res) {
+          resolve(res[key]);
+        } else {
+          resolve(res);
+        }
+      },
+      fail: (error) => {
+        reject(error);
+      },
+    });
+  });
+};
+
+/**
+ * @description: js异步转同步优化
+ * @param {*} promiseObj
+ * @return {*}
+ */
+export const to = (promiseObj) => {
+  return promiseObj
+    .then((data) => {
+      return [null, data];
+    })
+    .catch((err) => [err]);
+};
+
+/**
+ * @description: 对象排序
+ * @param {object} data
+ * @return {object}
+ */
+export const sortObj = (data) => {
+  let arr = [];
+  for (let key in data) {
+    arr.push(key);
+  }
+  arr = arr.sort();
+  let newData = {};
+  for (var i in arr) {
+    newData[arr[i]] = data[arr[i]];
+  }
+  return newData;
+};
+
+/**
+ * @description: 加密
+ * @param {*} value
+ * @return {string}
+ */
+export const compile = (value) => {
+  value = JSON.stringify(value);
+  let result = String.fromCharCode(value.charCodeAt(0) + value.length);
+  for (let i = 1; i < value.length; i++) {
+    result += String.fromCharCode(
+      value.charCodeAt(i) + value.charCodeAt(i - 1)
+    );
+  }
+  return escape(result);
+};
+
+/**
+ * @description:解密
+ * @param {string} value
+ * @return {*}
+ */
+export const uncompile = (value) => {
+  value = unescape(value);
+  let result = String.fromCharCode(value.charCodeAt(0) - value.length);
+  for (let i = 1; i < value.length; i++) {
+    result += String.fromCharCode(
+      value.charCodeAt(i) - result.charCodeAt(i - 1)
+    );
+  }
+  result = JSON.parse(result);
+  return result;
+};
+
+/**
+ * @description: 二次处理key
+ * @param {string} key
+ * @return {string}
+ */
+const getKey = (key) => {
+  return `xinxin_${key}_@`;
+};
+
+/**
+ * @description: 获取
+ * @param {string} key
+ * @return {*}
+ */
+export const getStorage = (key) => {
+  let value = wx.getStorageSync(getKey(key));
+  return value ? uncompile(value) : false;
+};
+
+/**
+ * @description: 存储
+ * @param {string} key
+ * @param {*} value
+ * @return {*}
+ */
+export const setStorage = (key, value) => {
+
+    wx.setStorageSync(getKey(key), compile(value));
+};
+
+/**
+ * @description: 删除
+ * @param {string} key
+ */
+export const removeStorage = (key) => {
+    console.log('remove', key)
+  wx.removeStorageSync(getKey(key));
+};
+
+/**
+ * @description: 虚拟支付
+ * @param {object}
+ * @return {*}
+ */
+export const requestMidasPayment = (data) => {
+  return new Promise((resolve, reject) => {
+    wx.requestMidasPayment({
+      ...data,
+      success: (res) => {
+        console.log('zhifu success', res)
+        // 腾讯广告小游戏SDK上报支付
+        
+        DnSdk.getInstance().onPurchase(data.amt * 100);
+        resolve(res);
+      },
+      fail: (error) => {
+        console.log('zhifu fail', error)
+        reject(error);
+      },
+    });
+  });
+};
+
+
+/**
+ * @description: 发起道具直购支付
+ * @param {object} data
+ * @return {*}
+ */
+export const requestMidasPaymentGameItem = (data) => {
+  return new Promise((resolve, reject) => {
+    wx.requestMidasPaymentGameItem({
+      ...data,
+      success: (res) => {
+        console.log('zhifu', res)
+        // 腾讯广告小游戏SDK上报支付
+        
+        DnSdk.getInstance().onPurchase(data.amt * 100);
+        resolve(res);
+      },
+      fail: (error) => {
+        console.log('zhifu fail', error)
+        reject(error);
+      },
+    });
+  });
+}
+
+
+/**
+ * @description: 随机字符串
+ * @param {number}
+ * @return {string}
+ */
+export const randomString = (length) => {
+  const chars =
+    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  var result = "";
+  for (let i = length; i > 0; --i)
+    result += chars[Math.floor(Math.random() * chars.length)];
+  return result;
+};
+
+/**
+ * @description: 获取unix时间戳(秒)
+ * @return {number}
+ */
+export const unixTimestamp = () => {
+  return Math.floor(Date.now() / 1000);
+};
+
+/**
+ * 版本判断
+ * @param {string} v1
+ * @param {string} v2
+ * @return {number}
+ */
+export const compareVersion = (v1, v2) => {
+  v1 = v1.split(".");
+  v2 = v2.split(".");
+  const len = Math.max(v1.length, v2.length);
+
+  while (v1.length < len) {
+    v1.push("0");
+  }
+  while (v2.length < len) {
+    v2.push("0");
+  }
+
+  for (let i = 0; i < len; i++) {
+    const num1 = parseInt(v1[i]);
+    const num2 = parseInt(v2[i]);
+
+    if (num1 > num2) {
+      return 1;
+    } else if (num1 < num2) {
+      return -1;
+    }
+  }
+
+  return 0;
+};
+export const assign = (obj, defaultInfo) => {
+  let info = {};
+  //合并,后覆盖前,所以必定有默认key
+  Object.assign(info, defaultInfo, obj);
+  let result = {};
+  for (let key in defaultInfo) {
+    if (typeof info[key] !== "undefined") {
+      obj[key] = info[key];
+      result[key] = info[key];
+    }
+  }
+  return result;
+};
+
+/**
+ * @description: 节流函数
+ * @param {Function} func 要节流的函数
+ * @param {number} wait 等待时间(毫秒)
+ * @return {Function} 节流后的函数
+ */
+export const throttle = (func, wait = 2000) => {
+  let lastCall = 0;
+  let pendingPromise = null;
+
+  return function executedFunction(...args) {
+    const now = Date.now();
+
+    if (now - lastCall >= wait) {
+      // 可以执行,重置时间
+      lastCall = now;
+      pendingPromise = null;
+      return func.apply(this, args);
+    } else {
+      // 被节流,返回一个被拒绝的 Promise
+      if (!pendingPromise) {
+        pendingPromise = Promise.reject(new Error("请求过于频繁,请稍后再试"));
+      }
+      return pendingPromise;
+    }
+  };
+};

+ 145 - 0
utils/request.js

@@ -0,0 +1,145 @@
+import apiConfig from "../config/api.js";
+import gameConfig from "../config/game.js";
+import sdkConfig from "../config/sdk.js";
+import { getSystem, getStorage } from "../utils/index.js";
+import { sortObj } from "./index.js";
+import SdkLoginReUserInfoModel from "../model/SdkLoginReUserInfoModel";
+import IpInfoModel from "../model/IpInfoModel";
+
+import md5 from "../lib/md5";
+
+class request {
+  // 统一API请求入口
+  async api(type, params, method = "post") {
+    try {
+      let wxNetworkInfo;
+      const wxSystemInfo = await getSystem();
+      // 获取启动query参数
+      const query = getStorage("urlQuery");
+      const rySdkConfig = getStorage("rySdkConfig");
+
+      // 组装公共参数
+      //启动参数有渠道id和site_id的按启动参数,没有则按系统类型对应的渠道id和site_id,游戏id按系统类型对应的游戏id
+      params.config_id = rySdkConfig.config_id; //配置id
+      params.platform = wxSystemInfo.platform;
+      params.os = wxSystemInfo.system;
+      params.model = wxSystemInfo.model;
+      params.device_brand = wxSystemInfo.brand;
+      // params.mnos = wxNetworkInfo.networkType;
+      //游戏版本,初始化的时候透传进来
+      params.app_version = rySdkConfig.app_version;
+      params.queryStr = query.queryStr;
+
+      // let ipinfo = IpInfoModel.getInstance().getStorage();
+      // params.ipv4 = ipinfo.ipv4;
+      // params.ipv6 = ipinfo.ipv6;
+      let loginInfo = SdkLoginReUserInfoModel.getInstance().getStorage();
+      params.access_token = loginInfo.access_token;
+      (params.username = loginInfo.username), (params.uid = loginInfo.uid);
+      params.openid = loginInfo.openid;
+      params.mtype = gameConfig.MTYPE;
+      params.uuid = sdkConfig.DEVICE_NO;
+      params.imei = sdkConfig.DEVICE_NO;
+      params.sdk_version = sdkConfig.SDK_VERSION;
+      params.sdk_version_code = sdkConfig.SDK_VERSION_CODE;
+      params.agent_id =
+        query.agent_id ||
+        ("ios" === wxSystemInfo.platform
+          ? gameConfig.IOS_AGENT_ID
+          : gameConfig.AGENT_ID);
+      params.site_id =
+        query.site_id ||
+        ("ios" === wxSystemInfo.platform
+          ? gameConfig.IOS_SITE_ID
+          : gameConfig.SITE_ID);
+
+      if (!params.appid) {
+        params.appid = loginInfo.appid;
+      }
+      params.launchScene = getStorage("launchScene");
+
+      // 组装请求接口地址
+      const url = type in apiConfig ? apiConfig[type] : false;
+      if (url === false) {
+        return Promise.reject("type error");
+      }
+      //common类接口统一加密
+      if (type === "COMMON") {
+        params = request.addCommonSign(params);
+      }
+      if (type === "WX_API") {
+        params = request.addCommonSign(params);
+      }
+      // 发起请求
+      const res = await this.doRequest(url, method, params);
+      return Promise.resolve(res);
+    } catch (error) {
+      return Promise.reject(error);
+    }
+  }
+
+  doRequest(url, method, params) {
+    return new Promise((resolve, reject) => {
+      // 发起请求
+      wx.request({
+        url: url,
+        header: {
+          "Content-Type": "application/x-www-form-urlencoded",
+        },
+        method: method,
+        data: params,
+        // 成功响应
+        success: (res) => {
+          if (res.statusCode === 200) {
+            if (res.data.ret === 1 || res.data.code === 1) {
+              resolve(res.data.info);
+            } else {
+              reject({
+                code: res.data.ret,
+                msg: res.data.msg,
+              });
+            }
+          } else {
+            reject({
+              code: -100,
+              msg: `network error ${res.statusCode}`,
+            });
+          }
+        },
+        fail: (error) => {
+          reject({
+            code: -101,
+            msg: error.errMsg,
+          });
+        },
+      });
+    });
+  }
+
+  /**
+   * 通用类加密
+   * @param params
+   */
+  static addCommonSign(params) {
+    const rySdkConfig = getStorage("rySdkConfig");
+    if (!params.time) {
+      params.time = parseInt(new Date().getTime() / 1000);
+    }
+    let newData = sortObj(params);
+    let signStr = "";
+    for (let k in newData) {
+      if (k === "sign") {
+        continue;
+      }
+      if (newData[k] === "") {
+        continue;
+      }
+      signStr = signStr + k + "=" + newData[k] + "&";
+    }
+    signStr = signStr.substring(0, signStr.length - 1) + rySdkConfig.config_id;
+    // console.log('加密原串:'+signStr);
+    params.sign = md5(signStr);
+    return params;
+  }
+}
+export default new request();

+ 68 - 0
webpack.config.js

@@ -0,0 +1,68 @@
+const TerserPlugin = require("terser-webpack-plugin");
+const webpack = require("webpack");
+const path = require("path");
+const pkg = require("./package.json");
+
+// 判断是否启用 TQ_SDK
+const isTQ_SDK = process.env.TQ_SDK === 'true';
+// 判断是否是开发环境
+const isDev = process.env.NODE_ENV === 'development';
+
+// 根据 TQ_SDK 和开发环境动态设置文件名
+let outputFilename;
+if (isTQ_SDK) {
+  outputFilename = `[name]-tqsdk.${pkg.version}.js`;
+} else {
+  outputFilename = `[name].${pkg.version}.js`
+}
+
+const plugins = [
+  // 注入环境变量
+  new webpack.DefinePlugin({
+    'process.env.TQ_SDK': JSON.stringify(process.env.TQ_SDK || 'false')
+  })
+];
+
+// 如果不是 TQ_SDK 模式,忽略 tqsdk 相关文件
+if (!isTQ_SDK) {
+  plugins.push(
+    new webpack.IgnorePlugin({
+      resourceRegExp: /^\.\.\/lib\/tqsdk/
+    })
+  );
+}
+
+module.exports = {
+  entry: {
+    rywxsdk: "./index.js",
+  },
+  experiments: {
+    outputModule: true,
+  },
+  output: {
+    filename: outputFilename,
+    path: path.resolve(__dirname, "dist"),
+    library: {
+      type: "module",
+    },
+  },
+  resolve: {
+    fallback: {
+      "crypto": false
+    }
+  },
+  plugins: plugins,
+  optimization: {
+    minimize: true, // 开发环境不压缩,加快构建速度
+    minimizer:  [
+      new TerserPlugin({
+        terserOptions: {
+          format: {
+            comments: false,
+          },
+        },
+        extractComments: false,
+      }),
+    ],
+  },
+};

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov