@anov/cic-standard-sdk 0.0.20 → 0.0.21

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.
@@ -2,6 +2,7 @@ import type { CICConfig, ComponentInstance } from '../types';
2
2
  import { CICInstance } from './CICInstance';
3
3
  import { createBareLoader, createDependencyLoader, getDependencyLoaderSingleton } from './depsLoader';
4
4
  import { Render } from './render';
5
+ import { createManifestLoader, resolveManifest } from './manifestLoader';
5
6
  export * from '../types';
6
7
  export type { Result as GeneratorResult } from './core';
7
8
  /**
@@ -55,4 +56,8 @@ export declare class CICSDK extends CICInstance {
55
56
  static getDependencyLoaderSingleton: typeof getDependencyLoaderSingleton;
56
57
  /** 渲染 */
57
58
  static Render: typeof Render;
59
+ /** 解析供需清单 */
60
+ static resolveManifest: typeof resolveManifest;
61
+ /** 创建 manifest 加载器 */
62
+ static createManifestLoader: typeof createManifestLoader;
58
63
  }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @file sdk/manifestLoader/index.ts
3
+ * @description Manifest 供需匹配核心实现
4
+ *
5
+ * ┌─────────────────────────────────────────────────────────────────────┐
6
+ * │ 职责 │
7
+ * │ 1. resolveManifest() —— 纯函数,供需匹配 + 合并,不依赖网络/DOM │
8
+ * │ 2. createManifestLoader() —— 工厂函数,远程加载 JSON 后调用 │
9
+ * │ resolveManifest,并将结果写入 globalThis │
10
+ * │ │
11
+ * │ 设计约束: │
12
+ * │ - resolveManifest 是纯函数,可在 Node.js / 浏览器 / 测试中运行 │
13
+ * │ - createManifestLoader 依赖 fetch API,仅面向浏览器环境 │
14
+ * │ - 两者均不依赖 DOM importMap 注入(由 manifest-loader.js 负责) │
15
+ * └─────────────────────────────────────────────────────────────────────┘
16
+ *
17
+ * 数据流:
18
+ * RuntimeManifest (JSON) ──┐
19
+ * ├─ resolveManifest() ──→ ResolvedManifest
20
+ * CICManifest (JSON) ──┘ │
21
+ * ▼
22
+ * window.__MANIFEST__
23
+ * window.__ENV__
24
+ * window.__manifestReady
25
+ */
26
+ import type { CICManifest } from '../../types/manifest/cic.manifest';
27
+ import type { LoaderOptions, ResolvedManifest, RuntimeManifest } from '../../types/manifest/runtime.manifest';
28
+ /**
29
+ * 供需匹配核心函数:将 RuntimeManifest(供给)与 CICManifest(需求)合并
30
+ *
31
+ * 输入:
32
+ * runtime —— 宿主供给表(RuntimeManifest),描述能提供什么
33
+ * cic —— 应用需求表(CICManifest),描述需要什么
34
+ *
35
+ * 输出:ResolvedManifest,包含:
36
+ * importMap —— 三方合并后的完整 importMap(可直接注入浏览器)
37
+ * env —— 合并后的环境变量(runtime.env 被 cic.env 覆盖)
38
+ * report —— 每条依赖的决策过程记录(可观测性)
39
+ *
40
+ * importMap 合并优先级(低 → 高):
41
+ * importsRuntime(runtime.importMap.imports)
42
+ * < importsGenerated(供需匹配生成:direct-esm URL + shimB data:URL)
43
+ * < importsAlias(alias 展开)
44
+ * < cic.modules.importMap.imports(应用显式声明,最高优先级)
45
+ *
46
+ * ⚠️ 纯函数,无副作用,无 DOM 操作,可在 Node.js / 测试环境安全调用。
47
+ * ⚠️ 此函数不负责 importMap 注入(由 manifest-loader.js 调用 injectImportMap 完成)。
48
+ */
49
+ export declare function resolveManifest(runtime: RuntimeManifest, cic: CICManifest): ResolvedManifest;
50
+ /**
51
+ * 创建 manifest loader 实例(面向浏览器环境)
52
+ *
53
+ * 职责:
54
+ * 1. 并行 fetch runtime.manifest.json 和 cic.manifest.json
55
+ * 2. 调用 resolveManifest 完成供需匹配
56
+ * 3. 将结果写入 globalThis 的三个全局变量
57
+ *
58
+ * 与 manifest-loader.js(浏览器脚本)的分工:
59
+ * manifest-loader.js —— 负责 importMap DOM 注入、modulepreload 插入、
60
+ * script 加载(shimB/globalTask)、import(entry)
61
+ * createManifestLoader —— 负责 JSON 加载和供需逻辑,不操作 DOM
62
+ *
63
+ * 使用示例:
64
+ * const loader = createManifestLoader({ runtimeUrl: '/runtime.manifest.json' })
65
+ * const resolved = await loader.load()
66
+ * console.log(resolved.report.entries)
67
+ *
68
+ * @param options LoaderOptions(所有字段可选,提供合理默认值)
69
+ */
70
+ export declare function createManifestLoader(options?: LoaderOptions): {
71
+ /**
72
+ * 加载并解析 manifest,写入全局状态
73
+ *
74
+ * 写入的全局变量:
75
+ * globalThis.__MANIFEST__ ResolvedManifest 完整结果
76
+ * globalThis.__ENV__ 合并后的环境变量(快捷访问)
77
+ * globalThis.__manifestReady 已 resolve 的 Promise(兼容 await 语法)
78
+ *
79
+ * 注意:此方法写入的 __manifestReady 是 Promise.resolve(resolved),
80
+ * 已经 resolve,不是 manifest-loader.js 中的 pending Promise。
81
+ * 两者在不同使用场景下使用,不要混淆。
82
+ *
83
+ * @throws 网络请求失败(HTTP 非 2xx)
84
+ * @throws resolveManifest 内部的版本/依赖校验错误
85
+ */
86
+ load(): Promise<ResolvedManifest>;
87
+ };
@@ -1,11 +1,73 @@
1
- import type { CICConfig, CICManifest, Adapter, CreateContextOptions } from '../../types';
1
+ /**
2
+ * @file sdk/render/index.ts
3
+ * @description Render 渲染协调器
4
+ *
5
+ * ┌─────────────────────────────────────────────────────────────────────┐
6
+ * │ 职责 │
7
+ * │ Render 是 ResolvedManifest 与 Adapter 之间的"协调层"。 │
8
+ * │ 它不关心框架细节,只负责按正确顺序调用 Adapter 生命周期。 │
9
+ * │ │
10
+ * │ 职责分工: │
11
+ * │ resolveManifest() —— 供需匹配,产出 ResolvedManifest │
12
+ * │ Render —— 消费 ResolvedManifest,驱动 Adapter 生命周期│
13
+ * │ Adapter —— 框架具体实现(Vue3/React 等) │
14
+ * └─────────────────────────────────────────────────────────────────────┘
15
+ *
16
+ * 生命周期调用顺序(render 方法内):
17
+ * supports() —— 校验适配器是否支持当前 manifest
18
+ * createContext() —— 创建贯穿生命周期的执行上下文
19
+ * prepare() —— 可选,预处理(框架实例初始化、异步资源准备)
20
+ * register() —— 必须,组件/插件注册
21
+ * mount() —— 可选,挂载到 DOM 容器
22
+ *
23
+ * 扩展能力(当前未封装,由调用方直接使用 adapter):
24
+ * update() —— 热更新 props/配置
25
+ * unmount() —— 卸载并清理
26
+ *
27
+ * 使用示例:
28
+ * const resolved = await window.__manifestReady
29
+ * const render = new Render(resolved, new Vue3Adapter())
30
+ * await render.render(document.getElementById('app'))
31
+ */
32
+ import type { Adapter, ResolvedManifest } from '../../types';
2
33
  export declare class Render {
3
- config: CICConfig;
4
- manifest: CICManifest;
34
+ /**
35
+ * 合并后的完整 manifest,包含供需匹配结果、importMap、env、report。
36
+ * Adapter 生命周期方法通过 AdapterContext.manifest 访问此对象。
37
+ */
38
+ manifest: ResolvedManifest;
39
+ /**
40
+ * 平台执行器实例。
41
+ * 使用无泛型参数的 Adapter(TContainer=unknown, TInstance=unknown),
42
+ * 允许接收任意平台的 Adapter 实现,由具体 Adapter 内部做类型断言。
43
+ *
44
+ * 若需要类型安全的泛型版本,可将 Render 改为泛型类:
45
+ * class Render<TContainer, TInstance> {
46
+ * adapter: Adapter<TContainer, TInstance>
47
+ * }
48
+ */
5
49
  adapter: Adapter;
6
- constructor(config: CICConfig, manifest: CICManifest, adapter: Adapter);
7
50
  /**
8
- * 渲染页面
51
+ * @param manifest 由 resolveManifest() 产出的合并结果
52
+ * @param adapter 目标平台的 Adapter 实现(如 Vue3Adapter)
53
+ */
54
+ constructor(manifest: ResolvedManifest, adapter: Adapter);
55
+ /**
56
+ * 执行完整的渲染装配流程
57
+ *
58
+ * 内部按顺序调用:supports → createContext → prepare? → register → mount?
59
+ *
60
+ * 错误处理策略(当前版本):
61
+ * - 任意阶段抛出错误,render() 直接向上传播,不做 onError 路由
62
+ * - 需要 onError 支持(abort/skip/retry)时,由调用方包裹 try/catch,
63
+ * 或扩展 Render 类,在各阶段调用 adapter.onError 决策后续行为
64
+ *
65
+ * @param container 挂载目标容器
66
+ * Web 场景:HTMLElement(如 document.getElementById('app'))
67
+ * 类型为 unknown,与 Adapter<TContainer=unknown> 保持一致
68
+ *
69
+ * @throws Error adapter.supports() 返回 false
70
+ * @throws Error adapter 生命周期方法内部抛出的任意错误
9
71
  */
10
- render(options: CreateContextOptions): Promise<void>;
72
+ render(container: unknown): Promise<void>;
11
73
  }
@@ -1,10 +1,8 @@
1
1
  import { CICEventMap } from './events';
2
2
  import { Data } from './data';
3
3
  import { JSFormat } from './deps';
4
- /** 通用表达式(用于条件、模板等) */
5
- export type Expr = string;
6
- /** 样式值可以是静态或表达式 */
7
- export type StyleValue = string | number | Expr;
4
+ /** 样式值 */
5
+ export type StyleValue = any;
8
6
  /** component 引用:字符串或 object 描述 */
9
7
  export type ComponentRef = string | {
10
8
  type: 'id';
@@ -1,6 +1,4 @@
1
1
  /** AUTO-GENERATED BY generate-types.ts — DO NOT EDIT MANUALLY */
2
- export * from './adapter';
3
- export * from './cic.manifest';
4
2
  export * from './cic';
5
3
  export * from './components';
6
4
  export * from './data';
@@ -10,5 +8,7 @@ export * from './events';
10
8
  export * from './meta';
11
9
  export * from './page';
12
10
  export * from './registry';
13
- export * from './runtime.manifest';
14
11
  export * from './variables';
12
+ export * from './manifest/adapter';
13
+ export * from './manifest/cic.manifest';
14
+ export * from './manifest/runtime.manifest';
@@ -0,0 +1,235 @@
1
+ /**
2
+ * @file adapter.ts
3
+ * @description Adapter 执行器接口类型定义
4
+ *
5
+ * ┌─────────────────────────────────────────────────────────────────────┐
6
+ * │ 职责定位 │
7
+ * │ Adapter 是"第三元":消费 ResolvedManifest,在目标平台执行装配。 │
8
+ * │ │
9
+ * │ 与 Loader 的职责分工: │
10
+ * │ Loader —— 供需匹配、importMap 注入、依赖加载、shim 生成 │
11
+ * │ Adapter —— 框架实例创建、组件/插件注册、DOM 挂载、生命周期管理 │
12
+ * │ │
13
+ * │ Adapter 不关心依赖从哪里来,只关心"已就绪的 ResolvedManifest" │
14
+ * │ 如何被转化成一个可运行的框架应用实例。 │
15
+ * └─────────────────────────────────────────────────────────────────────┘
16
+ *
17
+ * 生命周期顺序:
18
+ * supports? → createContext → prepare? → register → mount → update* → unmount
19
+ *
20
+ * 实现示例(Vue3):
21
+ * class Vue3Adapter implements Adapter<Element, App<Element>> { ... }
22
+ */
23
+ import type { ResolvedManifest } from './runtime.manifest';
24
+ /**
25
+ * Adapter 生命周期阶段枚举
26
+ * 传入 onError 钩子,用于区分错误发生的阶段
27
+ *
28
+ * prepare —— 预处理阶段(资源初始化、异步准备)
29
+ * register —— 注册阶段(组件/插件注册)
30
+ * mount —— 挂载阶段(框架实例挂载到 DOM)
31
+ * update —— 更新阶段(props/配置热更新)
32
+ * unmount —— 卸载阶段(实例销毁、资源清理)
33
+ */
34
+ export type AdapterPhase = 'prepare' | 'register' | 'mount' | 'update' | 'unmount';
35
+ /**
36
+ * 错误处置策略(onError 钩子的返回值)
37
+ *
38
+ * 'abort' —— 抛出错误,中止整个装配流程(默认值)
39
+ * 适用:注册必需插件失败、挂载失败等不可恢复错误
40
+ *
41
+ * 'skip' —— 跳过当前阶段,继续下一步
42
+ * 适用:prepare 阶段失败(非核心准备工作)、
43
+ * 非必需组件注册失败
44
+ *
45
+ * 'retry' —— 重试当前任务的网络加载(受 maxRetries 限制,默认 1 次)
46
+ * ⚠️ 重试粒度是单个任务的网络加载,不是整个生命周期阶段
47
+ * ⚠️ 禁止重试整个 register 阶段(防止 app.use 等副作用重复执行)
48
+ * 适用:临时网络抖动导致的资源加载失败
49
+ */
50
+ export type ErrorDisposition = 'abort' | 'skip' | 'retry';
51
+ /**
52
+ * register 阶段的执行结果报告
53
+ * 返回值结构化,便于上层(Loader 或测试)断言注册情况
54
+ */
55
+ export interface RegisterResult {
56
+ /** 成功注册的组件/插件名称列表 */
57
+ registered: string[];
58
+ /**
59
+ * 被跳过的组件/插件名称列表(required=false 且失败,或 conflictPolicy='replace')
60
+ * 跳过不代表错误,只是本次装配中未注册
61
+ */
62
+ skipped: string[];
63
+ /**
64
+ * 注册失败的条目列表
65
+ * name —— 组件/插件标识符
66
+ * reason —— 失败原因描述(错误消息或人类可读原因)
67
+ *
68
+ * 注意:required=true 的失败通常会在 register 阶段直接 throw,
69
+ * 不会进入此列表,除非 onError 返回 'skip'。
70
+ */
71
+ failed: Array<{
72
+ name: string;
73
+ reason: string;
74
+ }>;
75
+ }
76
+ /**
77
+ * 适配器执行上下文(贯穿整个生命周期的状态容器)
78
+ *
79
+ * 泛型参数:
80
+ * TContainer —— 挂载容器类型
81
+ * Web 平台:Element(HTMLElement / document.body)
82
+ * Electron:BrowserWindow 或自定义 host 对象
83
+ * 测试环境:DocumentFragment 或 mock 对象
84
+ *
85
+ * TInstance —— 框架应用实例类型
86
+ * Vue3:App<Element>(import('vue').App)
87
+ * Vue2:Vue 构造函数实例
88
+ * React:Root(ReactDOM.createRoot 返回值)
89
+ * 未初始化时为 undefined(prepare 阶段前)
90
+ *
91
+ * 生命周期中的状态变化:
92
+ * createContext → instance=undefined
93
+ * prepare → instance 可能被赋值(框架初始化)
94
+ * register → instance 完成插件注册(app.use / app.component)
95
+ * mount → instance 挂载到 container(app.mount(container))
96
+ * update → instance 响应 props 变化
97
+ * unmount → instance.unmount(),实例置为 undefined
98
+ */
99
+ export interface AdapterContext<TContainer = unknown, TInstance = unknown> {
100
+ /** 合并后的完整 manifest,提供所有配置信息 */
101
+ manifest: ResolvedManifest;
102
+ /**
103
+ * 目标挂载容器。
104
+ * Web 场景:document.getElementById('app') 返回的 Element
105
+ * Adapter 在 mount 阶段将框架实例挂载到此容器上。
106
+ */
107
+ container: TContainer;
108
+ /**
109
+ * 平台框架应用实例(可选,由 prepare/register 阶段赋值)。
110
+ * 类型参数 TInstance 可具体化为对应框架的实例类型,
111
+ * 避免在实现中进行不安全的类型断言。
112
+ */
113
+ instance?: TInstance;
114
+ }
115
+ /**
116
+ * 平台执行器接口:消费 ResolvedManifest,完成框架装配与挂载
117
+ *
118
+ * 泛型参数与 AdapterContext 一致:
119
+ * TContainer —— 挂载容器类型
120
+ * TInstance —— 框架应用实例类型
121
+ *
122
+ * 实现约定:
123
+ * 1. supports() 必须实现,用于多 Adapter 场景下的路由选择
124
+ * 2. createContext() 必须实现,是其他方法的前置条件
125
+ * 3. register() 必须实现,是注册组件的核心阶段
126
+ * 4. mount() 可选(某些场景由外部控制挂载时机)
127
+ * 5. prepare / update / unmount / onError 均可选
128
+ *
129
+ * 注册顺序(register 阶段内部):
130
+ * components.registry(静态,最先)
131
+ * → components.adapters(按 dependencies 拓扑排序后顺序执行)
132
+ * → conflictPolicy 处理同名冲突
133
+ */
134
+ export interface Adapter<TContainer = unknown, TInstance = unknown> {
135
+ /**
136
+ * 判断当前适配器是否支持目标 manifest
137
+ *
138
+ * 典型检查项:
139
+ * - manifest.runtime.engine.platform === 'web'
140
+ * - manifest.runtime.engine.runtime === 'vue3'
141
+ * - manifest.runtime.engine.version 满足适配器要求的最低版本
142
+ *
143
+ * 多 Adapter 场景下(如同时注册 Vue3Adapter / ReactAdapter),
144
+ * Loader 遍历 adapters 列表,选择第一个 supports() 返回 true 的 Adapter。
145
+ */
146
+ supports(manifest: ResolvedManifest): boolean;
147
+ /**
148
+ * 创建执行上下文
149
+ *
150
+ * 此阶段应只做轻量的同步初始化(分配内存、设置初始状态),
151
+ * 不发起网络请求,不创建框架实例(在 prepare 中进行)。
152
+ *
153
+ * 返回的 ctx 对象贯穿整个生命周期,所有阶段共享同一个引用。
154
+ */
155
+ createContext(manifest: ResolvedManifest, container: TContainer): AdapterContext<TContainer, TInstance>;
156
+ /**
157
+ * 预处理阶段(可选)
158
+ *
159
+ * 适用场景:
160
+ * - 创建框架应用实例(Vue: createApp / React: createRoot)
161
+ * - 异步加载非 external 的内部资源(主题、图标字体)
162
+ * - 建立与宿主环境的通信通道
163
+ *
164
+ * 失败处理:
165
+ * prepare 失败通常不致命,onError 可返回 'skip' 继续 register。
166
+ * 若框架实例创建失败,则应返回 'abort'(无法继续注册)。
167
+ */
168
+ prepare?(ctx: AdapterContext<TContainer, TInstance>): Promise<void>;
169
+ /**
170
+ * 注册阶段(必须实现)
171
+ *
172
+ * 核心职责:
173
+ * 1. 按 components.registry 静态注册表注册组件(优先级最高)
174
+ * 2. 按 components.adapters 列表(拓扑排序后)注册插件/组件
175
+ * 3. 处理同名冲突(按 components.conflictPolicy)
176
+ * 4. 返回 RegisterResult 报告注册情况
177
+ *
178
+ * 注意:
179
+ * - registry 与 adapters 同名冲突:registry 优先,记录 warning
180
+ * - required=true 的注册失败:应直接 throw(不进入 failed 列表)
181
+ * - required=false 的注册失败:进入 skipped 列表,继续执行
182
+ */
183
+ register(ctx: AdapterContext<TContainer, TInstance>): Promise<RegisterResult>;
184
+ /**
185
+ * 挂载阶段(可选,大多数场景需要实现)
186
+ *
187
+ * 将框架实例挂载到 ctx.container(Vue: app.mount(container))。
188
+ * 可选的原因:某些微前端场景由宿主统一控制挂载时机。
189
+ *
190
+ * 失败处理:mount 失败通常是致命的,onError 默认返回 'abort'。
191
+ */
192
+ mount?(ctx: AdapterContext<TContainer, TInstance>): Promise<void>;
193
+ /**
194
+ * 更新阶段(可选,热更新/动态配置场景使用)
195
+ *
196
+ * 适用场景:
197
+ * - 宿主下发新的运行配置(如切换主题、更新 locale)
198
+ * - 微前端框架调用子应用更新 props
199
+ *
200
+ * 实现建议:通过 provide/inject 或全局 store 传递 props,
201
+ * 避免销毁重建实例(开销大,破坏状态)。
202
+ */
203
+ update?(ctx: AdapterContext<TContainer, TInstance>, props: unknown): Promise<void>;
204
+ /**
205
+ * 卸载阶段(可选)
206
+ *
207
+ * 职责:
208
+ * - 调用框架实例的卸载方法(Vue: app.unmount())
209
+ * - 清理事件监听器、定时器等副作用
210
+ * - 将 ctx.instance 置为 undefined
211
+ *
212
+ * 微前端场景(子应用切换)必须实现此方法,防止内存泄漏。
213
+ */
214
+ unmount?(ctx: AdapterContext<TContainer, TInstance>): Promise<void>;
215
+ /**
216
+ * 错误处理钩子(可选)
217
+ *
218
+ * 在各生命周期阶段抛出错误时被调用,返回错误处置策略。
219
+ * 未实现时默认返回 'abort'(中止整个装配流程)。
220
+ *
221
+ * 推荐实现:
222
+ * onError(phase, err, ctx) {
223
+ * if (phase === 'prepare') return 'skip' // prepare 失败可跳过
224
+ * if (phase === 'update') return 'skip' // 热更新失败不影响运行
225
+ * return 'abort' // 其他阶段失败中止
226
+ * }
227
+ *
228
+ * retry 注意事项:
229
+ * - 重试粒度为单个任务的网络加载(script / import()),
230
+ * 不重试整个阶段(防止 app.use 等副作用重复执行)
231
+ * - 受 LoaderOptions.maxRetries 限制(默认 1 次)
232
+ * - 超过重试次数仍失败 → 降级为 'abort'
233
+ */
234
+ onError?(phase: AdapterPhase, err: Error, ctx: AdapterContext<TContainer, TInstance>): ErrorDisposition;
235
+ }