cdp-material-sdk 0.0.5
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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/DataScope-B7ffH5qN.js +106 -0
- package/dist/components/core/types.d.ts +16 -0
- package/dist/components/data-scope/DataScope.d.ts +45 -0
- package/dist/constants/event.d.ts +22 -0
- package/dist/context/DataContainerRuntimeContext.d.ts +16 -0
- package/dist/context/DataScopeContext.d.ts +51 -0
- package/dist/context/PageContext.d.ts +26 -0
- package/dist/hooks/useConcurrentLoading.d.ts +16 -0
- package/dist/hooks/useDataContainer.d.ts +61 -0
- package/dist/hooks/useDualLoading.d.ts +22 -0
- package/dist/host-react.d.ts +15 -0
- package/dist/host-react.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +42 -0
- package/dist/plugin.d.ts +45 -0
- package/dist/portable.d.ts +20 -0
- package/dist/portable.js +33 -0
- package/dist/protocol/adapter.d.ts +50 -0
- package/dist/protocol/common-schemas.d.ts +64 -0
- package/dist/protocol/events.d.ts +48 -0
- package/dist/protocol/manifest-types.d.ts +10 -0
- package/dist/protocol/manifest.d.ts +144 -0
- package/dist/protocol/traits.d.ts +7 -0
- package/dist/types/category.d.ts +15 -0
- package/dist/utils/mergeInitialValue.d.ts +10 -0
- package/dist/validateManifest-CYqjvQe_.js +355 -0
- package/dist/validation/validateManifest.d.ts +59 -0
- package/docs/component-development/FAQ.md +203 -0
- package/docs/component-development/README.md +176 -0
- package/docs/component-development/getting-started/01-/345/210/233/345/273/272/346/210/226/346/216/245/345/205/245/347/273/204/344/273/266/345/272/223/345/267/245/347/250/213.md +172 -0
- package/docs/component-development/getting-started/02-/345/210/233/345/273/272/347/273/204/344/273/266/345/214/205/345/271/266/346/263/250/345/206/214.md +185 -0
- package/docs/component-development/getting-started/03-/345/274/200/345/217/221/346/234/200/345/260/217/345/217/257/350/277/220/350/241/214/347/273/204/344/273/266.md +196 -0
- package/docs/component-development/getting-started/04-/346/236/204/345/273/272/345/217/221/345/270/203/344/270/216/345/256/277/344/270/273/346/216/245/345/205/245.md +147 -0
- package/docs/component-development/getting-started/05-/350/207/252/346/243/200/344/270/216/346/216/222/351/224/231.md +186 -0
- package/docs/component-development/recipes//344/275/277/347/224/250Adapter/351/200/202/351/205/215/347/273/204/344/273/266API.md +131 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/344/272/213/344/273/266.md +229 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/345/212/250/344/275/234/344/270/216/347/212/266/346/200/201.md +188 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/345/270/203/345/261/200/345/256/271/345/231/250/347/273/204/344/273/266.md +221 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/346/217/222/346/247/275.md +141 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/346/225/260/346/215/256/345/255/227/346/256/265/347/273/204/344/273/266.md +147 -0
- package/docs/component-development/recipes//345/243/260/346/230/216/346/225/260/346/215/256/345/256/271/345/231/250/347/273/204/344/273/266.md +258 -0
- package/docs/component-development/recipes//346/216/245/345/205/245/347/254/254/344/270/211/346/226/271React/347/273/204/344/273/266/345/272/223.md +209 -0
- package/docs/component-development/recipes//351/205/215/347/275/256DOM/346/240/271/350/212/202/347/202/271/346/263/250/345/205/245.md +222 -0
- package/docs/component-development/recipes//351/205/215/347/275/256Loading/347/255/226/347/225/245.md +198 -0
- package/docs/component-development/recipes//351/205/215/347/275/256/350/256/276/350/256/241/345/231/250/345/205/203/344/277/241/346/201/257.md +153 -0
- package/docs/component-development/reference/ActionsState/346/250/241/345/236/213.md +124 -0
- package/docs/component-development/reference/DOM/346/240/271/350/212/202/347/202/271/346/263/250/345/205/245/346/250/241/345/236/213.md +125 -0
- package/docs/component-development/reference/Events/346/250/241/345/236/213.md +170 -0
- package/docs/component-development/reference/Loading/347/255/226/347/225/245/346/250/241/345/236/213.md +140 -0
- package/docs/component-development/reference/Manifest/345/255/227/346/256/265/345/217/202/350/200/203.md +251 -0
- package/docs/component-development/reference/SDK/345/257/274/345/205/245/350/276/271/347/225/214.md +119 -0
- package/docs/component-development/reference/Slots/346/250/241/345/236/213.md +110 -0
- package/docs/component-development/reference/Traits/350/203/275/345/212/233/346/250/241/345/236/213.md +165 -0
- package/docs/component-development/reference/validateManifest/346/240/241/351/252/214/350/247/204/345/210/231.md +171 -0
- package/docs/component-development/reference//345/274/225/346/223/216/345/237/272/347/241/200/350/203/275/345/212/233/346/250/241/345/236/213.md +70 -0
- package/docs/component-development/reference//347/244/272/344/276/213/344/273/243/347/240/201/347/264/242/345/274/225.md +163 -0
- package/package.json +67 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: getting-started
|
|
3
|
+
capability: minimum-component
|
|
4
|
+
related:
|
|
5
|
+
- reference/Manifest字段参考.md
|
|
6
|
+
- reference/DOM根节点注入模型.md
|
|
7
|
+
- reference/validateManifest校验规则.md
|
|
8
|
+
- reference/示例代码索引.md
|
|
9
|
+
---
|
|
10
|
+
# 03 - 开发最小可运行组件
|
|
11
|
+
|
|
12
|
+
本文说明如何开发一个最小可被 CDP 宿主加载、渲染和识别的组件。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 适用场景
|
|
17
|
+
|
|
18
|
+
- 你要从零开发一个 CDP 组件。
|
|
19
|
+
- 你要往已有组件包里新增组件。
|
|
20
|
+
- 你要先跑通最小闭环,再按需添加事件、动作、状态、插槽或数据能力。
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 最小输出
|
|
25
|
+
|
|
26
|
+
一个最小组件通常包含:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
MyText/
|
|
30
|
+
├── index.tsx
|
|
31
|
+
└── manifest.ts
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 1. 编写 React 组件
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { forwardRef } from 'react';
|
|
40
|
+
import type { BaseUIProps } from 'cdp-material-sdk/portable';
|
|
41
|
+
|
|
42
|
+
export interface MyTextProps extends BaseUIProps<HTMLDivElement> {
|
|
43
|
+
text?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const MyText = forwardRef<HTMLDivElement, MyTextProps>((props, ref) => {
|
|
47
|
+
const { text = 'Hello CDP', slotProps } = props;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div {...slotProps?.root} ref={ref}>
|
|
51
|
+
{text}
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default MyText;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
关键要求:
|
|
60
|
+
|
|
61
|
+
- 使用 React 组件或 React wrapper。
|
|
62
|
+
- 推荐使用 `forwardRef`,后续可扩展 actions 和 state。
|
|
63
|
+
- 接收 `BaseUIProps`。
|
|
64
|
+
- 将 `slotProps.root` 透传到真实 DOM 根节点。
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 2. 编写 ComponentManifest
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import {
|
|
72
|
+
COMPONENT_CATEGORY,
|
|
73
|
+
INJECT_PATH_SLOT_PROPS,
|
|
74
|
+
type ComponentManifest,
|
|
75
|
+
} from 'cdp-material-sdk/portable';
|
|
76
|
+
|
|
77
|
+
export const myTextManifest = {
|
|
78
|
+
type: 'acme.MyText',
|
|
79
|
+
meta: {
|
|
80
|
+
title: '文本',
|
|
81
|
+
category: COMPONENT_CATEGORY.GENERAL,
|
|
82
|
+
description: '一个最小文本组件',
|
|
83
|
+
},
|
|
84
|
+
engine: {
|
|
85
|
+
render: {
|
|
86
|
+
injection: {
|
|
87
|
+
rootPath: INJECT_PATH_SLOT_PROPS,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
props: {
|
|
92
|
+
type: 'object',
|
|
93
|
+
properties: {
|
|
94
|
+
text: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
title: '文本内容',
|
|
97
|
+
default: 'Hello CDP',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
usage: {
|
|
102
|
+
tips: ['适合展示短文本'],
|
|
103
|
+
warnings: ['不建议用于长篇富文本'],
|
|
104
|
+
},
|
|
105
|
+
} satisfies ComponentManifest;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
最小必填项:
|
|
109
|
+
|
|
110
|
+
| 字段 | 说明 |
|
|
111
|
+
|------|------|
|
|
112
|
+
| `type` | 组件唯一标识 |
|
|
113
|
+
| `meta.title` | 组件显示名 |
|
|
114
|
+
| `meta.category` | 组件分类 |
|
|
115
|
+
|
|
116
|
+
推荐声明:
|
|
117
|
+
|
|
118
|
+
| 字段 | 说明 |
|
|
119
|
+
|------|------|
|
|
120
|
+
| `props` | 可配置属性的 JSON Schema |
|
|
121
|
+
| `engine.render.injection.rootPath` | 宿主根节点属性注入位置 |
|
|
122
|
+
| `usage.tips` / `usage.warnings` | 面向 AI 与设计器的使用提示,让组件从一开始就具备可读语义 |
|
|
123
|
+
| `meta.description` | 面向使用者的一句话说明 |
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 3. 加入组件包
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import type { EngineComponentPackage } from 'cdp-material-sdk/portable';
|
|
131
|
+
import { MyText } from './components/MyText';
|
|
132
|
+
import { myTextManifest } from './components/MyText/manifest';
|
|
133
|
+
|
|
134
|
+
export const myPackage: EngineComponentPackage = {
|
|
135
|
+
id: '@acme/cdp-components',
|
|
136
|
+
version: '1.0.0',
|
|
137
|
+
components: [
|
|
138
|
+
{
|
|
139
|
+
manifest: myTextManifest,
|
|
140
|
+
component: MyText,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 4. 按需添加能力
|
|
149
|
+
|
|
150
|
+
最小组件不需要声明所有能力。按需求选择:
|
|
151
|
+
|
|
152
|
+
| 需求 | 下一步 |
|
|
153
|
+
|------|--------|
|
|
154
|
+
| 参与表单值管理 | [声明数据字段组件](../recipes/声明数据字段组件.md) |
|
|
155
|
+
| 作为数据容器 | [声明数据容器组件](../recipes/声明数据容器组件.md) |
|
|
156
|
+
| 作为布局容器承载子组件 | [声明布局容器组件](../recipes/声明布局容器组件.md) |
|
|
157
|
+
| 触发事件 | [声明事件](../recipes/声明事件.md) |
|
|
158
|
+
| 暴露方法或状态 | [声明动作与状态](../recipes/声明动作与状态.md) |
|
|
159
|
+
| 提供可拖入区域 | [声明插槽](../recipes/声明插槽.md) |
|
|
160
|
+
| 调整设计器中的展示(图标、分组、隐藏) | [配置设计器元信息](../recipes/配置设计器元信息.md) |
|
|
161
|
+
| 接入第三方组件库 | [接入第三方 React 组件库](../recipes/接入第三方React组件库.md) |
|
|
162
|
+
| 配置 Loading | [配置 Loading 策略](../recipes/配置Loading策略.md) |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 自检
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { validateManifest, printValidationResult } from 'cdp-material-sdk/portable';
|
|
170
|
+
import { myTextManifest } from './components/MyText/manifest';
|
|
171
|
+
|
|
172
|
+
const result = validateManifest(myTextManifest);
|
|
173
|
+
printValidationResult(result);
|
|
174
|
+
|
|
175
|
+
if (!result.valid) {
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
完成标准:
|
|
181
|
+
|
|
182
|
+
- [ ] `validateManifest()` 没有 error。
|
|
183
|
+
- [ ] 组件能被加入 `EngineComponentPackage.components`。
|
|
184
|
+
- [ ] 组件根 DOM 能收到 `slotProps.root`。
|
|
185
|
+
- [ ] 没有直接依赖宿主内部模块。
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 关联文档
|
|
190
|
+
|
|
191
|
+
本文档只保留本层级职责内容:Recipe 提供任务步骤,Reference 提供稳定模型和规则,validateManifest 文档提供校验级别事实源。
|
|
192
|
+
|
|
193
|
+
- 字段参考:[Manifest字段参考](../reference/Manifest字段参考.md)
|
|
194
|
+
- 模型参考:[DOM根节点注入模型](../reference/DOM根节点注入模型.md)
|
|
195
|
+
- 校验规则:[validateManifest校验规则](../reference/validateManifest校验规则.md)
|
|
196
|
+
- 示例索引:[示例代码索引](../reference/示例代码索引.md)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: getting-started
|
|
3
|
+
capability: build-and-release
|
|
4
|
+
related:
|
|
5
|
+
- reference/SDK导入边界.md
|
|
6
|
+
- reference/validateManifest校验规则.md
|
|
7
|
+
---
|
|
8
|
+
# 04 - 构建发布与宿主接入
|
|
9
|
+
|
|
10
|
+
本文说明组件包如何构建成宿主可加载的 ESM 插件,以及交付时需要提供哪些信息。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 适用场景
|
|
15
|
+
|
|
16
|
+
- 你已经完成组件和 `EngineComponentPlugin`。
|
|
17
|
+
- 你要将组件包交付给 CDP 宿主加载。
|
|
18
|
+
- 你要确认 bundle 依赖处理是否正确。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 构建目标
|
|
23
|
+
|
|
24
|
+
宿主期望加载一个 ESM 模块。该模块应导出 `EngineComponentPlugin`,通常使用 default export:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import type { EngineComponentPlugin } from 'cdp-material-sdk/portable';
|
|
28
|
+
import { myPackage } from './package';
|
|
29
|
+
|
|
30
|
+
const plugin: EngineComponentPlugin = {
|
|
31
|
+
id: myPackage.id,
|
|
32
|
+
version: myPackage.version,
|
|
33
|
+
install: (api) => {
|
|
34
|
+
api.registerPackage(myPackage);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default plugin;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Vite 构建配置
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { defineConfig } from 'vite';
|
|
47
|
+
import react from '@vitejs/plugin-react';
|
|
48
|
+
import dts from 'vite-plugin-dts';
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
plugins: [react(), dts()],
|
|
52
|
+
build: {
|
|
53
|
+
lib: {
|
|
54
|
+
entry: 'src/plugin.ts',
|
|
55
|
+
formats: ['es'],
|
|
56
|
+
fileName: 'index',
|
|
57
|
+
},
|
|
58
|
+
rollupOptions: {
|
|
59
|
+
external: ['react', 'react/jsx-runtime', 'react-dom'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 依赖处理
|
|
68
|
+
|
|
69
|
+
| 依赖 | 推荐处理 |
|
|
70
|
+
|------|----------|
|
|
71
|
+
| `react` | `peerDependencies` + externalize,由宿主提供 |
|
|
72
|
+
| `react-dom` | `peerDependencies` + externalize,由宿主提供 |
|
|
73
|
+
| `react/jsx-runtime` | externalize |
|
|
74
|
+
| `cdp-material-sdk/portable` | 可作为普通依赖使用 |
|
|
75
|
+
| `cdp-material-sdk/host-react` | 仅当确认共享宿主 React Context 时使用 |
|
|
76
|
+
| UI 组件库 | 默认打入 bundle;如需共享,需与宿主协商 externalize |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 交付给宿主的信息
|
|
81
|
+
|
|
82
|
+
正式交付时,至少提供:
|
|
83
|
+
|
|
84
|
+
| 信息 | 示例 |
|
|
85
|
+
|------|------|
|
|
86
|
+
| 组件包 id | `@acme/cdp-components` |
|
|
87
|
+
| 版本 | `1.0.0` |
|
|
88
|
+
| ESM URL | `/packages/acme-cdp-components/index.js` |
|
|
89
|
+
| integrity | `sha384-...` |
|
|
90
|
+
| 组件清单 | `acme.MyText`、`acme.UserCard` |
|
|
91
|
+
| SDK 版本 | `cdp-material-sdk@0.0.4` |
|
|
92
|
+
|
|
93
|
+
后端下发字段由宿主侧契约决定,通常包含 `id`、`version`、`url`、`integrity`。
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Build Checklist
|
|
98
|
+
|
|
99
|
+
- [ ] `npm run build` 能成功输出 ESM。
|
|
100
|
+
- [ ] 入口文件默认导出 `EngineComponentPlugin`。
|
|
101
|
+
- [ ] `react`、`react-dom`、`react/jsx-runtime` 没有打进 bundle。
|
|
102
|
+
- [ ] `EngineComponentPlugin.id` 与 `EngineComponentPackage.id` 一致。
|
|
103
|
+
- [ ] `EngineComponentPlugin.version` 与 `EngineComponentPackage.version` 一致。
|
|
104
|
+
- [ ] 每个组件的 `manifest.type` 唯一且稳定。
|
|
105
|
+
- [ ] 每个 manifest 通过 `validateManifest()`。
|
|
106
|
+
- [ ] 如果使用 `host-react`,已确认外部 bundle 与宿主共享同一份 React runtime 和 Context 身份。
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 交付模式对比
|
|
111
|
+
|
|
112
|
+
| 模式 | 适用阶段 | 说明 |
|
|
113
|
+
|------|----------|------|
|
|
114
|
+
| 同源 URL 直载 | 联调、灰度、内部验证 | 宿主通过 URL 动态导入 ESM |
|
|
115
|
+
| 独立 npm / tgz 包 | 正式交付、版本管理 | 独立仓库构建后发布产物 |
|
|
116
|
+
| 文档内模板 | 快速复制、理解 authoring 方式 | 以本文和 [示例代码索引](../reference/示例代码索引.md) 为准 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 常见错误
|
|
121
|
+
|
|
122
|
+
### 把 React 打进 bundle
|
|
123
|
+
|
|
124
|
+
现象:组件渲染、Context 或 ref 行为异常。
|
|
125
|
+
|
|
126
|
+
处理:检查构建产物和 `rollupOptions.external`,确保 `react`、`react-dom`、`react/jsx-runtime` 被 externalize。
|
|
127
|
+
|
|
128
|
+
### 插件没有 default export
|
|
129
|
+
|
|
130
|
+
现象:宿主动态导入模块后无法解析插件。
|
|
131
|
+
|
|
132
|
+
处理:确保入口文件 `export default plugin`。
|
|
133
|
+
|
|
134
|
+
### 修改了已有组件 type
|
|
135
|
+
|
|
136
|
+
现象:旧页面或旧 DSL 找不到组件。
|
|
137
|
+
|
|
138
|
+
处理:`type` 是稳定协议。重命名应作为破坏性变更处理,并提供迁移方案。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 关联文档
|
|
143
|
+
|
|
144
|
+
本文档只保留本层级职责内容:Recipe 提供任务步骤,Reference 提供稳定模型和规则,validateManifest 文档提供校验级别事实源。
|
|
145
|
+
|
|
146
|
+
- SDK 导入边界:[SDK导入边界](../reference/SDK导入边界.md)
|
|
147
|
+
- 校验规则:[validateManifest校验规则](../reference/validateManifest校验规则.md)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: getting-started
|
|
3
|
+
capability: validation-and-troubleshooting
|
|
4
|
+
related:
|
|
5
|
+
- reference/validateManifest校验规则.md
|
|
6
|
+
- reference/Manifest字段参考.md
|
|
7
|
+
- FAQ.md
|
|
8
|
+
---
|
|
9
|
+
# 05 - 自检与排错
|
|
10
|
+
|
|
11
|
+
本文说明组件作者如何在交付前自检 manifest、组件 ref 契约、根节点注入和打包产物。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 适用场景
|
|
16
|
+
|
|
17
|
+
- 新增或修改组件后,需要确认契约是否正确。
|
|
18
|
+
- 组件已经接入宿主,但渲染、事件、动作或状态不生效。
|
|
19
|
+
- 构建后的组件包需要交付给宿主。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Manifest 静态校验
|
|
24
|
+
|
|
25
|
+
`cdp-material-sdk/portable` 提供纯函数校验工具:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import {
|
|
29
|
+
validateManifest,
|
|
30
|
+
printValidationResult,
|
|
31
|
+
} from 'cdp-material-sdk/portable';
|
|
32
|
+
import { myManifest } from './components/MyComponent/manifest';
|
|
33
|
+
|
|
34
|
+
const result = validateManifest(myManifest);
|
|
35
|
+
printValidationResult(result);
|
|
36
|
+
|
|
37
|
+
if (!result.valid) {
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
批量校验:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import {
|
|
46
|
+
validateManifests,
|
|
47
|
+
printValidationResult,
|
|
48
|
+
} from 'cdp-material-sdk/portable';
|
|
49
|
+
import { myPackage } from './package';
|
|
50
|
+
|
|
51
|
+
const result = validateManifests(
|
|
52
|
+
myPackage.components.map((item) => item.manifest),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
printValidationResult(result);
|
|
56
|
+
|
|
57
|
+
if (!result.valid) {
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
建议在组件包工程中提供脚本:
|
|
63
|
+
|
|
64
|
+
```jsonc
|
|
65
|
+
{
|
|
66
|
+
"scripts": {
|
|
67
|
+
"validate:manifest": "tsx scripts/validate-manifests.ts"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Actions / State 运行时诊断
|
|
75
|
+
|
|
76
|
+
如果组件声明了 `actions` 或 `state`,还需要确认 ref 实际暴露了对应能力。
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import {
|
|
80
|
+
COMPONENT_STATE_KEY,
|
|
81
|
+
diagnoseMissingActionImpls,
|
|
82
|
+
diagnoseMissingStateKeys,
|
|
83
|
+
} from 'cdp-material-sdk/portable';
|
|
84
|
+
|
|
85
|
+
const refValue = ref.current;
|
|
86
|
+
|
|
87
|
+
const missingActions = diagnoseMissingActionImpls(
|
|
88
|
+
Object.keys(myManifest.actions ?? {}),
|
|
89
|
+
refValue,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const missingStateKeys = diagnoseMissingStateKeys(
|
|
93
|
+
myManifest,
|
|
94
|
+
refValue?.[COMPONENT_STATE_KEY],
|
|
95
|
+
);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
如果 `missingActions` 或 `missingStateKeys` 非空,说明 manifest 声明和组件实现不一致。
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 3. rootPath 注入自检
|
|
103
|
+
|
|
104
|
+
检查组件根节点是否拿到宿主注入属性:
|
|
105
|
+
|
|
106
|
+
- `data-id`
|
|
107
|
+
- `data-path`
|
|
108
|
+
- `data-engine-hidden`
|
|
109
|
+
|
|
110
|
+
推荐写法:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<div {...slotProps?.root}>...</div>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
对应 manifest:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { INJECT_PATH_SLOT_PROPS } from 'cdp-material-sdk/portable';
|
|
120
|
+
|
|
121
|
+
engine: {
|
|
122
|
+
render: {
|
|
123
|
+
injection: {
|
|
124
|
+
rootPath: INJECT_PATH_SLOT_PROPS,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
如果你使用自定义 `rootPath`,请确认该路径上的 props 最终透传到了真实 DOM 根节点。
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 4. 打包自检
|
|
135
|
+
|
|
136
|
+
构建后检查:
|
|
137
|
+
|
|
138
|
+
- [ ] 产物是 ESM。
|
|
139
|
+
- [ ] `react`、`react-dom`、`react/jsx-runtime` 已 externalize。
|
|
140
|
+
- [ ] 入口模块能解析出 `EngineComponentPlugin`。
|
|
141
|
+
- [ ] `plugin.install(api)` 调用了 `api.registerPackage(pkg)`。
|
|
142
|
+
- [ ] `pkg.components` 包含所有对外组件。
|
|
143
|
+
- [ ] 没有从宿主源码路径或未公开的内部模块导入。
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 5. 常见现象与处理
|
|
148
|
+
|
|
149
|
+
| 现象 | 优先检查 |
|
|
150
|
+
|------|----------|
|
|
151
|
+
| 组件能渲染,但设计器无法选中 | `rootPath` 是否声明并透传到真实 DOM |
|
|
152
|
+
| Action 调用无效 | manifest `actions` 和 `useImperativeHandle` 暴露方法是否一致 |
|
|
153
|
+
| State 表达式读不到 | 是否使用 `COMPONENT_STATE_KEY` 暴露状态 |
|
|
154
|
+
| 自定义事件不触发 | `customEvents` 是否声明,`adapter.customEvents` 是否引用同一事件名 |
|
|
155
|
+
| Loading 不生效 | `engine.render.loading.strategy` 是否符合组件实际能力 |
|
|
156
|
+
| 表单值不更新 | 是否声明 `DATA_FIELD`,组件是否接收 `value` 并调用 `onChange` |
|
|
157
|
+
| 容器内字段写错位置 | 数据容器是否正确建立 DataScope,字段是否有 `name` |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 6. Error 与 Warning 的处理原则
|
|
162
|
+
|
|
163
|
+
| 级别 | 处理建议 |
|
|
164
|
+
|------|----------|
|
|
165
|
+
| error | 必须修复,否则不应交付 |
|
|
166
|
+
| warning | 需要确认是否符合预期;如果已按规则实现,可以记录并接受 |
|
|
167
|
+
|
|
168
|
+
例如自定义 `rootPath` 会提示作者确认 props 是否透传到根 DOM。若组件已经按规则实现,可忽略该提示。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 参考
|
|
173
|
+
|
|
174
|
+
- [validateManifest 校验规则](../reference/validateManifest校验规则.md)
|
|
175
|
+
- [DOM 根节点注入模型](../reference/DOM根节点注入模型.md)
|
|
176
|
+
- [Actions / State 模型](../reference/ActionsState模型.md)
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 关联文档
|
|
181
|
+
|
|
182
|
+
本文档只保留本层级职责内容:Recipe 提供任务步骤,Reference 提供稳定模型和规则,validateManifest 文档提供校验级别事实源。
|
|
183
|
+
|
|
184
|
+
- 校验规则:[validateManifest校验规则](../reference/validateManifest校验规则.md)
|
|
185
|
+
- 字段参考:[Manifest字段参考](../reference/Manifest字段参考.md)
|
|
186
|
+
- FAQ:[FAQ](../FAQ.md)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: recipe
|
|
3
|
+
capability: adapter
|
|
4
|
+
related:
|
|
5
|
+
- reference/Events模型.md
|
|
6
|
+
- reference/validateManifest校验规则.md
|
|
7
|
+
- recipes/接入第三方React组件库.md
|
|
8
|
+
---
|
|
9
|
+
# 使用 Adapter 适配组件 API
|
|
10
|
+
|
|
11
|
+
Adapter 用于把组件自身 API 映射到 CDP 约定。它适合接入第三方组件库或历史组件。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 适用场景
|
|
16
|
+
|
|
17
|
+
- 第三方组件的 prop 名与 CDP 默认名不同。
|
|
18
|
+
- 第三方组件的事件 prop 名不同。
|
|
19
|
+
- 需要对传入 props 做轻量转换。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 可以跳过的情况
|
|
24
|
+
|
|
25
|
+
- 你可以在 wrapper 内直接转换 API。
|
|
26
|
+
- 组件本身已经使用 `value`、`onChange`、`onClick` 等 CDP 约定。
|
|
27
|
+
- 适配逻辑复杂,需要在组件代码中处理。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## propMapping
|
|
32
|
+
|
|
33
|
+
将 CDP prop 名映射为组件实际 prop 名:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
adapter: {
|
|
37
|
+
propMapping: {
|
|
38
|
+
loading: 'spinning',
|
|
39
|
+
value: 'selectedValue',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
适合简单重命名。
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## events 映射
|
|
49
|
+
|
|
50
|
+
标准事件映射:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
events: {
|
|
54
|
+
click: { title: '点击' },
|
|
55
|
+
},
|
|
56
|
+
adapter: {
|
|
57
|
+
events: {
|
|
58
|
+
click: {
|
|
59
|
+
propName: 'onPress',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
自定义事件映射:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
customEvents: {
|
|
69
|
+
'acme:rowClick': {
|
|
70
|
+
title: '行点击',
|
|
71
|
+
payloadSchema: { type: 'object' },
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
adapter: {
|
|
75
|
+
customEvents: {
|
|
76
|
+
'acme:rowClick': {
|
|
77
|
+
propName: 'onRowClick',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## mapProps
|
|
86
|
+
|
|
87
|
+
当静态映射不够时,可以使用 `mapProps`:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
adapter: {
|
|
91
|
+
mapProps: (props) => ({
|
|
92
|
+
...props,
|
|
93
|
+
selectedValue: props.value,
|
|
94
|
+
onSelectedValueChange: props.onChange,
|
|
95
|
+
}),
|
|
96
|
+
},
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
注意:`mapProps` 是逃生舱。优先使用 wrapper 或 `propMapping`,避免把复杂逻辑藏在 manifest 中。
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 自检
|
|
104
|
+
|
|
105
|
+
- [ ] adapter 标准事件已经先在 `events` 声明。
|
|
106
|
+
- [ ] adapter 自定义事件已经先在 `customEvents` 声明。
|
|
107
|
+
- [ ] 每个 adapter event 都有 `propName`。
|
|
108
|
+
- [ ] `propMapping` 没有和 wrapper 内转换重复冲突。
|
|
109
|
+
- [ ] `validateManifest()` 没有 error。
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 常见错误
|
|
114
|
+
|
|
115
|
+
### Adapter 引用了未声明事件
|
|
116
|
+
|
|
117
|
+
先声明事件,再用 adapter 映射。否则 `validateManifest()` 会报错。
|
|
118
|
+
|
|
119
|
+
### 把复杂业务逻辑写进 mapProps
|
|
120
|
+
|
|
121
|
+
`mapProps` 只适合轻量适配。复杂逻辑应该写在 React wrapper 中。
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 关联文档
|
|
126
|
+
|
|
127
|
+
本文档只保留本层级职责内容:Recipe 提供任务步骤,Reference 提供稳定模型和规则,validateManifest 文档提供校验级别事实源。
|
|
128
|
+
|
|
129
|
+
- 模型参考:[Events模型](../reference/Events模型.md)
|
|
130
|
+
- 校验规则:[validateManifest校验规则](../reference/validateManifest校验规则.md)
|
|
131
|
+
- 任务 Recipe:[接入第三方React组件库](./接入第三方React组件库.md)
|