npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

im2-link-jssdk

v1.4.3

Published

`im2-link-jssdk` 是 H5 小程序与宿主 App/WebView 之间的通信 SDK。Web 侧通过统一 API 请求宿主完成支付 、导航、系统分享、下载、网络请求等原生能力;SDK 负责平台识别、消息封装和回调分发。

Readme

im2-link-jssdk

im2-link-jssdk 是 H5 小程序与宿主 App/WebView 之间的通信 SDK。Web 侧通过统一 API 请求宿主完成支付 、导航、系统分享、下载、网络请求等原生能力;SDK 负责平台识别、消息封装和回调分发。

本 README 以当前源码为准:公开方法、参数类型、消息类型和回调协议均与 src/index.ts、src/types/common.ts 保持一致。

在线文档

以上地址指向 npm 当前已发布版本的类型文档。仓库中的最新改动会在下次发布后同步到这两个地址。

目录

安装

npm install im2-link-jssdk

SDK 同时提供 ESM、CommonJS 和 TypeScript 类型声明。

快速开始

import IMSDK from 'im2-link-jssdk';

const sdk = new IMSDK({
  id: 'your-app-id',
  token: 'your-app-token',
  debug: false
});

sdk.share({
  type: 'system',
  param: {
    title: '分享标题',
    text: '分享描述',
    shareUrl: 'https://example.com?share_source=tg',
    imageUrl: 'https://example.com/share.png'
  }
});

初始化参数:

| 参数 | 类型 | 必填 | 说明 | | ------- | --------- | ---- | ----------------------------------- | | id | string | 是 | 小程序 App ID | | token | string | 是 | 小程序 App Token | | debug | boolean | 否 | 是否打印 SDK 调试日志,默认 false |

H5 小程序要求

  • 使用 Webpack、Rspack 或其他可输出浏览器资源的构建工具。
  • 使用 Hash 路由,路由状态由 window.location.hash 承载。
  • 构建入口文件命名为 index.html。
  • 发布时将构建产物打包为 ZIP。
  • SDK 依赖浏览器的 window 和 navigator,不要在 SSR 服务端执行初始化。

API 概览

| API | 宿主消息类型 | 用途 | | ---------------------- | ----------------- | ------------------------ | | platform | - | 获取当前运行平台 | | callPayment | payment | 拉起原生支付 | | callBack | back | 通知宿主返回 | | callConversation | conversation | 打开指定用户会话 | | callNavigate | navigate | 调用宿主导航 | | permissions | permissions | 请求宿主权限能力 | | callOpenMiniProgram | openminiapp | 打开其他小程序 | | callSetBarColor | barcolor | 设置状态栏颜色 | | callPopup | popup | 拉起原生弹框 | | requestApi | requireAPI | 由宿主发起网络请求 | | requestApp | requireAPP | 与宿主交换业务数据 | | adjustInputBoxHeight | inputBoxHeight | 调整输入框高度 | | switchLandscape | landscape | 切换横屏状态 | | share | share | 业务分享或系统分享 | | download | download | 请求宿主下载视频 | | behaviorCaptcha | behaviorCaptcha | 发送行为验证码结果 | | getCaptchaAccount | captchaAccount | 索取登录页账号与区号 | | vibrate | vibrate | 触发宿主系统振动 |

平台信息

const platform = sdk.platform;

返回值为:

type Platform = 'win' | 'mac' | 'unix' | 'linux' | 'android' | 'ios' | 'unknown';

支付

import { IMChainCurrencyEnum } from 'im2-link-jssdk';

sdk.callPayment(
  {
    amount: '99.00',
    consumeType: 'goods',
    chainCurrencyType: IMChainCurrencyEnum.CNY,
    productOrderNo: 'ORDER-20260828-001',
    productName: '商品名称',
    quantity: '1'
  },
  (isSuccess) => {
    console.log('支付是否成功:', isSuccess);
  }
);

chainCurrencyType 可选值:CNY = 1、KKC = 2、VNC = 3。

支付参数可以省略;省略时表示只校验支付密码:

sdk.callPayment(undefined, (isSuccess) => {
  console.log('支付密码校验结果:', isSuccess);
});

当初始化的 id 不等于字符串 '0' 时,SDK 会先校验 App ID 和 App Token,再向宿主发送支付消息。校验 失败只会输出 callPayment error,不会继续拉起支付。

callPayment 是当前唯一返回 Promise<void> 的公开方法。等待该 Promise 只表示前置校验和消息发送结束 ,支付最终结果仍以回调为准。

返回、会话与导航

返回

sdk.callBack(() => {
  console.log('宿主已处理返回');
});

打开会话

sdk.callConversation('target-user-open-id', () => {
  console.log('宿主已处理会话请求');
});

宿主导航

sdk.callNavigate(
  {
    actionType: 'external',
    params: {
      route: 'https://example.com'
    }
  },
  () => {
    console.log('宿主已处理导航请求');
  }
);

当前约定的 actionType 包括:

| 值 | 用途 | | ------------------ | --------------------------------- | | home | 首页 | | channel | 超级群,params 中传 channelId | | trad | 交易页面 | | inner | 内部链接,params 中传 route | | external | 外部链接,params 中传 route | | invite | 邀请页面 | | share | 系统分享入口 | | shortVideoSearch | 短视频搜索 | | customerService | 客服页面 |

actionType 在当前类型定义中是 string,表格列出的是宿主已约定的业务值。

权限

sdk.permissions(
  {
    actionType: 'camera'
  },
  (result) => {
    console.log('权限结果:', result);
  }
);

params 当前使用 IMNavigateParams 结构,实际 actionType 及返回数据由宿主约定。

打开小程序

sdk.callOpenMiniProgram(
  'miniapp://target-app',
  {
    source: 'current-app',
    scene: 'detail'
  },
  () => {
    console.log('宿主已处理打开请求');
  }
);

第二个参数为可选的透传对象。若不需要透传参数,可传 undefined:

sdk.callOpenMiniProgram('miniapp://target-app', undefined, () => {
  console.log('宿主已处理打开请求');
});

状态栏与原生弹框

设置状态栏颜色

sdk.callSetBarColor(
  {
    titleColor: '#FFFFFF',
    backgroundColor: '#1677FF'
  },
  () => {
    console.log('颜色设置完成');
  }
);

titleColor 和 backgroundColor 均为可选字符串,颜色格式由宿主解析。

拉起原生弹框

sdk.callPopup(
  {
    url: 'https://example.com/popup',
    ratio: 0.75,
    popupType: 2
  },
  () => {
    console.log('弹框已处理');
  }
);

popupType:

| 值 | 展示方式 | | --- | -------------- | | 1 | 带标题栏 | | 2 | 居中弹出 | | 3 | 从底部向上覆盖 |

网络请求与 App 数据交互

由宿主发起网络请求

interface UserProfile {
  id: string;
  nickname: string;
}

sdk.requestApi<UserProfile>(
  {
    type: 'core',
    url: '/v1/user/profile',
    method: 'GET',
    param: {
      userId: '10001'
    }
  },
  (data) => {
    console.log(data.nickname);
  }
);

参数说明:

| 参数 | 类型 | 必填 | 说明 | | -------- | --------------------- | ---- | ---------------------------- | | type | 'core' \| 'wallet' | 否 | 请求服务类型,默认 'core' | | url | string | 是 | 请求地址 | | method | string | 是 | 请求方法,例如 GET、POST | | param | Record<string, any> | 否 | 请求参数 |

与宿主交换业务数据

sdk.requestApp<{ url: string }>(
  {
    method: 'h5-register',
    param: {
      locale: 'zh-CN'
    }
  },
  (data) => {
    console.log('注册页面:', data.url);
  }
);

method 和 param 由 Web 与宿主共同约定;当前已记录的方法为 h5-register。

WebView 布局与方向

调整输入框高度

sdk.adjustInputBoxHeight(320, (result) => {
  console.log('调整结果:', result);
});

高度单位和结果数据由宿主约定。

切换横屏

sdk.switchLandscape(true, (result) => {
  console.log('切换结果:', result);
});

第一个参数默认值为 true;传 false 表示取消横屏。

分享

share 通过 type 区分短视频、棋牌游戏和系统分享。

短视频分享

sdk.share(
  {
    type: 'shortVideo',
    param: {
      cover_url: 'https://example.com/cover.jpg',
      description: '视频描述',
      title: '视频标题',
      user_id: '10001',
      video_id: 'video-001'
    }
  },
  (result) => {
    console.log('分享结果:', result);
  }
);

棋牌游戏分享

sdk.share(
  {
    type: 'cardGame',
    param: {
      show_type: 3,
      game_path: '/room/10001',
      game_preview_width: 375,
      game_preview_height: 667,
      game_preview_url: 'https://example.com/game-preview',
      currencySource: 'CNY',
      subGameName: {
        ch: '游戏名称',
        en: 'Game name'
      }
    }
  },
  (result) => {
    console.log('分享结果:', result);
  }
);

show_type 的含义:0 为默认旧样式,1 为不带链接的棋牌游戏样式,2 为带链接的棋牌游戏样式,3 为游戏预览。

系统分享

sdk.share({
  type: 'system',
  param: {
    title: '分享标题',
    text: '分享描述',
    shareUrl: 'https://example.com?share_source=tg',
    imageUrl: 'https://example.com/share.png'
  }
});

所有字段均为必填字符串:

| 字段 | 说明 | | ---------- | ---------------------------------------- | | title | 分享标题 | | text | 分享描述 | | shareUrl | 分享链接;游戏分享来源参数 share_source=tg 拼在此链接中 | | imageUrl | 分享图片 URL;宿主下载图片后用于图文分享 |

宿主收到的消息如下:

{
  "type": "share",
  "params": {
    "type": "system",
    "param": {
      "title": "分享标题",
      "text": "分享描述",
      "shareUrl": "https://example.com?share_source=tg",
      "imageUrl": "https://example.com/share.png"
    }
  },
  "appid": "your-app-id",
  "apptoken": "your-app-token"
}

系统分享与其他 share 类型一样,可以传入可选回调。

下载

sdk.download(
  {
    fileType: 'video',
    url: 'https://example.com/video.mp4'
  },
  (result) => {
    console.log('下载结果:', result);
  }
);

当前 fileType 仅支持 'video'。

行为验证码

sdk.behaviorCaptcha(
  {
    token: 'captcha-result-token'
  },
  () => {
    console.log('验证码结果已发送给宿主');
  }
);

此 API 用于 H5 完成滑动验证后,将验证码 token 透传给宿主。

验证码 token 获取失败时,也可沿用同一通道透传上游业务响应;SDK 不解析业务码或文案:

sdk.behaviorCaptcha({
  code: 1038,
  msg: '由业务服务返回的提示',
  data: {}
});

成功结果仍保持 { token },以兼容既有 App。宿主可通过是否存在 params.token 区分成功与业务失败。

系统振动

H5 通过 vibrate 通知宿主调用设备系统振动 / 触觉反馈。未传参数时按短振动处理。

// 默认短振动
sdk.vibrate();

// 短振动,指定强度
sdk.vibrate({ type: 'short', style: 'heavy' });

// 长振动
sdk.vibrate({ type: 'long' }, (isSuccess) => {
  console.log('振动是否已触发:', isSuccess);
});

// 指定时长(毫秒),宿主按系统能力执行
sdk.vibrate({ duration: 200 });

参数说明:

| 参数 | 类型 | 必填 | 说明 | | ---------- | -------------------------------- | ---- | ------------------------------------------------------------ | | type | 'short' \| 'long' | 否 | 振动类型,默认 'short' | | style | 'light' \| 'medium' \| 'heavy' | 否 | 短振动强度,仅 type 为 'short' 时生效 | | duration | number | 否 | 振动时长(毫秒)。与 type 同时存在时,宿主优先按 duration 执行 |

宿主收到的消息如下:

{
  "type": "vibrate",
  "params": {
    "type": "short",
    "style": "heavy"
  },
  "appid": "your-app-id",
  "apptoken": "your-app-token"
}

iOS 建议将 short + style 映射为 UIImpactFeedbackGenerator,long 映射为系统振动;Android 建议使用 VibrationEffect。桌面端和无振动能力的设备可直接回 isSuccess: 0。

宿主接入协议

本节供 iOS、Android、桌面端和 H5 容器开发者实现消息桥接。

Web 回调语义

| API | Web 侧收到的回调值 | | -------------------------- | --------------------------------------------- | | requestApi、requestApp | 宿主返回的业务数据 | | permissions | 宿主返回的权限数据 | | 其他带回调的 API | isSuccess === 1 时为 true,否则为 false |

部分历史 API 的 TypeScript 回调签名为 () => void,调用方可以只把它当作完成通知;SDK 运行时仍会传入 上述布尔结果。

Web 发给宿主的统一消息

interface SDKMessage {
  type: MessageTypeEnum;
  params?: unknown;
  callback?: string;
  appid: string;
  apptoken: string;
}
  • type:原生能力标识,见“API 概览”。
  • params:对应 API 的业务参数。
  • callback:调用方传入回调时由 SDK 生成;无回调时不发送该字段。
  • appid、apptoken:初始化 SDK 时传入的身份信息。

各平台发送通道

| 环境 | SDK 调用的宿主通道 | 消息形式 | | ---------------------- | ------------------------------------------------------------------- | ----------- | | iOS | window.webkit.messageHandlers.JSParent.postMessage(message) | 对象 | | Android | window.JSParent.postMessage(JSON.stringify(message)) | JSON 字符串 | | Windows / Unix / Linux | window.miniJSParent.postMessage(message) | 对象 | | macOS | 优先使用 webkit.messageHandlers.JSParent,否则使用 miniJSParent | 对象 | | H5 iframe | window.parent.postMessage(message, '*') | 对象 |

原生宿主返回回调

消息带有 callback 时,原生宿主处理完成后应调用对应的全局回调:

// 普通原生能力:payment、navigate、share 等
window.IMCallBack[callback](
  JSON.stringify({
    isSuccess: 1,
    callback
  })
);

// requestApi、requestApp
window.receiveData[callback](JSON.stringify(responseData));

// permissions
window.permissions[callback](JSON.stringify(permissionData));

IMCallBack 中 isSuccess 为 1 时,Web 回调接收 true;其他值接收 false。receiveData 和 permissions 的数据会先经过安全 JSON 解析,以避免大整数精度丢失。

H5 容器返回回调

父页面通过 postMessage 返回:

iframeWindow.postMessage(
  {
    type: 'IMCallBack',
    callback: message.callback,
    data: {
      isSuccess: 1
    }
  },
  '*'
);

type 与调用类型的对应关系:

| SDK 调用 | 回调 type | | -------------------------- | ------------- | | requestApi、requestApp | receiveData | | permissions | permissions | | 其他带回调的 API | IMCallBack |

H5 宿主需要在父级 window 上注入:

window['h5-app-version'] = '宿主版本号';

跨域 iframe 无法读取父页面字段时,SDK 会按 H5 容器处理。SDK 只接收 event.source === window.parent 的标准浏览器消息;source === null 的回包会被拒绝,网页宿主应通过 IMSDK.web.createHost 绑定真实 iframe WindowProxy。

回调生命周期

  • 回调被调用后会立即从全局回调表中删除。
  • requestApi 回调在 30 秒后仍未收到响应时会被清理。
  • 其他 API 回调在 10 分钟后仍未收到响应时会被清理。
  • 当前清理行为不会主动调用 Web 侧回调,也不会生成超时错误。

H5 容器外的行为

SDK 面向 App WebView 和宿主 iframe。在普通浏览器顶层页面中,如果不存在原生桥且未注入 h5-app-version,调用不会发送给宿主;传入回调时,SDK 会以 undefined 调用该回调。

导出的类型与工具

除默认导出的 IMSDK 外,包还导出:

  • 类型与枚举 :MessageTypeEnum、IMSDKConfig、IMPaymentParams、IMNavigateParams、IMRequestParams、IMRequestAppParams、IMPopupParams、IMShareParams、IMSystemShareParams、IMDownLoadParams、IMBehaviorCaptchaParams、IMVibrateParams、IMChainCurrencyEnum 等。
  • 工具:safeJSONParse、uuidv4、getOS、Md5。

大整数 JSON 解析示例:

import { safeJSONParse } from 'im2-link-jssdk';

const data = safeJSONParse('[123456789123456789123456789, 2.3]');
// 超出 JavaScript 安全整数范围的数字以字符串形式保留

本地开发

npm install
npm run build
npm run doc
  • npm run build:生成 ESM、CommonJS 和类型声明到 dist/。
  • npm run doc:根据源码类型和注释生成 TypeDoc 到 docs/。
  • 项目要求 Node.js >= 22.0.0。

发布流程见 PUBLISH.md。

网页宿主接口 web

网页容器可以直接使用 IMSDK.web.createHost(也可 import { web }),不需要创建游戏端 SDK 实例或传入 app token。该入口没有自动监听副作用,也不会改动 iOS/Android/PC 的原生桥。

import IMSDK from 'im2-link-jssdk';

const host = IMSDK.web.createHost({
  getTarget: () => iframe.contentWindow ? {
    source: iframe.contentWindow,
    origin: new URL(iframe.src).origin,
    key: `${currentAccountId}:${currentAppId}:${iframe.src}`
  } : null,
  onMessage: async (request) => {
    if (request.message.type !== 'share') return;
    // params 为 { type: 'cardGame', param: { show_type, game_path, ... } }。
    // 宿主必须校验 message.appid 与当前 iframe 的可信应用资料,然后让用户选会话。
    const accepted = await selectAndShare(request.message.params, request.signal);
    request.reply('IMCallBack', { isSuccess: accepted ? 1 : 0 });
  }
});
host.listen();
// iframe 关闭/重新加载、切账号和卸载时:
host.stop();
  • getTarget 必须来自宿主 iframe,不得用收到的 event.origin 或消息里的 appid 生成信任规则。origin 必须精确匹配,禁止 *。显式绑定 origin: 'null' 才接受 opaque iframe,此时回包使用浏览器要求的 *,仍严格绑定 WindowProxy。
  • key 标识当前应用/账号/页面。异步工作前使用 request.isCurrent();重新加载同一地址时也应 stop() 后 listen(),中止旧业务。监听只校验窗口来源,不代替宿主的 app token/权限验证。
  • reply('IMCallBack' | 'receiveData' | 'permissions', data) 自动带上原 callback,只能回复一次。停止或目标变化后的回复返回 false。业务回调 share(params, cb) 继续收到 boolean,不改变旧 API。
  • onMessage 的 Promise 拒绝时回 {isSuccess:0,error:'HOST_ERROR'};可用 onError 接入宿主诊断,不应输出完整请求凭据。不支持的业务应由宿主明确回失败。
  • 默认只分发 SDK 已声明消息类型,额外旧游戏事件通过 additionalMessageTypes 注册;normalizeMessage 只用于拆开宿主已有扩展包装,执行前已经校验 source/origin。
  • 已有事件循环可调用 handleMessage(event);不要同时再把同一事件交给自己的业务处理器。web.parseMessage(value) 只做对象/JSON 结构解析,不做来源或权限验证。
  • 同源与跨域 iframe 都支持网页通信,不要求父网页注入 h5-app-version。原生环境仍优先现有原生桥。没有原生桥、没有标记的顶层独立页仍不冒充宿主。

H5 游戏分享宿主将 isSuccess:1 定义为用户确认后,所有选中目标均被 IM 发送 API 接受;这不代表送达/已读。取消、忙碌、不可用及部分失败回 0,原始响应附带 status/sent/failed。iOS 现有分享没有实现结果回包,不应把“已弹出选择器”写为它的成功合同。