webloom-framework 0.1.0 → 0.2.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/dist/react.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
- import { a0 as PluginHost, ac as PluginState, b as PluginGraph, d as PluginReverseDep, a6 as PluginIntentSubmissionResult, a as PluginManifest, aD as ResourceStoreApi, aB as ResourceSnapshot } from './createPluginHost-CcW9sPNs.js';
4
+ import { s as PluginHost, aj as PluginState, a as PluginGraph, c as PluginReverseDep, ag as PluginIntentSubmissionResult, P as PluginManifest, aF as ResourceStoreApi, aD as ResourceSnapshot } from './createPluginHost-ChJNBTsX.js';
5
5
 
6
6
  declare const PluginHostContext: react.Context<PluginHost | undefined>;
7
7
  interface PluginHostProviderProps {
@@ -1,4 +1,4 @@
1
- import { aa as PluginSetup, aG as RuntimeUnitImplementationRegistry, M as MessageBus, y as LifecycleScopeKind, e as LifecycleScopeIdentity, L as LifecycleScope, v as LifecycleDisposeResult, a5 as PluginIntentSnapshot, a3 as PluginIntentController, au as RemoteServiceTransport, al as RemoteServiceBridge, as as RemoteServiceReference, an as RemoteServiceCallContext, i as RemoteServiceMessageCodec, aA as ResourceRegistry, ay as ResourceDefinition } from './createPluginHost-CcW9sPNs.js';
1
+ import { i as PluginSetup, aL as RuntimeUnitImplementationRegistry, M as MessageBus, W as LifecycleScopeKind, u as LifecycleScopeIdentity, t as LifecycleScope, L as LifecycleDisposeResult, af as PluginIntentSnapshot, ad as PluginIntentController, aw as RemoteServiceTransport, q as RemoteServiceBridge, n as RemoteServiceReference, ar as RemoteServiceCallContext, o as RemoteServiceMessageCodec, aC as ResourceRegistry, aA as ResourceDefinition } from './createPluginHost-ChJNBTsX.js';
2
2
 
3
3
  interface RuntimeUnitImplementation {
4
4
  /** 产品标识。 */
package/dist/testing.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { an as RemoteServiceCallContext, o as CreatePluginHostOptions, a0 as PluginHost, au as RemoteServiceTransport } from './createPluginHost-CcW9sPNs.js';
2
- export { j as CapabilityRegistry, k as ContextExtensionInput, l as ContributionAdapter, m as ContributionAdapterInput, n as ContributionHandle, T as PermissionPolicyInput, V as PermissionPolicyResult, Y as PluginConfigStore, aH as RuntimeUnitSnapshot, aJ as ScopeResolution, aK as ScopeResolver, aL as ScopeResolverInput, aO as StartupCapabilityError, aQ as StartupPluginError, a_ as createCapabilityRegistry, a$ as createInMemoryPluginConfigStore, b0 as createPluginHost, b2 as createResourceStore } from './createPluginHost-CcW9sPNs.js';
3
- export { C as CreateMessagePortServiceTransportOptions, a as CreatePluginIntentControllerOptions, b as CreateResourceScopeOptions, c as CreateServiceBridgeOptions, R as RemoteServicePortCallMessage, d as RemoteServicePortCancelMessage, e as RemoteServicePortErrorMessage, f as RemoteServicePortResponseMessage, g as RemoteServicePortResultMessage, h as ResourceScopeOptions, i as RuntimeUnitImplementation, j as createLifecycleScope, k as createMessageBus, l as createMessagePortServiceTransport, m as createPluginIntentController, n as createRemoteServiceBridge, o as createResourceRegistry, p as createResourceScope, q as createRuntimeUnitImplementationRegistry, r as createServiceBridge } from './resourceRegistry-BAnqKcp7.js';
1
+ import { ar as RemoteServiceCallContext, C as CreatePluginHostOptions, s as PluginHost, aw as RemoteServiceTransport } from './createPluginHost-ChJNBTsX.js';
2
+ export { z as CapabilityRegistry, A as ContextExtensionInput, B as ContributionAdapter, D as ContributionAdapterInput, E as ContributionHandle, a6 as PermissionPolicyInput, a7 as PermissionPolicyResult, a9 as PluginConfigStore, aG as RuntimeUnitAttributesInput, aH as RuntimeUnitAvailabilityInput, aM as RuntimeUnitParentScopeInput, aN as RuntimeUnitSnapshot, aR as StartupCapabilityError, aT as StartupPluginError, b1 as createCapabilityRegistry, b2 as createInMemoryPluginConfigStore, b3 as createPluginHost, b5 as createResourceStore } from './createPluginHost-ChJNBTsX.js';
3
+ export { C as CreateMessagePortServiceTransportOptions, a as CreatePluginIntentControllerOptions, b as CreateResourceScopeOptions, c as CreateServiceBridgeOptions, R as RemoteServicePortCallMessage, d as RemoteServicePortCancelMessage, e as RemoteServicePortErrorMessage, f as RemoteServicePortResponseMessage, g as RemoteServicePortResultMessage, h as ResourceScopeOptions, i as RuntimeUnitImplementation, j as createLifecycleScope, k as createMessageBus, l as createMessagePortServiceTransport, m as createPluginIntentController, n as createRemoteServiceBridge, o as createResourceRegistry, p as createResourceScope, q as createRuntimeUnitImplementationRegistry, r as createServiceBridge } from './resourceRegistry-MNM1c7od.js';
4
4
 
5
5
  interface FakeTransportCall {
6
6
  /** 调用请求体。 */
package/dist/testing.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createPluginHost } from './chunk-KGNF36DZ.js';
2
- export { StartupCapabilityError, StartupPluginError, createCapabilityRegistry, createInMemoryPluginConfigStore, createLifecycleScope, createMessageBus, createMessagePortServiceTransport, createPluginHost, createPluginIntentController, createRemoteServiceBridge, createResourceRegistry, createResourceScope, createResourceStore, createRuntimeUnitImplementationRegistry, createServiceBridge } from './chunk-KGNF36DZ.js';
1
+ import { createPluginHost } from './chunk-URY3E6UH.js';
2
+ export { StartupCapabilityError, StartupPluginError, createCapabilityRegistry, createInMemoryPluginConfigStore, createLifecycleScope, createMessageBus, createMessagePortServiceTransport, createPluginHost, createPluginIntentController, createRemoteServiceBridge, createResourceRegistry, createResourceScope, createResourceStore, createRuntimeUnitImplementationRegistry, createServiceBridge } from './chunk-URY3E6UH.js';
3
3
 
4
4
  // src/testing/fakes.ts
5
5
  function createFakeRemoteServiceTransport(options = {}) {
package/docs/api.md CHANGED
@@ -1,29 +1,171 @@
1
1
  # WebLoom API 说明
2
2
 
3
- ## 依赖和运行单元
3
+ ## 浏览器 Runtime
4
4
 
5
- `PluginManifest` 描述一个产品,`RuntimeUnitDescriptor` 描述该产品在某个 `execution` 环境中的运行单元。`pluginId` 是产品级稳定身份,`unitId` 是单元级稳定身份,`instanceId` 是每次启动新生成的实例身份。运行单元依赖必须同时声明 `capability`、`contractVersion`、`sourceExecution` `scope`,Host 不根据 capability 名猜测远端服务。可执行 setup 必须由宿主的 `runtimeUnitImplementationRegistry` 按 `pluginId + unitId` 提供,静态清单不携带函数。
5
+ WebLoom v1 只支持两个真实 JavaScript realm:`window-main` 和
6
+ `shared-worker`。`runtime` 是受限的 `RuntimeKind`,不是可自由填写的环境标签;
7
+ 不支持的 runtime 在装配边界 fail closed。v1 不实现 Server、Service Worker 或
8
+ 其它服务端 PluginHost。
6
9
 
7
- `meta.defaultEnabled` 是初始启用意图,`PluginState.kind` 是实际运行状态。两者必须分开读取:依赖缺失时可以得到 `blocked`,同时保留 `desiredEnabled: true`。
10
+ 一次 Runtime 启动会生成不可复用的 `runtimeInstanceId`。每个插件运行单元启动
11
+ 会生成不可复用的 `unitInstanceId`(在 Host 的兼容状态接口中表现为
12
+ `instanceId`)。同一 SharedWorker 接收多个 Window 连接时,Worker 单元仍只有
13
+ 一个实例;每条端口连接拥有独立的 `connectionId`、请求和取消空间。
8
14
 
9
- ## Context 和 Scope
15
+ ## 普通插件 API
10
16
 
11
- `PluginContext` 的基础字段只包含插件身份、实例身份、Scope、取消信号、权限租约、MessageBus、配置和 capability 访问。产品服务通过 `contextExtension` 注入,扩展属性按只读对象处理。
17
+ ```ts
18
+ import { createWindowApp, definePlugin } from "webloom-framework";
12
19
 
13
- `LifecycleScope.revoke()` 是同步安全边界:它先阻止新资源、撤销权限租约并触发 `AbortSignal`;`dispose()` 再等待清理。清理失败和超时通过 `LifecycleDisposeResult` 暴露,不能被包装成成功。异步创建在撤权后才返回时,资源会立即释放且不会进入旧实例。
20
+ const hello = definePlugin({
21
+ id: "hello",
22
+ provides: ["hello.service"],
23
+ setup(ctx) {
24
+ ctx.provide("hello.service", { value: "world" });
25
+ ctx.onDispose(() => {
26
+ // 释放本插件登记的资源。
27
+ });
28
+ },
29
+ });
14
30
 
15
- ## 权限
31
+ const app = await createWindowApp({ plugins: [hello] });
32
+ const service = app.capability<{ value: string }>("hello.service");
33
+ ```
16
34
 
17
- 权限租约把插件申请、可信批准和会话约束求交集。`permissions` 只是 Context 视图,最终远端调用或持久化写入仍需使用 `verifyPermissionLease()` `assertBinding()` fail-closed 检查。`attributes` 参与租约身份比较,但不作为任意数据仓库。
35
+ `definePlugin()` 将静态 `manifest/descriptor` 与当前 realm `setup` 分开保存。
36
+ 静态 descriptor 可用于验证和快照,不携带函数。`createWindowApp()` 自动固定
37
+ `window-main`、生成实例身份、创建内部 Implementation Registry、批量注册并
38
+ 等待初始启动;使用者不需要手工 `register()`。
18
39
 
19
- ## 服务桥和 wire codec
40
+ `createWindowApp()` Promise 只有在必需插件成功后才成功。失败会抛出包含
41
+ `pluginId`、`unitId` 和 `phase` 的 `RuntimeInitializationError`。非必需插件的
42
+ 失败保留在 Runtime 快照中,不会被伪装为 running。
43
+
44
+ ## SharedWorker
45
+
46
+ Worker 入口:
47
+
48
+ ```ts
49
+ import { definePlugin, startSharedWorkerApp } from "webloom-framework";
50
+
51
+ const storage = definePlugin({
52
+ id: "storage",
53
+ provides: ["storage.service"],
54
+ setup(ctx) {
55
+ ctx.provide("storage.service", {
56
+ handle(request: { key: string }) {
57
+ return { key: request.key };
58
+ },
59
+ });
60
+ },
61
+ });
62
+
63
+ startSharedWorkerApp({ id: "coordinator", plugins: [storage] });
64
+ ```
65
+
66
+ Window 入口:
67
+
68
+ ```ts
69
+ // Vite emits a hashed JavaScript SharedWorker asset from this importer.
70
+ import coordinatorWorkerUrl from "./coordinator.worker.ts?sharedworker&url";
71
+ import { connectSharedWorker } from "webloom-framework";
72
+
73
+ const runtime = await connectSharedWorker({
74
+ id: "coordinator",
75
+ url: coordinatorWorkerUrl,
76
+ });
77
+
78
+ const storage = runtime.capability("storage.service");
79
+ await storage.call({ key: "hello" });
80
+ ```
81
+
82
+ 连接入口必须创建真实的 `new SharedWorker(url, { type: "module" })`。握手成功
83
+ 后必须先收到完整 baseline;后续快照 revision 必须连续。断线、revision gap、
84
+ Worker 重启或 Provider 实例变化都会同步撤销旧代理。重连只建立新连接和新代理,
85
+ 不会重放可能产生外部副作用的调用,也不会静默替换旧代理的绑定。
86
+
87
+ 这里的 `url` 必须是 Bundler 产出的 JavaScript Worker URL。Vite 使用
88
+ `?sharedworker&url` 或等价的独立 Rollup entry;不要把
89
+ `new URL("./coordinator.worker.ts", import.meta.url)` 作为普通参数传入框架,
90
+ 因为框架内部的 `new SharedWorker()` 不会让 Vite 重新发现调用方源码入口。
20
91
 
21
- `createServiceBridge()` 只接受同一连接、权威身份、连续快照和精确契约版本。旧 revision、revision gap、Provider 实例重建和断线都会使旧代理永久失效。传输层每次调用生成独立 `callId`;业务 `operationId` 可以重用,两者不混淆。
92
+ `RuntimeHandle` 提供:
22
93
 
23
- `createRemoteServiceMessageCodec()` 默认生成 `webloom.remote-service.*` 消息名。产品迁移旧协议时可以传入旧前缀,编码、解码和版本仍由 codec 集中负责。
94
+ | 成员 | 语义 |
95
+ | --- | --- |
96
+ | `runtimeId` | Worker 的逻辑标识 |
97
+ | `runtimeInstanceId` | 当前 Worker 物理启动身份 |
98
+ | `connectionId` | 当前 Window 物理连接身份 |
99
+ | `state()` | `connecting / ready / disconnected / failed / disposed` 快照 |
100
+ | `ready()` | 等待握手和完整 baseline;不可自动重连的断线、failed 或 disposed 后持续拒绝 `RuntimeUnavailableError`,自动重连时只等待新的 readiness generation |
101
+ | `capability()` | 获取绑定 Runtime、Provider、契约版本和 revision 的代理 |
102
+ | `subscribe()` | 观察 Runtime/Unit/服务快照 |
103
+ | `dispose()` | 同步撤销本句柄,异步关闭连接资源 |
24
104
 
25
- ## 宿主扩展点
105
+ ### Window 投影 Worker capability
106
+
107
+ Window Host 不会根据 Worker manifest 创建假运行单元。需要使用 Worker capability
108
+ 的页面插件应把已经 `ready` 的句柄传给 Window App:
109
+
110
+ ```ts
111
+ const app = await createWindowApp({
112
+ remoteRuntime: runtime,
113
+ plugins: [definePlugin({
114
+ id: "window-consumer",
115
+ dependencies: [{
116
+ capability: "coordinator.service",
117
+ contractVersion: "coordinator.service.v1",
118
+ sourceRuntime: "shared-worker",
119
+ }],
120
+ async setup(ctx) {
121
+ const coordinator = ctx.serviceBridge?.requireProxy({
122
+ capabilityId: "coordinator.service",
123
+ contractVersion: "coordinator.service.v1",
124
+ runtime: "shared-worker",
125
+ }, ctx.scope);
126
+ ctx.provide("window.coordinator", await coordinator.call({ type: "health" }));
127
+ },
128
+ })],
129
+ });
130
+ ```
131
+
132
+ `remoteRuntime` 只向 Host 投影当前 baseline/revision 中的服务和单元状态;setup
133
+ 函数不会进入 Worker。断线时 Host 同步撤销页面插件的 Scope 和远程代理,重连后的
134
+ 新代理必须重新取得,不会静默重绑旧引用。
135
+
136
+ ## 生命周期和 Scope
137
+
138
+ RuntimeUnit 实例存在的条件是:目标 Runtime 存活、插件启用意图为 true、硬依赖
139
+ 已就绪并且当前 Runtime 已装配实现。每个实例仍由框架创建一个内部
140
+ `ResourceScope`,用于 `AbortSignal`、capability ownership、task/subscription
141
+ ownership 和 cleanup callbacks;这个 Scope 不再从用户声明的生命周期分类推导。
142
+
143
+ 停用顺序固定为:同步阻止新 capability 和调用、撤销旧引用、触发 Scope
144
+ `AbortSignal`、执行 setup teardown 与 `ctx.onDispose()`,最后发布停止/清理状态。
145
+ `revoke()` 先形成安全边界,`dispose()` 再等待异步收尾;清理失败和超时通过
146
+ `LifecycleDisposeResult` 暴露。
147
+
148
+ 领域状态(例如 owner、session epoch、Vault lock/unlock、桶世代和最终 I/O
149
+ fence)不属于 WebLoom Runtime 生命周期。应用自己的 Coordinator/服务控制器
150
+ 负责推进领域状态,再通过新的服务快照让旧代理失效。
151
+
152
+ ## 依赖和契约
153
+
154
+ 跨 Runtime 依赖必须声明精确的 `contractVersion` 和 `sourceRuntime`。本地
155
+ capability 可以使用 `runtimeCapabilityContractVersion()` 或
156
+ `defineRuntimeUnitProvidedContracts()` 生成默认 v1 版本;框架不会根据 capability
157
+ 名称猜测远端服务。`providedContracts`、Provider 实例身份、Runtime 启动身份和
158
+ 快照 revision 都参与代理绑定。
159
+
160
+ ## 服务桥和 wire codec
26
161
 
27
- `CreatePluginHostOptions` 提供 `capabilities`、`contextExtension`、`manifestValidator`、`scopeResolver`、`permissionPolicy`、`configStore`、`pluginIntentCoordinator`、`runtimeSnapshots`、`contributionAdapters` 和 `serviceBridgeForPlugin`。WebLoom 不创建产品 Registry、日志、存储或身份状态机。
162
+ 低层 `createServiceBridge()` 仍可用于复杂打包和协议扩展。它只接受同一连接、
163
+ 权威身份、连续快照和精确契约版本;传输层每次调用生成独立 `callId`,业务
164
+ `operationId` 可以复用但不参与响应关联。默认消息 codec 生成
165
+ `webloom.remote-service.*`;迁移旧协议时可传入显式前缀。
28
166
 
29
- 贡献适配器返回的 `ContributionHandle` 支持 `revoke()` 和 `dispose()`:前者用于同步撤下入口,后者用于等待异步收尾。任何贡献都必须绑定当前 `instanceId` 和 Scope。
167
+ 普通插件不需要接触 `MessagePort`、握手或 codec。测试中的 `MessageChannel`
168
+ 证明 transport simulation;真实浏览器验收仍需确认 `Window` 与
169
+ `SharedWorkerGlobalScope` 的 realm marker、setup 次数和多页面连接行为。
170
+ 仓库提供 `scripts/browser-runtime-fixture/` 与 `pnpm run test:browser`;缺少
171
+ Playwright/Chromium 时脚本明确报告 unsupported,不回退为 Node 或同页面模拟。
@@ -8,25 +8,33 @@
8
8
  | WebLoom 起始提交 | `f1c801655c3132c57b66045ff6d5e642fba4a8ea` |
9
9
  | Node | `v22.13.1` |
10
10
  | pnpm | `11.5.1` |
11
- | 首发包版本 | `0.1.0` |
11
+ | 下一发布包版本 | `0.2.0` |
12
+ | npm 包名 | `webloom-framework` |
13
+ | 发布来源提交 | `a5ace48` |
14
+ | 已发布基线标签 | `v0.1.0` |
12
15
 
13
16
  迁入范围是通用 Manifest、依赖图、Host 调度、MessageBus、生命周期 Scope、权限租约、服务桥、MessagePort 传输、升级门禁、意图控制、任务调度、资源 Store 和 React 绑定。产品 Registry、业务配置、产品日志、身份状态机和视觉组件不属于 WebLoom。
14
17
 
15
- 本文件只记录代码迁移基线。npm 包名占用查询、许可证归属确认、provenance、发布和部署由发布责任人在发布批次执行;施工代理不自动发布。
18
+ 本文件记录代码迁移基线和首发包发布 provenance。npm 包名占用查询、许可证归属确认、
19
+ 发布和部署由发布责任人在发布批次执行;施工代理不自动发布。
16
20
 
17
21
  ## 当前工作区发布状态
18
22
 
19
- 当前拆分源码仍在工作树中,尚未形成包含全部实现的正式提交;上表的
20
- `WebLoom 起始提交` 只是独立仓库初始化提交,不能充当 `0.1.0` 的源码 provenance。
23
+ 当前工作区正在准备 `webloom-framework@0.2.0`,但该版本尚未发布到 npm;下游在发布
24
+ 责任人完成正式发布前继续使用本地工作区依赖。`v0.1.0` / npm `0.1.0` 是已发布基线,
25
+ 不是本轮未发布代码的验收替代品。
21
26
 
22
- 正式发布前必须由负责人完成以下确认:
27
+ WebLoom 已形成包含全部实现和测试的正式发布提交 `a5ace48`,并以 `v0.1.0` 标签发布
28
+ `webloom-framework@0.1.0`。上表的 `WebLoom 起始提交` 仍只是独立仓库初始化提交,
29
+ 不作为 `0.1.0` 的源码 provenance。
23
30
 
24
- - 提交 WebLoom 全部实现和测试,并把该提交记录为发布 provenance;
25
- - 确认 `AGPL-3.0-only` 源码归属和发布责任;
26
- - 使用 `pnpm run pack:consumer` 验证 tarball 的 core-only、React 和 Worker 三类消费者;
27
- - 每个临时消费者都生成独立的 `smoke.ts`,使用临时项目自己的 `tsc --noEmit`
31
+ 发布记录确认如下:
32
+
33
+ - `AGPL-3.0-only` 源码归属和发布责任已按包元数据记录;
34
+ - `pnpm run pack:consumer` 已验证 tarball 的 core-only、React 和 Worker 三类消费者;
35
+ - 每个临时消费者均使用独立的 `smoke.ts` 和临时项目自己的 `tsc --noEmit`
28
36
  编译公开声明;Worker 消费者使用 `lib: ["ES2022", "WebWorker"]` 且不安装 React;
29
- - `npm pack --json` 必须通过发布文件白名单、tarball/解包体积上限和必需入口文件检查;
30
- - 从 tarball 解包后扫描全部 `.d.ts` 与 `.js.map`,禁止本地绝对路径、不可发布的
37
+ - `npm pack --json` 已通过发布文件白名单、tarball/解包体积上限和必需入口文件检查;
38
+ - 从 tarball 解包后扫描全部 `.d.ts` 与 `.js.map`,未发现本地绝对路径、不可发布的
31
39
  source map 路径以及产品领域字段;
32
- - 在负责人确认后创建 `v0.1.0` tag 并发布 npm 包。
40
+ - 已创建 `v0.1.0` tag 并发布 npm 包 `webloom-framework@0.1.0`。