open-index/open-npm huggingface dataset:
npm package: @seayoo-account/login-sdk
Description: seayoo account login sdk
Author: web@seayoo.com
Latest version: 1.2.0

# Seayoo Account Login SDK

## Web页面使用

```js
import { AccountLogin } from "@seayoo-account/login-sdk";

// 环境标记支持 dev / prod
const loginSDK = new AccountLogin("dev");

// 返回 Error 表示意外错误，返回 false 表示用户关闭，返回非空字符串表示 idToken
const idToken = await loginSDK.login();

// 应优先检查 Error 给予提示或调整后续业务逻辑
if (idToken instanceof Error) {
  message.error(idToken.message);
} else if (idToken) {
  // 获得 idToken
}
```

### 自定义配置

```js
const loginSDK = new AccountLogin("dev", {
  /** 是否开启匿名登录模式，开启后隐藏logo/协议和密码登录模式 */
  anonymous: false,
  /** 登录页面打开超时时间，默认 6000，即 6 秒 */
  timeout: 6000,
  /** 背景透明度，默认 0.5 */
  backgroundOpacity: 0.5,
  /** 是否隐藏密码登录模式 */
  hidePasswordLogin: false,
  /** 弹窗的位置，默认 "middle"，可选 "bottom" */
  dialogPosition: "middle";
  /** 用户协议链接，域名受限 */
  userAgreementUrl: "https://www.seayoo.com/....",
  /** 隐私政策链接，域名受限 */
  privacyPolicyUrl: "https://jxfs.seayoo.com/...."
});

// 修改配置
loginSDK.config({ ... })
```

### 错误上报

```js
import { captureException } from "@sentry/vue";

const loginSDK = new AccountLogin("prod");
loginSDK.onError((error) => captureException(error));
```

## 小程序使用

```js
import { NetRequest } from "@seayoo-web/request/wx";
import { AccountLoginWeixin } from "@seayoo-account/login-sdk";

// 环境标记支持 dev / prod
const loginSDK = new AccountLoginWeixin("dev", APP_ID, NetRequest);

// 如果有本地缓存，则直接调用 login 进行静默登录
if (loginSDK.hasLoginToken) {
  const idToken = await loginSDK.login();
  if (idToken instanceof Error) {
    message.error(idToken.message);
  } else if (idToken === "needCode") {
    // 登录 token 失效，需要用户重新授权手机号
  } else {
    // 获得 idToken
  }
}

// 如果没有本地缓存，则需要先获取用户授权手机号
// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
// 获得 code 之后调用登录
const idToken = await loginSDK.login(weixinCode);
if (idToken instanceof Error) {
  message.error(idToken.message);
} else {
  // 获得 idToken
}
```
npm package: @seayoo-web/app-info
Description: app info parser
Author: web@seayoo.com
Latest version: 1.0.1

# app-info

读取 `.apk` `.ipa` `.app` 的应用元信息

## 读取 apk 文件

```ts
import { AndroidAppParser } from "@seayoo-web/app-info";

// file 类型 Uint8Array | ArrayBuffer | Blob;
const parser = new AndroidAppParser(file);
const appInfo = await parser.parse();

if (appInfo instanceof Error) {
  console.log("apk parse error", appInfo.message);
} else {
  console.log(appInfo);
  /**
  {
   "package": "...",
   "versionCode": 9999,
   "versionName": "9999.0.0",
   "icon": "...",
   "manifest": {...}
  */
}

const fileContent = await parser.readFile("AndroidManifest.xml", "text");
```

## 读取 ipa 文件

```ts
import { IosAppParser } from "@seayoo-web/app-info";

// 由于资源保护，.ipa 文件不解析图标资源
const parser = new IosAppParser(file);
const appInfo = await parser.parse();

if (appInfo instanceof Error) {
  console.log("ipa parse error", appInfo.message);
} else {
  console.log(appInfo);
  /**
  {
   "package": "...",
   "versionCode": 9999,
   "versionName": "9999.0.0",
   "icon": "...",
   "plist": {...},
  }
  */
}

// 读取指定模块的 plist 信息
const frameworkPlist = await parser.parseFramework("ComboSDKSentry");
if (frameworkPlist instanceof Error) {
  console.log("ComboSDKSentry parse error", frameworkPlist.message);
} else {
  console.log(frameworkPlist);
}

// 读取指定文件
const fileContent = await parser.readFile("ComboConfig.json", "text");
```

## 读取鸿蒙 app 文件

```ts
import { HosAppParser } from "@seayoo-web/app-info";

const parser = new HosAppParser(file);
// 设置 ignoreIcon: true 可以忽略图标解析以节约解析时间
const appInfo = await parser.parse({ ignoreIcon: false });

if (appInfo instanceof Error) {
  console.log("hos app parse error", appInfo.message);
} else {
  console.log(appInfo);
  /**
  {
   "package": "...",
   "versionCode": 9999,
   "versionName": "9999.0.0",
   "icon": "...",
   "pack": {...},
  }
  */
}
// 读取 app 下文件
const fileContent = await parser.readFile("pack.info", "blob");
// 读取主包下的文件
const fileContent = await parser.readEntryHapFile("pkgInfo.json", "text");
```
npm package: @seayoo-web/auth
Description: web auth sdk for seayoo
Author: web@seayoo.com
Latest version: 0.7.2
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Seayoo.com WebAuthSDK

internal use only.

### configAuth

设置 SDK 基础信息

### sendCaptcha

发送一条验证码

### loginWithPhoneAndCaptcha

使用手机号和验证码进行登录

### silentLoginForWeixin

微信静默登录

### updateWeixinUserInfo

更新用户微信个人信息

### loginWithWeixinPhone

在静默登录后，经过用户授权手机号进行登录

### queryUserInfo

查询用户信息，其中手机号是脱敏过的

### verifyUserRealInfo

实名认证用户信息
npm package: @seayoo-web/combo-webview
Description: combo webview js bridge
Author: web@seayoo.com
Latest version: 2.8.0

# Combo WebView

提供跟 Combo WebView 通信的工具库

[WebView 需求文档](https://365.kdocs.cn/l/ce7c0MFIG5Wj)

[WebView User-Agent](https://365.kdocs.cn/l/ccIHbDmNTlwx)

[Combo SDK - WebView 通信机制](https://365.kdocs.cn/l/ch5GoK1LvTuL)
npm package: @seayoo-web/gamer-api
Description: agent for gamer api
Author: web@seayoo.com
Latest version: 4.0.5

# Gamer Api Agent

## 页面初始化

```js
import { NetRequest } from "@seayoo-web/request";
import { AuthToken, EventApi, ClubApi, CommunityApi } from "@seayoo-web/gamer-api";
import { captureException } from "@sentry/vue";
import { GamerWebAuth } from "@seayoo-web/login";

const authToken = new AuthToken(SY_GAMER_API, NetRequest);
const eventApi = new EventApi(authToken, SY_EVENT_ID);
const clubApi = new ClubApi(authToken);
const communityApi = new CommunityApi(authToken);
const loginSDK = new GamerWebAuth(autoToken, {
  anonymous: false,
  hidePasswordLogin: false,
  // 更多配置 @seayoo-web/login
});

// 调整请求配置
authToken.req.setConfig({
  messageHandler(_, message) {
    toast(message);
  },
  errorHandler({ status, rawError, sentryError, sentryTags, sentryExtra }) {
    if (status === 401) {
      // 提示或直接登录
      // loginSDK.login()
      return;
    }
    // 意外错误进行上报
    if (rawError) {
      captureException(sentryError, {
        extra: sentryExtra,
        tags: sentryTags,
      });
    }
  },
});

// 导出供其他功能使用
export { eventApi, clubApi, communityApi, loginSDK };
```

## 小程序初始化

```js
import { NetRequest } from "@seayoo-web/request/wx";
import { AuthToken, EventApi, ClubApi, WeixinApi } from "@seayoo-web/gamer-api";
import { GamerWeixinAuth } from "@seayoo-web/login";

const authToken = new AuthToken(SY_GAMER_API, NetRequest);
const eventApi = new EventApi(authToken, SY_EVENT_ID);
const clubApi = new ClubApi(authToken);
const communityApi = new CommunityApi(authToken);
const weixinApi = new WeixinApi(authToken, SY_APP_ID);
const loginSDK = new GamerWeixinAuth(authToken, weixinApi);

// 调整请求配置
authToken.req.setConfig({
  messageHandler(_, message) {
    toast(message);
  },
  errorHandler({ status, rawError, sentryError, sentryTags, sentryExtra }) {
    if (status === 401) {
      // 提示或直接登录
      if(loginSDK.hasLoginToken) {
         loginSDK.login()
      } else {
         // 跳转到用户手机号授权页面
      }
      return;
    }
    // 意外错误进行上报
    if (rawError) {
      captureException(sentryError, {
        extra: sentryExtra,
        tags: sentryTags,
      });
    }
  },
});

// 导出供其他功能使用
export { eventApi, clubApi, communityApi, weixinApi, loginSDK };
```
npm package: @seayoo-web/i18n
Description: utils of i18n
Author: web@seayoo.com
Latest version: 1.1.0

# i18n

```js
// 定义语言包数据类型
interface LanguagePackData {
  someKey: string,
  dataKey: {
    payload: string,
    count: number
  }
}

// 定义语言包配置类型
// 配置类型会添加 Record<`api_${string}`, string> 的联合类型用以支持 api 响应的翻译
import type { DefineLanguagePack } from "@seayoo-web/i18n"
type LanguagePack = DefineLanguagePack<LanguagePackData>;

// 定义配置文件
const pack: LanguagePack = {
  someKey: "....",
  dataKey: "...."
}

// 创建语言包管理器
import { createLangPackManager } from "@seayoo-web/i18n"
// 可以直接内联加载默认语言包
import { pack as zhCnPack } from "./packs/zh-cn.ts";
const languagePack = createLangPackManager<LanguagePackData>([
  {
    id: "zh-CN",
    name: "简体中文",
    isDefault: true,
    // 需要导出包含 pack 字段的模块
    load: () => Promise.resolve({ pack: zhCnPack })
  },
  {
    id: "en-US",
    name: "English",
    load: () => import("./packs/en-US.ts")
  }
])

// 读取支持的语言列表
languagePack.supportLanguages;

// 读取当前语言包编号，初始化 lang 为空字符串
languagePack.lang;

// 可以从 url 的 lang 参数读取语言编号
await languagePack.loadWithDefault(queryString("lang"))

// 使用 t 函数进行翻译，
languagePack.t("someKey", "这是默认值")
languagePack.t("dataKey", { payload: "这是动态填充内容", count: 1  }, "可以继续设置默认值")

// t 函数做了 bind 处理，可以直接引用到需要的地方
// 比如设置到 vue 全局静态属性
app.config.globalProperties.t = languagePackage.t;
// 同时给予类型定义
declare module "vue" {
  interface ComponentCustomProperties {
    t: typeof languagePackage.t;
  }
}

```
npm package: @seayoo-web/kms
Description: agent for seayoo.kms
Author: web@seayoo.com
Latest version: 3.5.2

# KMS Agent

- dsi 查询工具
  - `query` 以 ajax 方式查询 dsi 数据
  - `jsonp` 以 jsonp 方式查询 dsi 数据，微信环境无效
  - `jsonx` 以 script 方式查询 dsi 数据，微信环境无效
  - `convertDsiParam` 工具函数，将 dsi query 参数转成 request param

```js
import { KMSDsi } from "@seayoo-web/kms";
import { NetRequest } from "@seayoo-web/request";

const dsi = new KMSDsi("https://<project>.dsi.seayoo.com", NetRequest);

// 如需要调整 req 工具函数配置
// 详情参看 @seayoo-web/request 工具配置
dsi.req.setConfig({
  timeout: 5000,
});

dsi.query({ key, query, guard });
```

```js
import { convertDsiParam } from "@seayoo-web/kms";

// 可以仅仅使用工具来生成 dsi 的查询参数
const param = convertDsiParam(query);
```
npm package: @seayoo-web/login
Description: seayoo login
Author: web@seayoo.com
Latest version: 1.2.3

# Seayoo Login

## Gamer Web Login

```js
import { NetRequest } from "@seayoo-web/request";
import { AuthToken } from "@seayoo-web/gamer-api";
import { GamerWebAuth } from "@seayoo-web/login";

// 创建 AuthToken 实例
const authToken = new AuthToken(SY_GAMER_API, NetRequest);
// 修改请求工具配置
authToken.req.setConfig({
  messageHandler(_, message) {
    toast(message);
  },
  errorHandler({ status, rawError, sentryError, sentryTags, sentryExtra }) {
    if (status === 401) {
      // 提示或直接登录
      // toast('xxx')
      gamerAuth.login();
      return;
    }
    // 意外错误进行上报
    if (rawError) {
      captureException(sentryError, {
        extra: sentryExtra,
        tags: sentryTags,
      });
    }
  },
});

// 创建 GamerAuth 实例，可选登录组件配置
const gamerAuth = new GamerWebAuth(authToken, {
  anonymous: false,
  hidePasswordLogin: false,
  // 更多配置见类型 AccountLoginOption
});
// 可以在需要的时候修改登录组件参数
gamerAuth.config({
  hidePasswordLogin: true
});

// 上报登录过程中的异常
gamerAuth.onError(function (error) {
  captureException(error);
});

// gamerAuth 方法
// 是否登录
gamerAuth.isLoggedIn();
// 登录
const result = await gamerAuth.login();
// 退出
gamerAuth.logout();
// 获取用户信息，默认读取页面缓存（session cache）
const userInfo = await gamerAuth.getUserInfo();
// 获取最新的用户信息
const userInfo2 = await gamerAuth.getUserInfo(true);
// 实名认证
await gamerAuth.realNameAuth({ ... });
```

## Gamer Weixin Login

```js
import { NetRequest } from "@seayoo-web/request/wx"; // 与 web 使用不同
import { AuthToken, WeixinApi } from "@seayoo-web/gamer-api";
import { GamerWeixinAuth } from "@seayoo-web/login"; // 与 web 使用不同

// 创建 AuthToken 实例
const authToken = new AuthToken(SY_GAMER_API, NetRequest);
// 修改请求工具配置
authToken.req.setConfig({
  messageHandler(_, message) {
    toast(message);
  },
  errorHandler({ status, rawError, sentryError, sentryTags, sentryExtra }) {
    if (status === 401) {
      // 提示或直接登录
      // toast('xxx')
      gamerAuth.login();
      return;
    }
    // 意外错误进行上报
    if (rawError) {
      captureException(sentryError, {
        extra: sentryExtra,
        tags: sentryTags,
      });
    }
  },
});

// 创建 WeixinApi 实例
const weixinApi = new WeixinApi(authToken, APP_ID);
// 创建 GamerWeixinAuth 实例
const gamerAuth = new GamerWeixinAuth(authToken, weixinApi);

// gamerAuth 方法
// 是否登录
gamerAuth.isLoggedIn();
// 检测登录状态变更
// 默认在缓存有长期登录token的时候会自动触发登录，登录后会通知状态变更
gamerAuth.onStatusChange((loggedIn) => {
  console.log("当前登录状态为", loggedIn);
});
// 自动登录（有缓存的长期登录token时）
// 以下自动登录逻辑会在实例创建的时候执行，不需要手动触发
if (gamerAuth.hasLoginToken) {
  const result = await gamerAuth.login();
}
// 页面上显示登录按钮时，需要用户授权手机号访问，获得微信返回的授权 code
// 然后执行登录流程
const result = await gamerAuth.login(WeixinCode);
// 退出
gamerAuth.logout();
// 获取 unionId 和 openId
await gamerAuth.getUnionId();
await gamerAuth.getOpenId();
// 获取用户信息，优先读取页面缓存（session cache）
await gamerAuth.getUserInfo();
// 从服务器获取最新的用户信息
await gamerAuth.getUserInfo(true);
```
npm package: @seayoo-web/pixi-live2d
Description: pixi-live2d viewer
Author: web@seayoo.com
Latest version: 0.1.0

# @seayoo-web/pixi-live2d

基于 `pixi-live2d-display` 的二次封装库，旨在简化 Live2D 模型的加载与交互。原库 `pixi-live2d-display` 因维护停滞且依赖复杂，本库对其进行了整理与封装，提供更友好的 API。

## 特性

- **零 Vue 依赖**：纯 TypeScript 实现，可用于任何框架（React, Vue, Vanilla JS）。
- **自动缩放**：内置适配 1920x1080 设计稿的响应式缩放逻辑。
- **简单易用**：只需传入 Canvas 元素和模型路径即可。
- **交互支持**：内置点击交互与动作播放方法。

## 安装

```bash
pnpm add @seayoo-web/pixi-live2d
```

## 在你的项目中使用：

### 基础用法

```typescript
import { Live2DViewer } from "@seayoo-web/pixi-live2d";

// 方式 1: 传入 Canvas ID
const viewer1 = new Live2DViewer("live2d-canvas", {
  modelPath: "https://cdn.example.com/live2d/model.json",
});

// 方式 2: 传入 HTMLCanvasElement 并配置初始参数
const canvasElement = document.getElementById("my-canvas") as HTMLCanvasElement;
const viewer2 = new Live2DViewer(canvasElement, {
  modelPath: "https://cdn.example.com/live2d/model.json",

  // 初始位置和缩放
  x: 0,
  y: 0,
  scale: 0.2, // 模型缩放比例

  // 设计稿尺寸 (用于自动计算适配比例)
  designWidth: 1920,
  designHeight: 1080,

  autoResize: true,

  onModelLoaded: (model) => {
    console.log("模型加载成功:", model);
  },
  onModelError: (error) => {
    console.error("模型加载失败:", error);
  },
});
```

### API 说明

#### `new Live2DViewer(canvas, options)`

- `canvas`: `HTMLCanvasElement | string` - 用于渲染的 Canvas 元素或其 ID
- `options`: `Live2DViewerOptions` - 配置项

| 属性 | 类型 | 默认值 | 说明 |
|Data Type|Type|Default|Description|
|---|---|---|---|
| `modelPath` | `string` | (必填) | Live2D 模型配置文件 (.json) 的路径 |
| `scale` | `number` | - | 初始缩放比例 |
| `x` | `number` | 0 | 初始 X 轴偏移 |
| `y` | `number` | 0 | 初始 Y 轴偏移 |
| `designWidth` | `number` | 1920 | 设计稿宽度（用于适配计算） |
| `designHeight` | `number` | 1080 | 设计稿高度（用于适配计算） |
| `autoResize` | `boolean` | `true` | 是否监听窗口 resize 事件并自动调整模型大小 |
| `onModelLoaded` | `(model) => void` | - | 模型加载完成后的回调函数 |
| `onModelError` | `(error) => void` | - | 模型加载失败的回调函数 |

#### 实例方法

- **`startMotion(group: string, no: number)`**
  播放指定分组的动作。

  ```typescript
  viewer.startMotion("TapBody", 0);
  ```

- **`setScale(scale: number)`**
  设置模型的缩放比例（基于自动计算的基础比例）。

  ```typescript
  viewer.setScale(0.2);
  ```

- **`resize()`**
  手动触发一次重新计算布局（通常在容器大小变化但窗口大小未变时使用）。

  ```typescript
  viewer.resize();
  ```

- **`destroy()`**
  销毁实例，清理 PIXI 应用及事件监听。
  ```typescript
  viewer.destroy();
  ```

## 注意事项

本库依赖 `pixi.js` v6 版本（与 `pixi-live2d-display` 兼容），请确保项目中未安装冲突的 PIXI 版本。