跳到主要内容

事件、类型与错误码

事件

WidgetEventName 共 8 个事件名,均可通过 api.on(name, listener) 订阅(返回退订函数),部分能力另有专用订阅入口(storage.onChangedtodos.onChangedchannel.subscribeonWidgetThemeChanged):

事件名载荷类型结构
channelMessageWidgetChannelMessageEvent{ message: WidgetJsonValue },结构化克隆副本
localeChangedWidgetLocaleChangedEvent{ locale: 'zh-CN' | 'en-US' }
sizeChangedWidgetSizeChangedEvent{ previousSize: WidgetTileSize; size: WidgetTileSize }
storageChangedWidgetStorageChangedEvent{ key: string; operation: 'set' | 'remove' },刻意不含 value
themeChangedWidgetThemeChangedEvent{ theme: 'light' | 'dark'; reducedMotion: boolean; tokens?: WidgetThemeTokens }
todoChangedWidgetTodoChangedEvent{ change: 'created' | 'updated' | 'deleted'; id: string }
variantChangedWidgetVariantChangedEvent{ previousVariantId?: string; variantId?: string }
visibilityChangedWidgetVisibilityChangedEvent{ visible: boolean },隐藏不销毁实例存储或会话

事件 DTO 携带 protocol/apiVersion/sessionId,SDK 校验后才会投递给 listener;不匹配的端口消息被静默忽略。

WidgetContext

interface WidgetContext {
componentId: string
instanceId: string
componentVersion: string
apiVersion: 1
surface: string
size: WidgetTileSize // {w:1,h:1} | {w:2,h:2} | {w:3,h:2} | {w:4,h:2}
variantId?: string
locale: 'zh-CN' | 'en-US'
theme: 'light' | 'dark'
reducedMotion: boolean
visible: boolean
permissions: WidgetPermissionSnapshot
}

interface WidgetPermissionSnapshot {
granted: readonly WidgetPermission[]
networkOrigins: readonly `https://${string}`[]
}

通过 api.context.get() 获取;每次返回副本,事件载荷即变化后的当前快照。

WidgetJsonValue

storage 与 channel 允许的唯一载荷形状——可跨 MessagePort 传递的纯 JSON:

type WidgetJsonValue =
| null
| boolean
| number
| string
| readonly WidgetJsonValue[]
| { readonly [key: string]: WidgetJsonValue }

WidgetThemeTokens

themeChanged 事件可携带的版本化主题 token 快照:

interface WidgetThemeTokens {
version: 1
values: Readonly<Record<WidgetThemeTokenName, string>>
}

WidgetThemeTokenName 是 20 个 --pt-* token 名称的联合类型,完整列表见 theme.css 与主题 token

权限类型

const WIDGET_TODO_PERMISSIONS = ['todos.read', 'todos.create', 'todos.update', 'todos.delete'] as const
const WIDGET_PERMISSIONS = WIDGET_TODO_PERMISSIONS // v1 全部可声明权限

type WidgetPermission = (typeof WIDGET_PERMISSIONS)[number]
type WidgetPermissionSet = readonly WidgetPermission[]

interface WidgetPermissionDeclarations {
required?: readonly WidgetPermission[]
optional?: readonly WidgetPermission[]
}

function validateWidgetPermissionDeclarations(
declarations: WidgetPermissionDeclarations | undefined,
): WidgetContractValidationResult

校验器拒绝:未知权限、同一列表内重复声明、同一权限同时出现在 requiredoptional。失败结果带 INVALID_ARGUMENT 错误与字段路径(如 permissions.required[0])。

错误码

宿主 API 失败时通过 WidgetApiError 返回稳定错误码(WidgetErrorCode,共 19 个):

错误码触发场景
API_INCOMPATIBLEManifest 的 apiVersion 与宿主 API 主版本不一致
CONCURRENCY_LIMIT并发请求超限(总并发 16 / 网络 4)
INSTANCE_DISABLED实例因连续故障被自动停用
INTEGRITY_FAILED完整性清单校验失败
INVALID_ARGUMENT参数未通过契约校验
INVALID_PACKAGE组件包不合法
INVALID_REQUESTRPC 消息形状/协议/会话不合法
MANIFEST_INVALIDManifest 未通过 Schema 校验
ORIGIN_NOT_ALLOWED网络来源未声明/未授权,或 URL 不合法
PERMISSION_DENIED权限未授予或已被撤销
QUOTA_EXCEEDED实例存储超 1 MiB 配额
RATE_LIMITED请求频率超限(10 秒 100 次)
RESPONSE_TOO_LARGE网络响应正文超 2 MiB
SAFE_MODE_ACTIVE宿主处于安全模式,第三方组件暂停运行
SIGNATURE_INVALID签名校验失败
SURFACE_LIMIT_REACHED同实例已有弹层,重复打开
SURFACE_NOT_DECLARED请求的 surface 未在 Manifest 声明
TIMEOUT宿主侧处理超时
UNKNOWN_METHOD未知 RPC 方法名

错误消息面向用户、不包含宿主内部细节;path 字段只指向公开 DTO 的出错字段。全部错误码也可从 WIDGET_ERROR_CODES 常量数组读取。

校验结果类型

SDK 的纯校验函数统一返回:

type WidgetContractValidationResult =
| { valid: true }
| { valid: false; error: WidgetApiError }

function createWidgetContractValidationSuccess(): WidgetContractValidationSuccess
function createWidgetContractValidationFailure(
code: WidgetErrorCode, message: string, path: string,
): WidgetContractValidationFailure