npm package: @liujialin/hybrid-sdk
Description: Hybrid JSBridge SDK with HTTP capabilities
Author: 1473972376@qq.com
Latest version: 1.0.5

# @liujialin/hybrid-sdk

[![npm version](https://badge.fury.io/js/%40liujialin%2Fhybrid-sdk.svg)](https://badge.fury.io/js/%40liujialin%2Fhybrid-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

一个基于dsBridge的Hybrid JSBridge SDK，支持Promise和回调两种模式调用移动端原生方法。

## ✨ 特性

- 🚀 **Promise & 回调**: 支持现代Promise API和传统回调方式
- 📱 **iOS/Android**: 完整的移动端平台支持
- 🔗 **WebView桥接**: 调用原生App注入的JavaScript方法
- 📦 **轻量级**: 专注于桥接功能，无额外依赖
- 🎯 **TypeScript**: 完整的类型支持
- 🛠️ **灵活使用**: 支持npm安装和CDN引入

## 📦 npm 安装与使用

### 安装

```bash
# 使用 npm
npm install @liujialin/hybrid-sdk

# 使用 yarn
yarn add @liujialin/hybrid-sdk

# 使用 pnpm
pnpm add @liujialin/hybrid-sdk
```

### npm 项目中使用

#### 方式一：ES6 模块导入 (推荐)

```javascript
import { DSBridgePromise, DSBridgeCompat } from '@liujialin/hybrid-sdk';

// Promise模式 (推荐)
const bridge = new DSBridgePromise();
const result = await bridge.call('NativeToken');
console.log('原生返回:', result);

// 兼容模式
const compatBridge = new DSBridgeCompat();
compatBridge.call('NativeToken', null, (result) => {
  console.log('原生返回:', result);
});
```

#### 方式二：CommonJS 导入

```javascript
const { DSBridgePromise, DSBridgeCompat } = require('@liujialin/hybrid-sdk');

// 使用方式同上
const bridge = new DSBridgePromise();
```

### TypeScript 项目支持

```typescript
import { DSBridgePromise, DSBridgeCompat } from '@liujialin/hybrid-sdk';

// 完整的类型支持
const bridge = new DSBridgePromise();

// 方法调用带有类型提示
const userInfo: any = await bridge.call('getUserInfo');
const deviceInfo: any = await bridge.call('getDeviceInfo');
```

## 🌐 CDN 引入与使用

### CDN 链接

```html
<!-- 最新版本 -->
<script src="https://cdn.jsdelivr.net/npm/@liujialin/hybrid-sdk@latest/DSBridge/hybrid-sdk.js"></script>

<!-- 指定版本 -->
<script src="https://cdn.jsdelivr.net/npm/@liujialin/hybrid-sdk@1.0.1/DSBridge/hybrid-sdk.js"></script>

<!-- 或者使用 unpkg -->
<script src="https://unpkg.com/@liujialin/hybrid-sdk@latest/DSBridge/hybrid-sdk.js"></script>
```

### CDN 方式使用

#### 方式一：使用SDK类

```html
<!DOCTYPE html>
<html>
<head>
    <title>CDN方式使用Hybrid SDK</title>
    <script src="https://cdn.jsdelivr.net/npm/@liujialin/hybrid-sdk@latest/DSBridge/hybrid-sdk.js"></script>
</head>
<body>
    <h1>Hybrid SDK CDN使用示例</h1>
    <button onclick="testPromiseMode()">Promise模式测试</button>
    <button onclick="testCompatMode()">兼容模式测试</button>

    <script>
        // Promise模式
        async function testPromiseMode() {
            try {
                const bridge = new window.HybridSDK.DSBridgePromise();
                const result = await bridge.call('NativeToken');
                console.log('Promise模式结果:', result);
                alert('Promise模式调用成功: ' + JSON.stringify(result));
            } catch (error) {
                console.error('Promise模式调用失败:', error);
                alert('Promise模式调用失败: ' + error.message);
            }
        }

        // 兼容模式
        function testCompatMode() {
            const bridge = new window.HybridSDK.DSBridgeCompat();
            bridge.call('NativeToken', null, (result) => {
                console.log('兼容模式结果:', result);
                alert('兼容模式调用成功: ' + JSON.stringify(result));
            });
        }
    </script>
</body>
</html>
```

#### 方式二：直接使用dsBridge

```html
<!DOCTYPE html>
<html>
<head>
    <title>直接使用dsBridge</title>
    <script src="https://cdn.jsdelivr.net/npm/@liujialin/hybrid-sdk@latest/DSBridge/hybrid-sdk.js"></script>
</head>
<body>
    <h1>直接使用dsBridge</h1>
    <button onclick="testDirectCall()">直接调用</button>

    <script>
        function testDirectCall() {
            // 直接使用底层的dsBridge (如果可用)
            if (window.dsBridge) {
                window.dsBridge.call('NativeToken', null, (result) => {
                    console.log('直接调用结果:', result);
                    alert('直接调用成功: ' + JSON.stringify(result));
                });
            } else {
                alert('dsBridge不可用，请在移动端App中使用');
            }
        }
    </script>
</body>
</html>
```

## 📚 API 文档

### DSBridgePromise 类

基于Promise的现代化API，推荐使用。

#### `call<T>(method: string, params?: any, timeout?: number): Promise<T>`

调用原生方法，返回Promise。

**参数**:
- `method`: 原生方法名
- `params`: 参数对象（可选）
- `timeout`: 超时时间（毫秒，默认10000）

**示例**:
```javascript
const bridge = new DSBridgePromise();

// 基本调用
const result = await bridge.call('getUserInfo');

// 带参数调用
const data = await bridge.call('processData', { action: 'save' });

// 设置超时
const result = await bridge.call('longTask', params, 30000);

// 自动检查方法存在性 - 如果方法不存在会抛出错误
try {
  const result = await bridge.call('nonExistentMethod');
} catch (error) {
  console.log('方法不存在:', error.message);
  // 输出: Native method 'nonExistentMethod' is not available
}
```

#### 其他方法

```javascript
const bridge = new DSBridgePromise();

// 检查方法是否存在
const exists = bridge.hasNativeMethod('getUserInfo');

// 注册JavaScript方法供原生调用
bridge.register('getWebData', () => {
  return { url: window.location.href };
});

// 注册异步方法
bridge.registerAsyn('asyncTask', async (data) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  return { processed: data };
});

// 检查可用性
const isAvailable = bridge.isAvailable();
```

### DSBridgeCompat 类

传统回调模式的API，向后兼容。

#### `call(method: string, params?: any, callback?: Function): void`

调用原生方法，使用回调函数接收结果。

**参数**:
- `method`: 原生方法名
- `params`: 参数对象（可选）
- `callback`: 结果回调函数

**示例**:
```javascript
const bridge = new DSBridgeCompat();

// 基本调用
bridge.call('getUserInfo', null, (result) => {
  console.log('用户信息:', result);
});

// 带参数调用
bridge.call('processData', { action: 'save' }, (result) => {
  console.log('处理结果:', result);
});
```

## 🎯 使用场景

### Vue 3 项目

```javascript
// composables/useHybridBridge.js
import { DSBridgePromise } from '@liujialin/hybrid-sdk';

export function useHybridBridge() {
  const bridge = new DSBridgePromise();

  const callNative = async (method, params) => {
    try {
      return await bridge.call(method, params);
    } catch (error) {
      console.error('调用原生方法失败:', error);
      throw error;
    }
  };

  return { callNative };
}
```

```vue
<template>
  <div>
    <button @click="getToken">获取Token</button>
    <p v-if="token">Token: {{ token }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useHybridBridge } from '@/composables/useHybridBridge';

const { callNative } = useHybridBridge();
const token = ref('');

const getToken = async () => {
  try {
    token.value = await callNative('NativeToken');
  } catch (error) {
    console.error('获取Token失败:', error);
  }
};
</script>
```

### React 项目

```javascript
// hooks/useHybridBridge.js
import { useCallback } from 'react';
import { DSBridgePromise } from '@liujialin/hybrid-sdk';

export function useHybridBridge() {
  const bridge = new DSBridgePromise();

  const callNative = useCallback(async (method, params) => {
    try {
      return await bridge.call(method, params);
    } catch (error) {
      console.error('调用原生方法失败:', error);
      throw error;
    }
  }, []);

  return { callNative };
}
```

```jsx
import React, { useState } from 'react';
import { useHybridBridge } from './hooks/useHybridBridge';

function App() {
  const { callNative } = useHybridBridge();
  const [token, setToken] = useState('');

  const getToken = async () => {
    try {
      const result = await callNative('NativeToken');
      setToken(result);
    } catch (error) {
      alert('获取Token失败: ' + error.message);
    }
  };

  return (
    <div>
      <button onClick={getToken}>获取Token</button>
      {token && <p>Token: {token}</p>}
    </div>
  );
}
```

### 原生App集成

#### iOS (WKWebView)

```swift
// 在ViewController中
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let config = WKWebViewConfiguration()
        // 配置dsBridge
        config.userContentController.add(self, name: "dsBridge")

        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        view.addSubview(webView)

        // 加载HTML
        if let url = Bundle.main.url(forResource: "index", withExtension: "html") {
            webView.loadFileURL(url, allowingReadAccessTo: url)
        }
    }
}

// 实现WKScriptMessageHandler
extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController,
                              didReceive message: WKScriptMessage) {
        if message.name == "dsBridge" {
            // 处理来自JavaScript的调用
            print("收到JS调用:", message.body)
        }
    }
}
```

#### Android (WebView)

```kotlin
// 在Activity中
import android.webkit.WebView
import android.webkit.WebViewClient

class MainActivity : AppCompatActivity() {
    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById(R.id.webView)
        webView.settings.javaScriptEnabled = true

        // 配置WebView
        webView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                // 页面加载完成后可以调用JS方法
                super.onPageFinished(view, url)
            }
        }

        // 加载HTML
        webView.loadUrl("file:///android_asset/index.html")
    }
}
```

## 🔧 故障排除

### 常见问题

#### 1. `dsBridge is not available` 错误

**问题**: 在浏览器中调用原生方法时出现此错误

**原因**: dsBridge只在移动端App的WebView中可用

**解决**:
```javascript
const bridge = new DSBridgePromise();

if (bridge.isAvailable()) {
  // 在移动端App中，可以正常调用
  const result = await bridge.call('NativeToken');
} else {
  // 在浏览器中，模拟数据或显示提示
  console.log('请在移动端App中使用此功能');
}
```

#### 2. 调用超时

**问题**: 调用原生方法超时

**解决**: 调整超时时间
```javascript
// 设置更长的超时时间
const result = await bridge.call('longRunningTask', params, 30000); // 30秒
```

#### 3. 方法不存在错误

**问题**: 抛出 "Native method 'xxx' is not available" 错误

**原因**: SDK会在调用前自动检查方法是否存在，如果不存在会立即报错

**解决**: 确保原生App已注册相应方法

```javascript
// 检查方法是否存在
const bridge = new DSBridgePromise();

if (bridge.hasNativeMethod('NativeToken')) {
  const result = await bridge.call('NativeToken');
} else {
  console.log('原生方法未注册，请检查原生App代码');
}

// 或者直接调用，会自动检查
try {
  const result = await bridge.call('NativeToken');
} catch (error) {
  console.log('方法调用失败:', error.message);
}
```

## 📄 许可证

MIT License

## 📞 联系我们

如有问题或建议，请联系：
- 📧 邮箱: 1473972376@qq.com

---

**Made with ❤️ by liujialin**