@dino-dev/bridge-core-ts
v0.0.5
Published
Bridge Core SDK for h5_app_container — H5 ↔ Flutter 通信 + 原生模块类型安全调用(零框架依赖)
Maintainers
Readme
Bridge Core TS
H5 端与 Flutter 容器通信的核心 TypeScript SDK(零框架依赖)。 适用于 React / Vue / Svelte / Vanilla JS 等任何前端框架。
文件说明
| 文件 | 用途 |
|------|------|
| src/mrp-bridge.ts | 核心 Bridge SDK(消息通信 + 模块代理) |
| src/system-module.ts | 内置系统模块类型定义 + getSystemModule() 工厂 |
| src/content-protocol.ts | 标准渲染、交互与错误协议 |
| src/index.ts | 包入口,统一 re-export 所有 API |
| generated/*_module.ts | 各模块的 TypeScript 类型定义(由 build_runner 自动生成,纯类型) |
| generated/index.ts | 自动生成的模块类型 re-export + 工厂函数 |
设计原则:消费者只需从
@h5-container/bridge-core-ts导入,无需感知generated/目录。
安装
通过 pnpm workspace 依赖引用:
{
"dependencies": {
"@h5-container/bridge-core-ts": "workspace:*"
}
}基础用法
import { bridge, getAudio } from '@h5-container/bridge-core-ts';
// 发送消息到 Flutter(type 为自由字符串)
bridge.send('interaction', 'onFindTarget', { target: 'ladybug', position: { x: 100, y: 200 } });
// 调用原生模块(通过工厂函数,无需手动指定 namespace)
const audio = getAudio();
await audio.play({ soundId: 'success', volume: 0.8 });
// 监听 Flutter 发来的消息
const unsubscribe = bridge.on('ai', 'highlight', (msg) => {
console.log('AI 指令:', msg.payload);
});
// 不再需要时取消监听
unsubscribe();在 React 中使用
SDK 本身不依赖 React,搭配 useMemo / useEffect 即可:
import { useMemo, useEffect, useCallback, useState } from 'react';
import { bridge, getAudio, getDevice } from '@h5-container/bridge-core-ts';
function FindBugGame({ bugs }) {
const audio = useMemo(() => getAudio(), []);
const device = useMemo(() => getDevice(), []);
// 监听 AI 指令(useEffect 自动清理)
const [aiState, setAiState] = useState('idle');
useEffect(() => {
return bridge.on('ai', null, (msg) => {
const s = (msg.payload as Record<string, unknown>)?.aiState as string;
if (s) setAiState(s);
});
}, []);
const handleClick = async (bugId: string) => {
bridge.send('interaction', 'onFindTarget', { target: bugId });
await audio.play({ soundId: 'success', volume: 0.8 });
await device.vibrate({ duration: 50 });
};
return <div>{/* ... */}</div>;
}在 Vue 中使用
import { bridge, getAudio } from '@h5-container/bridge-core-ts';
const audio = getAudio();
// 在 setup / onMounted 中使用
onMounted(() => {
const unsubscribe = bridge.on('ai', 'highlight', (msg) => {
console.log('AI 指令:', msg.payload);
});
onUnmounted(() => unsubscribe());
});
async function playSound() {
await audio.play({ soundId: 'success', volume: 0.8 });
}原生模块调用
Flutter 宿主通过 registerModule() 注册的模块,前端通过工厂函数获取类型安全的代理:
import { getAudio, getDevice, getUser } from '@h5-container/bridge-core-ts';
const audio = getAudio();
await audio.play({ soundId: 'success', volume: 0.8 });
const device = getDevice();
const info = await device.getDeviceInfo();
// 仅导入类型
import type { Audio, Device } from '@h5-container/bridge-core-ts';内置系统模块
容器自动注册的系统模块不受白名单限制,通过 getSystemModule() 访问:
import { getSystemModule } from '@h5-container/bridge-core-ts';
const system = getSystemModule();
const { allowed } = await system.isModuleAllowed({ namespace: 'audio' });
const { modules } = await system.getAvailableModules();
const info = await system.getContainerInfo();App 统一屏幕适配
在使用设计稿尺寸的 H5 中初始化一次,即可使用与 Flutter .ar 相同的缩放规则:
import {
ar,
getArScale,
initArAdaptation,
onArAdaptationChange,
} from '@h5-container/bridge-core-ts';
await initArAdaptation();
const style = { width: ar(120), fontSize: ar(18) };
// React 等框架可在回调中更新 state,触发使用 ar() 的样式重新计算。
const unsubscribe = onArAdaptationChange(() => {
setScale(getArScale());
});App 横竖屏或窗口尺寸变化时,SDK 会自动更新比例并触发订阅回调。组件销毁时调用 unsubscribe()。当前工具覆盖 TS/TSX 数值样式;CSS 全局适配暂不自动修改页面根字号。
标准内容协议
SDK 为内容型 H5 固定定义以下协议域:
| 方向 | type | action | payload |
|---|---|---|---|
| Flutter → H5 | render | set | { data, options? } |
| Flutter → H5 | render | update | { data, options? } |
| Flutter → H5 | render | clear | {} |
| H5 → Flutter | render | ready | 应用能力信息 |
| H5 → Flutter | render | applied | 已执行操作信息 |
| H5 → Flutter | interaction | 业务动作 | { source_id, value?, ... } |
| H5 → Flutter | error | report | { source, code, message, details? } |
H5 通过 bindRenderProtocol() 接收渲染消息,通过 renderProtocol、interaction 和 bridgeError 上报事件:
import {
bindRenderProtocol,
bridgeError,
interaction,
renderProtocol,
} from '@h5-container/bridge-core-ts';
const unsubscribe = bindRenderProtocol({
set: ({ data }) => renderCompleteContent(data),
update: ({ data, options }) => updateContent(data, options),
clear: () => clearContent(),
});
await renderProtocol.ready({ supportedOrientations: ['portrait'] });
await interaction.send('submit', { source_id: 'choice-1', value: ['fast'] });
await bridgeError.report({
source: 'render',
code: 'INVALID_CONTENT',
message: 'Unsupported content type',
});payload.data 的结构由当前 H5 package 定义和校验,Container SDK 不理解具体业务类型。packageId 负责区分当前加载的 H5 应用。
底层协议
所有消息遵循统一信封。除上述标准内容协议外,底层 bridge.send() 和 bridge.on() 仍允许业务扩展自由字符串:
{
"type": "<自定义类别>",
"action": "onFindTarget",
"payload": { "target": "ladybug" },
"messageId": "optional-uuid",
"timestamp": 1708588800000
}新的内容型 H5 应优先使用标准内容协议;自由字符串只用于无法归入标准域的扩展能力。
