@zhama/a2ui-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -0
- package/dist/builders/index.cjs +496 -0
- package/dist/builders/index.cjs.map +1 -0
- package/dist/builders/index.d.cts +538 -0
- package/dist/builders/index.d.ts +538 -0
- package/dist/builders/index.js +445 -0
- package/dist/builders/index.js.map +1 -0
- package/dist/index.cjs +869 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +43 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +802 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.cjs +22 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +711 -0
- package/dist/types/index.d.ts +711 -0
- package/dist/types/index.js +15 -0
- package/dist/types/index.js.map +1 -0
- package/dist/validators/index.cjs +313 -0
- package/dist/validators/index.cjs.map +1 -0
- package/dist/validators/index.d.cts +68 -0
- package/dist/validators/index.d.ts +68 -0
- package/dist/validators/index.js +308 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types/messages.ts"],"names":[],"mappings":";AAiNO,SAAS,aAAa,OAAA,EAAqE;AAChG,EAAA,OAAO,eAAA,IAAmB,OAAA,IAAW,kBAAA,IAAsB,OAAA,IAAW,iBAAA,IAAqB,OAAA;AAC7F;AAKO,SAAS,aAAa,OAAA,EAAqE;AAChG,EAAA,OAAO,gBAAA,IAAoB,OAAA,IAAW,eAAA,IAAmB,OAAA,IAAW,iBAAA,IAAqB,OAAA;AAC3F;AAuFO,IAAM,mBAAA,GAAsB;AAK5B,IAAM,sBAAA,GAAyB;AAK/B,IAAM,kBAAA,GAAqB;AAK3B,IAAM,cAAA,GAAiB","file":"index.js","sourcesContent":["/**\n * A2UI Message Types\n *\n * 服务器到客户端的消息类型定义\n * Based on A2UI v0.9 specification\n */\n\nimport type { ComponentInstance } from './components';\n\n// ============================================================================\n// Theme\n// ============================================================================\n\n/**\n * A2UI 主题配置\n */\nexport interface Theme {\n /**\n * 主要字体\n */\n font?: string;\n /**\n * 主题色(十六进制格式,如 '#00BFFF')\n */\n primaryColor?: string;\n /**\n * 其他自定义样式\n */\n [key: string]: string | undefined;\n}\n\n// ============================================================================\n// v0.9 消息格式\n// ============================================================================\n\n/**\n * CreateSurface 消息 - 创建新的 UI Surface\n */\nexport interface CreateSurfaceMessage {\n createSurface: {\n /**\n * Surface 唯一标识符\n */\n surfaceId: string;\n /**\n * 组件目录 ID\n * @example \"https://a2ui.dev/specification/0.9/standard_catalog_definition.json\"\n */\n catalogId: string;\n };\n}\n\n/**\n * UpdateComponents 消息 - 更新 Surface 中的组件\n */\nexport interface UpdateComponentsMessage {\n updateComponents: {\n /**\n * Surface 唯一标识符\n */\n surfaceId: string;\n /**\n * 组件列表(扁平化,通过 ID 引用建立关系)\n */\n components: ComponentInstance[];\n };\n}\n\n/**\n * UpdateDataModel 消息 - 更新数据模型\n */\nexport interface UpdateDataModelMessage {\n updateDataModel: {\n /**\n * Surface 唯一标识符\n */\n surfaceId: string;\n /**\n * 数据路径(可选,默认为根路径)\n * @example \"/user/name\"\n */\n path?: string;\n /**\n * 操作类型\n */\n op?: 'add' | 'replace' | 'remove';\n /**\n * 数据值(add/replace 操作需要)\n */\n value?: unknown;\n };\n}\n\n/**\n * DeleteSurface 消息 - 删除 Surface\n */\nexport interface DeleteSurfaceMessage {\n deleteSurface: {\n /**\n * 要删除的 Surface ID\n */\n surfaceId: string;\n };\n}\n\n/**\n * v0.9 服务器到客户端消息\n */\nexport type ServerToClientMessageV09 =\n | CreateSurfaceMessage\n | UpdateComponentsMessage\n | UpdateDataModelMessage\n | DeleteSurfaceMessage;\n\n// ============================================================================\n// v0.8 消息格式(兼容性)\n// ============================================================================\n\n/**\n * BeginRendering 消息 (v0.8) - 开始渲染\n */\nexport interface BeginRenderingMessage {\n beginRendering: {\n /**\n * Surface ID\n */\n surfaceId: string;\n /**\n * 根组件 ID\n */\n root: string;\n /**\n * 样式配置\n */\n styles?: Theme;\n };\n}\n\n/**\n * SurfaceUpdate 消息 (v0.8) - 更新组件\n */\nexport interface SurfaceUpdateMessage {\n surfaceUpdate: {\n surfaceId: string;\n components: ComponentInstanceV08[];\n };\n}\n\n/**\n * v0.8 组件实例格式\n */\nexport interface ComponentInstanceV08 {\n id: string;\n weight?: number;\n component: Record<string, unknown>;\n}\n\n/**\n * DataModelUpdate 消息 (v0.8) - 更新数据模型\n */\nexport interface DataModelUpdateMessage {\n dataModelUpdate: {\n surfaceId: string;\n path?: string;\n contents: ValueMap[];\n };\n}\n\n/**\n * DeleteSurface 消息 (v0.8)\n */\nexport interface DeleteSurfaceMessageV08 {\n deleteSurface: {\n surfaceId: string;\n };\n}\n\n/**\n * v0.8 ValueMap 格式\n */\nexport interface ValueMap {\n key: string;\n valueString?: string;\n valueNumber?: number;\n valueBoolean?: boolean;\n valueMap?: ValueMap[];\n}\n\n/**\n * v0.8 服务器到客户端消息\n */\nexport type ServerToClientMessageV08 =\n | BeginRenderingMessage\n | SurfaceUpdateMessage\n | DataModelUpdateMessage\n | DeleteSurfaceMessageV08;\n\n// ============================================================================\n// 通用消息类型\n// ============================================================================\n\n/**\n * 服务器到客户端消息(支持 v0.8 和 v0.9)\n */\nexport type ServerToClientMessage = ServerToClientMessageV08 | ServerToClientMessageV09;\n\n/**\n * 判断是否为 v0.9 消息\n */\nexport function isV09Message(message: ServerToClientMessage): message is ServerToClientMessageV09 {\n return 'createSurface' in message || 'updateComponents' in message || 'updateDataModel' in message;\n}\n\n/**\n * 判断是否为 v0.8 消息\n */\nexport function isV08Message(message: ServerToClientMessage): message is ServerToClientMessageV08 {\n return 'beginRendering' in message || 'surfaceUpdate' in message || 'dataModelUpdate' in message;\n}\n\n// ============================================================================\n// 客户端到服务器消息\n// ============================================================================\n\n/**\n * 用户操作事件\n */\nexport interface UserActionEvent {\n /**\n * 操作名称\n */\n actionName: string;\n /**\n * 触发组件的 ID\n */\n sourceComponentId: string;\n /**\n * 时间戳(ISO 8601 格式)\n */\n timestamp: string;\n /**\n * 操作上下文(解析后的值)\n */\n context?: Record<string, unknown>;\n}\n\n/**\n * 数据变更事件\n */\nexport interface DataChangeEvent {\n /**\n * Surface ID\n */\n surfaceId: string;\n /**\n * 数据路径\n */\n path: string;\n /**\n * 新值\n */\n value: unknown;\n /**\n * 触发组件的 ID\n */\n sourceComponentId: string;\n}\n\n/**\n * 客户端到服务器消息\n */\nexport type ClientToServerMessage =\n | { userAction: UserActionEvent }\n | { dataChange: DataChangeEvent };\n\n// ============================================================================\n// 数据类型\n// ============================================================================\n\n/**\n * 数据模型值类型\n */\nexport type DataValue =\n | string\n | number\n | boolean\n | null\n | DataObject\n | DataArray;\n\n/**\n * 数据对象\n */\nexport interface DataObject {\n [key: string]: DataValue;\n}\n\n/**\n * 数据数组\n */\nexport type DataArray = DataValue[];\n\n/**\n * A2UI 标准 Catalog ID\n */\nexport const STANDARD_CATALOG_ID = 'https://a2ui.dev/specification/0.9/standard_catalog_definition.json';\n\n/**\n * A2UI 扩展 URI (v0.8)\n */\nexport const A2UI_EXTENSION_URI_V08 = 'https://a2ui.org/a2a-extension/a2ui/v0.8';\n\n/**\n * A2UI 扩展 URI (v0.9)\n */\nexport const A2UI_EXTENSION_URI = 'https://a2ui.dev/specification/0.9';\n\n/**\n * A2UI MIME 类型\n */\nexport const A2UI_MIME_TYPE = 'application/json+a2ui';\n\n"]}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/validators/message-validator.ts
|
|
4
|
+
var STANDARD_COMPONENT_TYPES = [
|
|
5
|
+
"Text",
|
|
6
|
+
"Image",
|
|
7
|
+
"Icon",
|
|
8
|
+
"Video",
|
|
9
|
+
"AudioPlayer",
|
|
10
|
+
"Row",
|
|
11
|
+
"Column",
|
|
12
|
+
"List",
|
|
13
|
+
"Card",
|
|
14
|
+
"Tabs",
|
|
15
|
+
"Divider",
|
|
16
|
+
"Modal",
|
|
17
|
+
"Button",
|
|
18
|
+
"CheckBox",
|
|
19
|
+
"TextField",
|
|
20
|
+
"DateTimeInput",
|
|
21
|
+
"ChoicePicker",
|
|
22
|
+
"Slider"
|
|
23
|
+
];
|
|
24
|
+
function validateV09Message(message, options = {}) {
|
|
25
|
+
const errors = [];
|
|
26
|
+
const warnings = [];
|
|
27
|
+
if ("createSurface" in message) {
|
|
28
|
+
const { createSurface } = message;
|
|
29
|
+
if (!createSurface.surfaceId) {
|
|
30
|
+
errors.push({
|
|
31
|
+
code: "MISSING_SURFACE_ID",
|
|
32
|
+
message: "createSurface.surfaceId is required",
|
|
33
|
+
path: "createSurface.surfaceId"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (!createSurface.catalogId) {
|
|
37
|
+
errors.push({
|
|
38
|
+
code: "MISSING_CATALOG_ID",
|
|
39
|
+
message: "createSurface.catalogId is required",
|
|
40
|
+
path: "createSurface.catalogId"
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
} else if ("updateComponents" in message) {
|
|
44
|
+
const { updateComponents } = message;
|
|
45
|
+
if (!updateComponents.surfaceId) {
|
|
46
|
+
errors.push({
|
|
47
|
+
code: "MISSING_SURFACE_ID",
|
|
48
|
+
message: "updateComponents.surfaceId is required",
|
|
49
|
+
path: "updateComponents.surfaceId"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (!updateComponents.components || !Array.isArray(updateComponents.components)) {
|
|
53
|
+
errors.push({
|
|
54
|
+
code: "INVALID_COMPONENTS",
|
|
55
|
+
message: "updateComponents.components must be an array",
|
|
56
|
+
path: "updateComponents.components"
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
validateComponentsV09(updateComponents.components, errors, warnings, options);
|
|
60
|
+
}
|
|
61
|
+
} else if ("updateDataModel" in message) {
|
|
62
|
+
const { updateDataModel } = message;
|
|
63
|
+
if (!updateDataModel.surfaceId) {
|
|
64
|
+
errors.push({
|
|
65
|
+
code: "MISSING_SURFACE_ID",
|
|
66
|
+
message: "updateDataModel.surfaceId is required",
|
|
67
|
+
path: "updateDataModel.surfaceId"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
} else if ("deleteSurface" in message) {
|
|
71
|
+
const { deleteSurface } = message;
|
|
72
|
+
if (!deleteSurface.surfaceId) {
|
|
73
|
+
errors.push({
|
|
74
|
+
code: "MISSING_SURFACE_ID",
|
|
75
|
+
message: "deleteSurface.surfaceId is required",
|
|
76
|
+
path: "deleteSurface.surfaceId"
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
errors.push({
|
|
81
|
+
code: "INVALID_MESSAGE_TYPE",
|
|
82
|
+
message: "Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
valid: errors.length === 0,
|
|
87
|
+
errors,
|
|
88
|
+
warnings
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function validateV08Message(message, options = {}) {
|
|
92
|
+
const errors = [];
|
|
93
|
+
const warnings = [];
|
|
94
|
+
if ("beginRendering" in message) {
|
|
95
|
+
const { beginRendering } = message;
|
|
96
|
+
if (!beginRendering.surfaceId) {
|
|
97
|
+
errors.push({
|
|
98
|
+
code: "MISSING_SURFACE_ID",
|
|
99
|
+
message: "beginRendering.surfaceId is required",
|
|
100
|
+
path: "beginRendering.surfaceId"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (!beginRendering.root) {
|
|
104
|
+
errors.push({
|
|
105
|
+
code: "MISSING_ROOT",
|
|
106
|
+
message: "beginRendering.root is required",
|
|
107
|
+
path: "beginRendering.root"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
} else if ("surfaceUpdate" in message) {
|
|
111
|
+
const { surfaceUpdate } = message;
|
|
112
|
+
if (!surfaceUpdate.surfaceId) {
|
|
113
|
+
errors.push({
|
|
114
|
+
code: "MISSING_SURFACE_ID",
|
|
115
|
+
message: "surfaceUpdate.surfaceId is required",
|
|
116
|
+
path: "surfaceUpdate.surfaceId"
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (!surfaceUpdate.components || !Array.isArray(surfaceUpdate.components)) {
|
|
120
|
+
errors.push({
|
|
121
|
+
code: "INVALID_COMPONENTS",
|
|
122
|
+
message: "surfaceUpdate.components must be an array",
|
|
123
|
+
path: "surfaceUpdate.components"
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
validateComponentsV08(surfaceUpdate.components, errors, warnings, options);
|
|
127
|
+
}
|
|
128
|
+
} else if ("dataModelUpdate" in message) {
|
|
129
|
+
const { dataModelUpdate } = message;
|
|
130
|
+
if (!dataModelUpdate.surfaceId) {
|
|
131
|
+
errors.push({
|
|
132
|
+
code: "MISSING_SURFACE_ID",
|
|
133
|
+
message: "dataModelUpdate.surfaceId is required",
|
|
134
|
+
path: "dataModelUpdate.surfaceId"
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (!dataModelUpdate.contents || !Array.isArray(dataModelUpdate.contents)) {
|
|
138
|
+
errors.push({
|
|
139
|
+
code: "INVALID_CONTENTS",
|
|
140
|
+
message: "dataModelUpdate.contents must be an array",
|
|
141
|
+
path: "dataModelUpdate.contents"
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
} else if ("deleteSurface" in message) {
|
|
145
|
+
const { deleteSurface } = message;
|
|
146
|
+
if (!deleteSurface.surfaceId) {
|
|
147
|
+
errors.push({
|
|
148
|
+
code: "MISSING_SURFACE_ID",
|
|
149
|
+
message: "deleteSurface.surfaceId is required",
|
|
150
|
+
path: "deleteSurface.surfaceId"
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
errors.push({
|
|
155
|
+
code: "INVALID_MESSAGE_TYPE",
|
|
156
|
+
message: "Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface"
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
valid: errors.length === 0,
|
|
161
|
+
errors,
|
|
162
|
+
warnings
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function validateMessage(message, options = {}) {
|
|
166
|
+
if ("createSurface" in message || "updateComponents" in message || "updateDataModel" in message) {
|
|
167
|
+
return validateV09Message(message, options);
|
|
168
|
+
}
|
|
169
|
+
if ("beginRendering" in message || "surfaceUpdate" in message || "dataModelUpdate" in message) {
|
|
170
|
+
return validateV08Message(message, options);
|
|
171
|
+
}
|
|
172
|
+
if ("deleteSurface" in message) {
|
|
173
|
+
if (!message.deleteSurface.surfaceId) {
|
|
174
|
+
return {
|
|
175
|
+
valid: false,
|
|
176
|
+
errors: [{
|
|
177
|
+
code: "MISSING_SURFACE_ID",
|
|
178
|
+
message: "deleteSurface.surfaceId is required",
|
|
179
|
+
path: "deleteSurface.surfaceId"
|
|
180
|
+
}],
|
|
181
|
+
warnings: []
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return { valid: true, errors: [], warnings: [] };
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
valid: false,
|
|
188
|
+
errors: [{
|
|
189
|
+
code: "UNKNOWN_MESSAGE_TYPE",
|
|
190
|
+
message: "Unknown message type"
|
|
191
|
+
}],
|
|
192
|
+
warnings: []
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function validateMessages(messages, options = {}) {
|
|
196
|
+
const errors = [];
|
|
197
|
+
const warnings = [];
|
|
198
|
+
for (let i = 0; i < messages.length; i++) {
|
|
199
|
+
const result = validateMessage(messages[i], options);
|
|
200
|
+
for (const error of result.errors) {
|
|
201
|
+
errors.push({
|
|
202
|
+
...error,
|
|
203
|
+
path: `messages[${i}].${error.path || ""}`
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
for (const warning of result.warnings) {
|
|
207
|
+
warnings.push({
|
|
208
|
+
...warning,
|
|
209
|
+
path: `messages[${i}].${warning.path || ""}`
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
valid: errors.length === 0,
|
|
215
|
+
errors,
|
|
216
|
+
warnings
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function validateComponentsV09(components, errors, warnings, options) {
|
|
220
|
+
const componentIds = /* @__PURE__ */ new Set();
|
|
221
|
+
let hasRoot = false;
|
|
222
|
+
for (let i = 0; i < components.length; i++) {
|
|
223
|
+
const comp = components[i];
|
|
224
|
+
const path = `updateComponents.components[${i}]`;
|
|
225
|
+
if (!comp.id) {
|
|
226
|
+
errors.push({
|
|
227
|
+
code: "MISSING_COMPONENT_ID",
|
|
228
|
+
message: "Component id is required",
|
|
229
|
+
path: `${path}.id`
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
if (componentIds.has(comp.id)) {
|
|
233
|
+
errors.push({
|
|
234
|
+
code: "DUPLICATE_COMPONENT_ID",
|
|
235
|
+
message: `Duplicate component id: ${comp.id}`,
|
|
236
|
+
path: `${path}.id`
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
componentIds.add(comp.id);
|
|
240
|
+
if (comp.id === "root") {
|
|
241
|
+
hasRoot = true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!comp.component) {
|
|
245
|
+
errors.push({
|
|
246
|
+
code: "MISSING_COMPONENT_TYPE",
|
|
247
|
+
message: "Component type is required",
|
|
248
|
+
path: `${path}.component`
|
|
249
|
+
});
|
|
250
|
+
} else if (options.strict && options.allowedComponents) {
|
|
251
|
+
if (!options.allowedComponents.includes(comp.component)) {
|
|
252
|
+
warnings.push({
|
|
253
|
+
code: "UNKNOWN_COMPONENT_TYPE",
|
|
254
|
+
message: `Unknown component type: ${comp.component}`,
|
|
255
|
+
path: `${path}.component`
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (!hasRoot && options.strict) {
|
|
261
|
+
warnings.push({
|
|
262
|
+
code: "MISSING_ROOT_COMPONENT",
|
|
263
|
+
message: 'No component with id "root" found',
|
|
264
|
+
path: "updateComponents.components"
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function validateComponentsV08(components, errors, warnings, options) {
|
|
269
|
+
const componentIds = /* @__PURE__ */ new Set();
|
|
270
|
+
for (let i = 0; i < components.length; i++) {
|
|
271
|
+
const comp = components[i];
|
|
272
|
+
const path = `surfaceUpdate.components[${i}]`;
|
|
273
|
+
if (!comp.id) {
|
|
274
|
+
errors.push({
|
|
275
|
+
code: "MISSING_COMPONENT_ID",
|
|
276
|
+
message: "Component id is required",
|
|
277
|
+
path: `${path}.id`
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
if (componentIds.has(comp.id)) {
|
|
281
|
+
errors.push({
|
|
282
|
+
code: "DUPLICATE_COMPONENT_ID",
|
|
283
|
+
message: `Duplicate component id: ${comp.id}`,
|
|
284
|
+
path: `${path}.id`
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
componentIds.add(comp.id);
|
|
288
|
+
}
|
|
289
|
+
if (!comp.component || typeof comp.component !== "object") {
|
|
290
|
+
errors.push({
|
|
291
|
+
code: "MISSING_COMPONENT",
|
|
292
|
+
message: "Component definition is required",
|
|
293
|
+
path: `${path}.component`
|
|
294
|
+
});
|
|
295
|
+
} else {
|
|
296
|
+
const componentType = Object.keys(comp.component)[0];
|
|
297
|
+
if (options.strict && !STANDARD_COMPONENT_TYPES.includes(componentType)) {
|
|
298
|
+
warnings.push({
|
|
299
|
+
code: "UNKNOWN_COMPONENT_TYPE",
|
|
300
|
+
message: `Unknown component type: ${componentType}`,
|
|
301
|
+
path: `${path}.component`
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
exports.validateMessage = validateMessage;
|
|
309
|
+
exports.validateMessages = validateMessages;
|
|
310
|
+
exports.validateV08Message = validateV08Message;
|
|
311
|
+
exports.validateV09Message = validateV09Message;
|
|
312
|
+
//# sourceMappingURL=index.cjs.map
|
|
313
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/validators/message-validator.ts"],"names":[],"mappings":";;;AA+DA,IAAM,wBAAA,GAA2B;AAAA,EAC/B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAKO,SAAS,kBAAA,CACd,OAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAClB,EAAA,MAAM,SAA4B,EAAC;AACnC,EAAA,MAAM,WAAgC,EAAC;AAEvC,EAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,IAAA,MAAM,EAAE,eAAc,GAAI,OAAA;AAC1B,IAAA,IAAI,CAAC,cAAc,SAAA,EAAW;AAC5B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,qCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,cAAc,SAAA,EAAW;AAC5B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,qCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAA,IAAW,sBAAsB,OAAA,EAAS;AACxC,IAAA,MAAM,EAAE,kBAAiB,GAAI,OAAA;AAC7B,IAAA,IAAI,CAAC,iBAAiB,SAAA,EAAW;AAC/B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,wCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,iBAAiB,UAAA,IAAc,CAAC,MAAM,OAAA,CAAQ,gBAAA,CAAiB,UAAU,CAAA,EAAG;AAC/E,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,8CAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH,CAAA,MAAO;AAEL,MAAA,qBAAA,CAAsB,gBAAA,CAAiB,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA;AAAA,IAC9E;AAAA,EACF,CAAA,MAAA,IAAW,qBAAqB,OAAA,EAAS;AACvC,IAAA,MAAM,EAAE,iBAAgB,GAAI,OAAA;AAC5B,IAAA,IAAI,CAAC,gBAAgB,SAAA,EAAW;AAC9B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,uCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAA,IAAW,mBAAmB,OAAA,EAAS;AACrC,IAAA,MAAM,EAAE,eAAc,GAAI,OAAA;AAC1B,IAAA,IAAI,CAAC,cAAc,SAAA,EAAW;AAC5B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,qCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAO;AACL,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,sBAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAO,MAAA,KAAW,CAAA;AAAA,IACzB,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAKO,SAAS,kBAAA,CACd,OAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAClB,EAAA,MAAM,SAA4B,EAAC;AACnC,EAAA,MAAM,WAAgC,EAAC;AAEvC,EAAA,IAAI,oBAAoB,OAAA,EAAS;AAC/B,IAAA,MAAM,EAAE,gBAAe,GAAI,OAAA;AAC3B,IAAA,IAAI,CAAC,eAAe,SAAA,EAAW;AAC7B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,sCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,eAAe,IAAA,EAAM;AACxB,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,EAAS,iCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAA,IAAW,mBAAmB,OAAA,EAAS;AACrC,IAAA,MAAM,EAAE,eAAc,GAAI,OAAA;AAC1B,IAAA,IAAI,CAAC,cAAc,SAAA,EAAW;AAC5B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,qCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,cAAc,UAAA,IAAc,CAAC,MAAM,OAAA,CAAQ,aAAA,CAAc,UAAU,CAAA,EAAG;AACzE,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,2CAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,qBAAA,CAAsB,aAAA,CAAc,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA;AAAA,IAC3E;AAAA,EACF,CAAA,MAAA,IAAW,qBAAqB,OAAA,EAAS;AACvC,IAAA,MAAM,EAAE,iBAAgB,GAAI,OAAA;AAC5B,IAAA,IAAI,CAAC,gBAAgB,SAAA,EAAW;AAC9B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,uCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,gBAAgB,QAAA,IAAY,CAAC,MAAM,OAAA,CAAQ,eAAA,CAAgB,QAAQ,CAAA,EAAG;AACzE,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,kBAAA;AAAA,QACN,OAAA,EAAS,2CAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAA,IAAW,mBAAmB,OAAA,EAAS;AACrC,IAAA,MAAM,EAAE,eAAc,GAAI,OAAA;AAC1B,IAAA,IAAI,CAAC,cAAc,SAAA,EAAW;AAC5B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,oBAAA;AAAA,QACN,OAAA,EAAS,qCAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAO;AACL,IAAA,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,sBAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAO,MAAA,KAAW,CAAA;AAAA,IACzB,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAKO,SAAS,eAAA,CACd,OAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAElB,EAAA,IAAI,eAAA,IAAmB,OAAA,IAAW,kBAAA,IAAsB,OAAA,IAAW,qBAAqB,OAAA,EAAS;AAC/F,IAAA,OAAO,kBAAA,CAAmB,SAAqC,OAAO,CAAA;AAAA,EACxE;AAEA,EAAA,IAAI,gBAAA,IAAoB,OAAA,IAAW,eAAA,IAAmB,OAAA,IAAW,qBAAqB,OAAA,EAAS;AAC7F,IAAA,OAAO,kBAAA,CAAmB,SAAqC,OAAO,CAAA;AAAA,EACxE;AAEA,EAAA,IAAI,mBAAmB,OAAA,EAAS;AAE9B,IAAA,IAAI,CAAC,OAAA,CAAQ,aAAA,CAAc,SAAA,EAAW;AACpC,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,KAAA;AAAA,QACP,QAAQ,CAAC;AAAA,UACP,IAAA,EAAM,oBAAA;AAAA,UACN,OAAA,EAAS,qCAAA;AAAA,UACT,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,QACD,UAAU;AAAC,OACb;AAAA,IACF;AACA,IAAA,OAAO,EAAE,OAAO,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AAAA,EACjD;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,KAAA;AAAA,IACP,QAAQ,CAAC;AAAA,MACP,IAAA,EAAM,sBAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,IACD,UAAU;AAAC,GACb;AACF;AAKO,SAAS,gBAAA,CACd,QAAA,EACA,OAAA,GAA6B,EAAC,EACZ;AAClB,EAAA,MAAM,SAA4B,EAAC;AACnC,EAAA,MAAM,WAAgC,EAAC;AAEvC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,QAAA,CAAS,CAAC,GAAG,OAAO,CAAA;AACnD,IAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,GAAG,KAAA;AAAA,QACH,MAAM,CAAA,SAAA,EAAY,CAAC,CAAA,EAAA,EAAK,KAAA,CAAM,QAAQ,EAAE,CAAA;AAAA,OACzC,CAAA;AAAA,IACH;AACA,IAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACrC,MAAA,QAAA,CAAS,IAAA,CAAK;AAAA,QACZ,GAAG,OAAA;AAAA,QACH,MAAM,CAAA,SAAA,EAAY,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,OAC3C,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAO,MAAA,KAAW,CAAA;AAAA,IACzB,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAMA,SAAS,qBAAA,CACP,UAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAY;AACrC,EAAA,IAAI,OAAA,GAAU,KAAA;AAEd,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,IAAA,GAAO,WAAW,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,+BAA+B,CAAC,CAAA,CAAA,CAAA;AAG7C,IAAA,IAAI,CAAC,KAAK,EAAA,EAAI;AACZ,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,sBAAA;AAAA,QACN,OAAA,EAAS,0BAAA;AAAA,QACT,IAAA,EAAM,GAAG,IAAI,CAAA,GAAA;AAAA,OACd,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAI,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AAC7B,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACV,IAAA,EAAM,wBAAA;AAAA,UACN,OAAA,EAAS,CAAA,wBAAA,EAA2B,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,UAC3C,IAAA,EAAM,GAAG,IAAI,CAAA,GAAA;AAAA,SACd,CAAA;AAAA,MACH;AACA,MAAA,YAAA,CAAa,GAAA,CAAI,KAAK,EAAE,CAAA;AAExB,MAAA,IAAI,IAAA,CAAK,OAAO,MAAA,EAAQ;AACtB,QAAA,OAAA,GAAU,IAAA;AAAA,MACZ;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,wBAAA;AAAA,QACN,OAAA,EAAS,4BAAA;AAAA,QACT,IAAA,EAAM,GAAG,IAAI,CAAA,UAAA;AAAA,OACd,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,iBAAA,EAAmB;AACtD,MAAA,IAAI,CAAC,OAAA,CAAQ,iBAAA,CAAkB,QAAA,CAAS,IAAA,CAAK,SAAS,CAAA,EAAG;AACvD,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA,EAAM,wBAAA;AAAA,UACN,OAAA,EAAS,CAAA,wBAAA,EAA2B,IAAA,CAAK,SAAS,CAAA,CAAA;AAAA,UAClD,IAAA,EAAM,GAAG,IAAI,CAAA,UAAA;AAAA,SACd,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,MAAA,EAAQ;AAC9B,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,IAAA,EAAM,wBAAA;AAAA,MACN,OAAA,EAAS,mCAAA;AAAA,MACT,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF;AAEA,SAAS,qBAAA,CACP,UAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAY;AAErC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,IAAA,GAAO,WAAW,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,4BAA4B,CAAC,CAAA,CAAA,CAAA;AAG1C,IAAA,IAAI,CAAC,KAAK,EAAA,EAAI;AACZ,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,sBAAA;AAAA,QACN,OAAA,EAAS,0BAAA;AAAA,QACT,IAAA,EAAM,GAAG,IAAI,CAAA,GAAA;AAAA,OACd,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAI,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AAC7B,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACV,IAAA,EAAM,wBAAA;AAAA,UACN,OAAA,EAAS,CAAA,wBAAA,EAA2B,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,UAC3C,IAAA,EAAM,GAAG,IAAI,CAAA,GAAA;AAAA,SACd,CAAA;AAAA,MACH;AACA,MAAA,YAAA,CAAa,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,IAC1B;AAGA,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,IAAa,OAAO,IAAA,CAAK,cAAc,QAAA,EAAU;AACzD,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,mBAAA;AAAA,QACN,OAAA,EAAS,kCAAA;AAAA,QACT,IAAA,EAAM,GAAG,IAAI,CAAA,UAAA;AAAA,OACd,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,MAAM,gBAAgB,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,SAAS,EAAE,CAAC,CAAA;AACnD,MAAA,IAAI,QAAQ,MAAA,IAAU,CAAC,wBAAA,CAAyB,QAAA,CAAS,aAAa,CAAA,EAAG;AACvE,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,IAAA,EAAM,wBAAA;AAAA,UACN,OAAA,EAAS,2BAA2B,aAAa,CAAA,CAAA;AAAA,UACjD,IAAA,EAAM,GAAG,IAAI,CAAA,UAAA;AAAA,SACd,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF","file":"index.cjs","sourcesContent":["/**\n * Message Validator\n *\n * 提供 A2UI 消息验证功能\n */\n\nimport type {\n ServerToClientMessage,\n ServerToClientMessageV08,\n ServerToClientMessageV09,\n ComponentInstance,\n ComponentInstanceV08,\n} from '../types';\n\n/**\n * 验证结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误信息列表 */\n errors: ValidationError[];\n /** 警告信息列表 */\n warnings: ValidationWarning[];\n}\n\n/**\n * 验证错误\n */\nexport interface ValidationError {\n /** 错误代码 */\n code: string;\n /** 错误消息 */\n message: string;\n /** 错误路径(如 'components[0].id') */\n path?: string;\n}\n\n/**\n * 验证警告\n */\nexport interface ValidationWarning {\n /** 警告代码 */\n code: string;\n /** 警告消息 */\n message: string;\n /** 警告路径 */\n path?: string;\n}\n\n/**\n * 验证选项\n */\nexport interface ValidationOptions {\n /** 是否严格模式(报告更多问题) */\n strict?: boolean;\n /** 允许的组件类型(为空表示允许所有) */\n allowedComponents?: string[];\n}\n\n/**\n * 标准组件类型列表\n */\nconst STANDARD_COMPONENT_TYPES = [\n 'Text',\n 'Image',\n 'Icon',\n 'Video',\n 'AudioPlayer',\n 'Row',\n 'Column',\n 'List',\n 'Card',\n 'Tabs',\n 'Divider',\n 'Modal',\n 'Button',\n 'CheckBox',\n 'TextField',\n 'DateTimeInput',\n 'ChoicePicker',\n 'Slider',\n];\n\n/**\n * 验证 v0.9 消息\n */\nexport function validateV09Message(\n message: ServerToClientMessageV09,\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n if ('createSurface' in message) {\n const { createSurface } = message;\n if (!createSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'createSurface.surfaceId is required',\n path: 'createSurface.surfaceId',\n });\n }\n if (!createSurface.catalogId) {\n errors.push({\n code: 'MISSING_CATALOG_ID',\n message: 'createSurface.catalogId is required',\n path: 'createSurface.catalogId',\n });\n }\n } else if ('updateComponents' in message) {\n const { updateComponents } = message;\n if (!updateComponents.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'updateComponents.surfaceId is required',\n path: 'updateComponents.surfaceId',\n });\n }\n if (!updateComponents.components || !Array.isArray(updateComponents.components)) {\n errors.push({\n code: 'INVALID_COMPONENTS',\n message: 'updateComponents.components must be an array',\n path: 'updateComponents.components',\n });\n } else {\n // 验证组件\n validateComponentsV09(updateComponents.components, errors, warnings, options);\n }\n } else if ('updateDataModel' in message) {\n const { updateDataModel } = message;\n if (!updateDataModel.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'updateDataModel.surfaceId is required',\n path: 'updateDataModel.surfaceId',\n });\n }\n } else if ('deleteSurface' in message) {\n const { deleteSurface } = message;\n if (!deleteSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n });\n }\n } else {\n errors.push({\n code: 'INVALID_MESSAGE_TYPE',\n message: 'Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * 验证 v0.8 消息\n */\nexport function validateV08Message(\n message: ServerToClientMessageV08,\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n if ('beginRendering' in message) {\n const { beginRendering } = message;\n if (!beginRendering.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'beginRendering.surfaceId is required',\n path: 'beginRendering.surfaceId',\n });\n }\n if (!beginRendering.root) {\n errors.push({\n code: 'MISSING_ROOT',\n message: 'beginRendering.root is required',\n path: 'beginRendering.root',\n });\n }\n } else if ('surfaceUpdate' in message) {\n const { surfaceUpdate } = message;\n if (!surfaceUpdate.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'surfaceUpdate.surfaceId is required',\n path: 'surfaceUpdate.surfaceId',\n });\n }\n if (!surfaceUpdate.components || !Array.isArray(surfaceUpdate.components)) {\n errors.push({\n code: 'INVALID_COMPONENTS',\n message: 'surfaceUpdate.components must be an array',\n path: 'surfaceUpdate.components',\n });\n } else {\n validateComponentsV08(surfaceUpdate.components, errors, warnings, options);\n }\n } else if ('dataModelUpdate' in message) {\n const { dataModelUpdate } = message;\n if (!dataModelUpdate.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'dataModelUpdate.surfaceId is required',\n path: 'dataModelUpdate.surfaceId',\n });\n }\n if (!dataModelUpdate.contents || !Array.isArray(dataModelUpdate.contents)) {\n errors.push({\n code: 'INVALID_CONTENTS',\n message: 'dataModelUpdate.contents must be an array',\n path: 'dataModelUpdate.contents',\n });\n }\n } else if ('deleteSurface' in message) {\n const { deleteSurface } = message;\n if (!deleteSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n });\n }\n } else {\n errors.push({\n code: 'INVALID_MESSAGE_TYPE',\n message: 'Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * 验证消息(自动检测版本)\n */\nexport function validateMessage(\n message: ServerToClientMessage,\n options: ValidationOptions = {}\n): ValidationResult {\n // 检测消息版本\n if ('createSurface' in message || 'updateComponents' in message || 'updateDataModel' in message) {\n return validateV09Message(message as ServerToClientMessageV09, options);\n }\n \n if ('beginRendering' in message || 'surfaceUpdate' in message || 'dataModelUpdate' in message) {\n return validateV08Message(message as ServerToClientMessageV08, options);\n }\n\n if ('deleteSurface' in message) {\n // deleteSurface 在两个版本中格式相同\n if (!message.deleteSurface.surfaceId) {\n return {\n valid: false,\n errors: [{\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n }],\n warnings: [],\n };\n }\n return { valid: true, errors: [], warnings: [] };\n }\n\n return {\n valid: false,\n errors: [{\n code: 'UNKNOWN_MESSAGE_TYPE',\n message: 'Unknown message type',\n }],\n warnings: [],\n };\n}\n\n/**\n * 验证消息数组\n */\nexport function validateMessages(\n messages: ServerToClientMessage[],\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const result = validateMessage(messages[i], options);\n for (const error of result.errors) {\n errors.push({\n ...error,\n path: `messages[${i}].${error.path || ''}`,\n });\n }\n for (const warning of result.warnings) {\n warnings.push({\n ...warning,\n path: `messages[${i}].${warning.path || ''}`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n// ============================================================================\n// 内部辅助函数\n// ============================================================================\n\nfunction validateComponentsV09(\n components: ComponentInstance[],\n errors: ValidationError[],\n warnings: ValidationWarning[],\n options: ValidationOptions\n): void {\n const componentIds = new Set<string>();\n let hasRoot = false;\n\n for (let i = 0; i < components.length; i++) {\n const comp = components[i];\n const path = `updateComponents.components[${i}]`;\n\n // 验证 ID\n if (!comp.id) {\n errors.push({\n code: 'MISSING_COMPONENT_ID',\n message: 'Component id is required',\n path: `${path}.id`,\n });\n } else {\n if (componentIds.has(comp.id)) {\n errors.push({\n code: 'DUPLICATE_COMPONENT_ID',\n message: `Duplicate component id: ${comp.id}`,\n path: `${path}.id`,\n });\n }\n componentIds.add(comp.id);\n\n if (comp.id === 'root') {\n hasRoot = true;\n }\n }\n\n // 验证组件类型\n if (!comp.component) {\n errors.push({\n code: 'MISSING_COMPONENT_TYPE',\n message: 'Component type is required',\n path: `${path}.component`,\n });\n } else if (options.strict && options.allowedComponents) {\n if (!options.allowedComponents.includes(comp.component)) {\n warnings.push({\n code: 'UNKNOWN_COMPONENT_TYPE',\n message: `Unknown component type: ${comp.component}`,\n path: `${path}.component`,\n });\n }\n }\n }\n\n // 检查是否有 root 组件\n if (!hasRoot && options.strict) {\n warnings.push({\n code: 'MISSING_ROOT_COMPONENT',\n message: 'No component with id \"root\" found',\n path: 'updateComponents.components',\n });\n }\n}\n\nfunction validateComponentsV08(\n components: ComponentInstanceV08[],\n errors: ValidationError[],\n warnings: ValidationWarning[],\n options: ValidationOptions\n): void {\n const componentIds = new Set<string>();\n\n for (let i = 0; i < components.length; i++) {\n const comp = components[i];\n const path = `surfaceUpdate.components[${i}]`;\n\n // 验证 ID\n if (!comp.id) {\n errors.push({\n code: 'MISSING_COMPONENT_ID',\n message: 'Component id is required',\n path: `${path}.id`,\n });\n } else {\n if (componentIds.has(comp.id)) {\n errors.push({\n code: 'DUPLICATE_COMPONENT_ID',\n message: `Duplicate component id: ${comp.id}`,\n path: `${path}.id`,\n });\n }\n componentIds.add(comp.id);\n }\n\n // 验证组件类型\n if (!comp.component || typeof comp.component !== 'object') {\n errors.push({\n code: 'MISSING_COMPONENT',\n message: 'Component definition is required',\n path: `${path}.component`,\n });\n } else {\n const componentType = Object.keys(comp.component)[0];\n if (options.strict && !STANDARD_COMPONENT_TYPES.includes(componentType)) {\n warnings.push({\n code: 'UNKNOWN_COMPONENT_TYPE',\n message: `Unknown component type: ${componentType}`,\n path: `${path}.component`,\n });\n }\n }\n }\n}\n\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ServerToClientMessageV09, ServerToClientMessageV08, ServerToClientMessage } from '../types/index.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Message Validator
|
|
5
|
+
*
|
|
6
|
+
* 提供 A2UI 消息验证功能
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 验证结果
|
|
11
|
+
*/
|
|
12
|
+
interface ValidationResult {
|
|
13
|
+
/** 是否有效 */
|
|
14
|
+
valid: boolean;
|
|
15
|
+
/** 错误信息列表 */
|
|
16
|
+
errors: ValidationError[];
|
|
17
|
+
/** 警告信息列表 */
|
|
18
|
+
warnings: ValidationWarning[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 验证错误
|
|
22
|
+
*/
|
|
23
|
+
interface ValidationError {
|
|
24
|
+
/** 错误代码 */
|
|
25
|
+
code: string;
|
|
26
|
+
/** 错误消息 */
|
|
27
|
+
message: string;
|
|
28
|
+
/** 错误路径(如 'components[0].id') */
|
|
29
|
+
path?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 验证警告
|
|
33
|
+
*/
|
|
34
|
+
interface ValidationWarning {
|
|
35
|
+
/** 警告代码 */
|
|
36
|
+
code: string;
|
|
37
|
+
/** 警告消息 */
|
|
38
|
+
message: string;
|
|
39
|
+
/** 警告路径 */
|
|
40
|
+
path?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 验证选项
|
|
44
|
+
*/
|
|
45
|
+
interface ValidationOptions {
|
|
46
|
+
/** 是否严格模式(报告更多问题) */
|
|
47
|
+
strict?: boolean;
|
|
48
|
+
/** 允许的组件类型(为空表示允许所有) */
|
|
49
|
+
allowedComponents?: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 验证 v0.9 消息
|
|
53
|
+
*/
|
|
54
|
+
declare function validateV09Message(message: ServerToClientMessageV09, options?: ValidationOptions): ValidationResult;
|
|
55
|
+
/**
|
|
56
|
+
* 验证 v0.8 消息
|
|
57
|
+
*/
|
|
58
|
+
declare function validateV08Message(message: ServerToClientMessageV08, options?: ValidationOptions): ValidationResult;
|
|
59
|
+
/**
|
|
60
|
+
* 验证消息(自动检测版本)
|
|
61
|
+
*/
|
|
62
|
+
declare function validateMessage(message: ServerToClientMessage, options?: ValidationOptions): ValidationResult;
|
|
63
|
+
/**
|
|
64
|
+
* 验证消息数组
|
|
65
|
+
*/
|
|
66
|
+
declare function validateMessages(messages: ServerToClientMessage[], options?: ValidationOptions): ValidationResult;
|
|
67
|
+
|
|
68
|
+
export { type ValidationError, type ValidationOptions, type ValidationResult, type ValidationWarning, validateMessage, validateMessages, validateV08Message, validateV09Message };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ServerToClientMessageV09, ServerToClientMessageV08, ServerToClientMessage } from '../types/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Message Validator
|
|
5
|
+
*
|
|
6
|
+
* 提供 A2UI 消息验证功能
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 验证结果
|
|
11
|
+
*/
|
|
12
|
+
interface ValidationResult {
|
|
13
|
+
/** 是否有效 */
|
|
14
|
+
valid: boolean;
|
|
15
|
+
/** 错误信息列表 */
|
|
16
|
+
errors: ValidationError[];
|
|
17
|
+
/** 警告信息列表 */
|
|
18
|
+
warnings: ValidationWarning[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 验证错误
|
|
22
|
+
*/
|
|
23
|
+
interface ValidationError {
|
|
24
|
+
/** 错误代码 */
|
|
25
|
+
code: string;
|
|
26
|
+
/** 错误消息 */
|
|
27
|
+
message: string;
|
|
28
|
+
/** 错误路径(如 'components[0].id') */
|
|
29
|
+
path?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 验证警告
|
|
33
|
+
*/
|
|
34
|
+
interface ValidationWarning {
|
|
35
|
+
/** 警告代码 */
|
|
36
|
+
code: string;
|
|
37
|
+
/** 警告消息 */
|
|
38
|
+
message: string;
|
|
39
|
+
/** 警告路径 */
|
|
40
|
+
path?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 验证选项
|
|
44
|
+
*/
|
|
45
|
+
interface ValidationOptions {
|
|
46
|
+
/** 是否严格模式(报告更多问题) */
|
|
47
|
+
strict?: boolean;
|
|
48
|
+
/** 允许的组件类型(为空表示允许所有) */
|
|
49
|
+
allowedComponents?: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 验证 v0.9 消息
|
|
53
|
+
*/
|
|
54
|
+
declare function validateV09Message(message: ServerToClientMessageV09, options?: ValidationOptions): ValidationResult;
|
|
55
|
+
/**
|
|
56
|
+
* 验证 v0.8 消息
|
|
57
|
+
*/
|
|
58
|
+
declare function validateV08Message(message: ServerToClientMessageV08, options?: ValidationOptions): ValidationResult;
|
|
59
|
+
/**
|
|
60
|
+
* 验证消息(自动检测版本)
|
|
61
|
+
*/
|
|
62
|
+
declare function validateMessage(message: ServerToClientMessage, options?: ValidationOptions): ValidationResult;
|
|
63
|
+
/**
|
|
64
|
+
* 验证消息数组
|
|
65
|
+
*/
|
|
66
|
+
declare function validateMessages(messages: ServerToClientMessage[], options?: ValidationOptions): ValidationResult;
|
|
67
|
+
|
|
68
|
+
export { type ValidationError, type ValidationOptions, type ValidationResult, type ValidationWarning, validateMessage, validateMessages, validateV08Message, validateV09Message };
|