npm package: @jiangzhongxi0322/messagechannel
Description: A message channel for communication between VSCode extensions and webviews.
Author: jiangzhongxi0322
Latest version: 1.0.2

# MessageChannel 库

一个轻量级的消息通道库，用于在 VSCode 扩展和 Webview 之间进行通信。

## 特性

- **双向通信**：在 VSCode 扩展和 Webview 之间实现无缝通信。
- **事件订阅**：允许订阅特定事件类型以进行有针对性的消息处理。
- **基于 Promise 的 API**：支持使用 async/await 模式处理消息和响应。
- **跨扩展通信**：促进不同 VSCode 扩展之间的通信。

## 安装

通过 npm 安装库：

```bash
npm install messagechannel
```

## 使用方法

### 基本设置

#### 在 VSCode 扩展（Node.js 端）

```typescript
import MessageChannel from 'messagechannel';

const channel = MessageChannel();

// 设置载体（VSCode Webview）
channel.setCarrier(yourWebview);

// 订阅一个事件
channel.subscribe('eventType1', (data) => {
  console.log('接收到的数据:', data);
});

// 发布一个事件
channel.publish('eventType2', { key: 'value2' });
```

#### 在 Webview（浏览器端）

```typescript
import MessageChannel from 'messagechannel';

const channel = MessageChannel();

// 初始化通道（Webview 中不需要载体）
channel.setCarrier(undefined);

// 订阅一个事件
channel.subscribe('eventType2', (data) => {
  console.log('接收到的数据:', data);
});

// 发布一个事件
channel.publish('eventType1', { key: 'value1' });
```

### 高级用法

#### 使用 `pubWithSub` 进行请求-响应模式

```typescript
import MessageChannel from 'messagechannel';

const channel = MessageChannel();

// 发布并订阅一次调用
const response = await channel.pubWithSub('eventType', { key: 'value' }); // 也可以channel.pubWithSub('eventType', { key: 'value' }, (response) => {})
console.log('响应:', response);
```

#### 跨扩展通信
插件A的web端
```typescript
import MessageChannel from 'messagechannel';

const channel = MessageChannel();

// 向另一个扩展发布事件
channel..pubWithSub(extensionId, options, callback);
```

1. extensionId，要通信的插件的唯一标识，由package.json中的name和publisher组成。
 
2. options，是一个对象，包含如下选项：

   1. viewType，要打开的webview的type，一般声明为静态类型。

   2. source

	| 文件预览型webview | 命令打开的webview面板 |
	| ----- | ----- |
	| D:\\\\project\\\\vscode\\\\vscode-extension-samples\\\\url-webview-sample\\\\exampleFiles\\\\example.cscratch' | 相应的命令 |

   3. selector，打开web后要自动点击的元素的选择器列表，多个元素依次点击。比如打开env的页面后自动添加添加按钮。

   4. payload，要传递的额外参数，这个参数会自动添加为selector对应元素的payload属性

3. callback，接受另一个插件的web部分回传的数据
###### 示例

```typescript
// 扩展 A webviewProvider
const channel = MessageChannel();
channel.initiator(ColorsViewProvider.viewType);
// 这俩顺序没关系
channel.setCarrier(webview);
// 扩展 A web 在某个时机比如点击按钮调用下面就会自动打开扩展B的webview
channel.pubWithSub('extensionB', 
  { 
	viewType: 'catCustoms.catScratch',
	source: 'D:\\\\project\\\\vscode\\\\vscode-extension-samples\\\\url-webview-sample\\\\exampleFiles\\\\example.cscratch',
	selector: ['input'],
	payload: value
  },
  (data) => {
	console.log(data);
  });

// 扩展 B webviewProvider  
const channel = MessageChannel();
channel.initiator(CatCodingPanel.viewType);
// 这俩顺序没关系
channel.setCarrier(webview);
// 扩展 B web 在某个实际比如点击事件，可以通过feedbackResult回馈数据
const channel = MessageChannel();
document.querySelector('button').addEventListener('click', (args) => {
  const result = document.querySelector('input').value;
  feedbackResult && feedbackResult(result);
});
channel.setCarrier();
channel.initiator();
```

## API 参考

### `MessageChannel()`

创建一个新的消息通道实例。

#### 返回值

一个包含以下方法的对象：

- `publish(typename: string, msg?: any)`：向通道发布消息。
- `subscribe(typename: string, subscriber: (data: FeedbackData) => any, once?: boolean)`：订阅一个消息类型。
- `setCarrier(carrier: any)`：设置消息通道的载体。
- `pubWithSub(typename: string, msg: any, subscriber?: (data: FeedbackData) => any)`：发布消息并订阅响应。
- `initiator(viewType: string)`：初始化特定 Webview 类型的通信。
- `getCarrier()`：获取当前载体。

### 接口

#### `Event`

```typescript
interface Event {
  typename?: string;
  key?: string;
  channelId: string;
  data: FeedbackData;
}
```

#### `FeedbackData`

```typescript
interface FeedbackData {
  code: 0 | 1 | 2;
  msg: string;
  data: any;
}
```

## 许可证

本项目采用 MIT 许可证。详情请见 [LICENSE](LICENSE) 文件。