@dp-bohrium/widget-contracts 0.0.1 → 0.0.3

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 CHANGED
@@ -1,22 +1,32 @@
1
1
  # @dp-bohrium/widget-contracts
2
2
 
3
- Bohrium Widget Platform 的跨仓共享 Contract 包。它是 Manifest、Host
4
- Runtime Config、Runtime Bridge 消息及其相关类型的唯一事实源,供 Shrimp
5
- Host Runtime、SDK Runtime 和 Widget 工具链共同消费。
3
+ Bohrium Widget 平台的跨仓共享 Contract 包。它是 Manifest、Host Runtime Config、
4
+ Runtime Bridge 消息及其相关类型的唯一事实源,供 HostSDK Runtime 与 Widget
5
+ 工具链共同消费。
6
6
 
7
7
  本包只提供版本化 JSON Schema、由 Schema 生成的 TypeScript 类型和
8
8
  conformance fixtures,不提供生产 Runtime、AJV validator 或 Widget UI。
9
9
 
10
10
  ## 安装
11
11
 
12
- 当前版本从 Bohrium 内部 npm Registry 安装,并建议固定到明确版本:
13
-
14
12
  ```bash
15
- pnpm add @dp-bohrium/widget-contracts@0.0.1 \
16
- --registry=https://registry.npmjs.org
13
+ pnpm add @dp-bohrium/widget-contracts
17
14
  ```
18
15
 
19
- 运行环境要求 Node.js 20 或更高版本。
16
+ 运行环境要求 Node.js 20 或更高版本。需要钉死版本时,在消费方自己的
17
+ `package.json` / lockfile 中锁定,而不是照抄过期的安装命令。
18
+
19
+ ### 消费方门禁 CLI
20
+
21
+ 包内附带 `check-no-legacy-bohrium-widget-scope`,用于禁止继续依赖已废弃的
22
+ `@bohrium/widget-contracts` / `@bohrium/widget-sdk`(不影响
23
+ `@bohrium/widget-runtime*`):
24
+
25
+ ```bash
26
+ pnpm exec check-no-legacy-bohrium-widget-scope
27
+ # 或
28
+ pnpm exec check-no-legacy-bohrium-widget-scope /path/to/consumer-repo
29
+ ```
20
30
 
21
31
  ## TypeScript 类型
22
32
 
@@ -40,7 +50,7 @@ function handleRender(request: RenderRequest) {
40
50
  主要导出包括:
41
51
 
42
52
  - `WidgetManifest`:Widget bundle 的 Manifest;
43
- - `WidgetHostRuntimeConfig`:Shrimp 为一次运行解析出的 Host Runtime Config;
53
+ - `WidgetHostRuntimeConfig`:控制面为一次运行解析出的 Host Runtime Config;
44
54
  - `RenderRequest`:`tool-result`、`file-preview` 和 `panel` 三种 Slot 的渲染请求;
45
55
  - `HostToWidgetMessage` / `WidgetToHostMessage`:双向 Bridge 消息联合类型;
46
56
  - `CapabilityRequest` / `CapabilityResult`:能力请求与结果;
@@ -71,9 +81,9 @@ function handleRender(request: RenderRequest) {
71
81
  - `runtime.origin` 与 `catalogRevision` 由 Host Config 注入,消费者不得写死
72
82
  当前 Runtime 域名。
73
83
 
74
- `network.fetch` 只定义 Widget/Host 间的结构化能力契约,不让 Widget Runtime 依赖
75
- Agent Widget。默认 provider、无头授权控制器和复用 Agent Widget primitives 的默认弹窗
76
- 由 Host 组合;Host 也可以替换 presenter 或整个 provider,因此无需新增独立设计系统。
84
+ `network.fetch` 只定义 Widget/Host 间的结构化能力契约,不规定 Host UI 实现。
85
+ 默认 provider、无头授权控制器和授权弹窗由 Host 组合;Host 也可以替换 presenter
86
+ 或整个 provider,因此无需新增独立设计系统。
77
87
 
78
88
  ## JSON Schema
79
89
 
@@ -83,7 +93,7 @@ Schema 文件通过包的子路径导出,可交给 AJV 或其他 JSON Schema 2
83
93
  | 文件 | 责任 | 主要消费者 |
84
94
  | --- | --- | --- |
85
95
  | `schemas/widget-manifest.schema.json` | bundle 名称、入口、Slot、能力申请和样例 | 上传与管理侧 |
86
- | `schemas/host-runtime-config.schema.json` | Shrimp 为一次运行选择的版本、Digest、授权和资源配置 | Host Runtime |
96
+ | `schemas/host-runtime-config.schema.json` | 控制面为一次运行选择的版本、Digest、授权和资源配置 | Host Runtime |
87
97
  | `schemas/widget-runtime-contracts.schema.json` | iframe 启动后的 Bridge、Render、Capability、Error 和资源预算消息 | SDK Runtime / Host Runtime |
88
98
 
89
99
  例如,在支持 JSON module import 的 ESM 工程中:
@@ -98,9 +108,8 @@ import manifestSchema from
98
108
  Schema 的 `$id` 使用包内相对标识(例如 `widget-manifest.schema.json`),**不是**可联网拉取的 URL。
99
109
  依赖方必须从已安装的 `@dp-bohrium/widget-contracts/schemas/*.json` 本地加载并按 `$id` 注册,再解析 `$ref`;不要假设校验器会访问网络。
100
110
 
101
- 公开探测版从 `0.0.1` 起发布到 npmjs(`@dp-bohrium`)。历史内部 prerelease
102
- (`0.1.0-alpha.*`)曾去掉 schema 文件名的 `.v1` 后缀、增加 Host 托管网络与
103
- Panel 能力,并移除静态 `outboundOrigins`;那些变更已并入当前 Contract。
111
+ 公开探测版发布到 npmjs(`@dp-bohrium`)。当前 Contract 已包含 Host 托管网络与
112
+ Panel 能力,并移除静态 `outboundOrigins`;Schema 文件名不再使用 `.v1` 后缀。
104
113
 
105
114
  `host-runtime-config.schema.json` 通过包内 `$id`/`$ref` 指向 Manifest 与 Runtime
106
115
  Schema。跨语言消费者必须先从已安装的 schema 文件注册这两个 `$id`,再编译
@@ -148,7 +157,7 @@ const fixture = await import(
148
157
 
149
158
  ## 边界和版本约定
150
159
 
151
- - `host-runtime-config.schema.json` Shrimp 与 Host Runtime 之间的配置
160
+ - `host-runtime-config.schema.json` 是控制面与 Host Runtime 之间的配置
152
161
  Contract,不是 Widget 收到的 Bridge 消息;Host Runtime 只将必要视图通过
153
162
  `init` 消息传给 Widget。
154
163
  - 本包不实现 Runtime 行为,也不负责权限执行、iframe 隔离、CSP、资源治理
@@ -165,26 +174,8 @@ const fixture = await import(
165
174
  `resourceBudget.version` 承载,不进 schema 文件名或 `$id`。在进入稳定发布前,
166
175
  Contract 只有一套当前定义;如需破坏性调整,直接更新 prerelease 消费者,不创建
167
176
  V1/V2 sibling 或 `<name>.v2.schema.json`。
168
- - 类型由仓库根目录的生成脚本维护,不应直接编辑 `src/generated-*.ts`。
169
-
170
- ## 仓库开发
171
-
172
- 在 `bohrium-widget-sdk` monorepo 中运行:
173
-
174
- ```bash
175
- pnpm --filter @dp-bohrium/widget-contracts generate:types
176
- pnpm --filter @dp-bohrium/widget-contracts schema:check
177
- pnpm --filter @dp-bohrium/widget-contracts typecheck
178
- pnpm --filter @dp-bohrium/widget-contracts test
179
- pnpm --filter @dp-bohrium/widget-contracts build
180
- ```
181
-
182
- 详细的协议设计见
183
- [`docs/design/widget-contract-v1.md`](../../docs/design/widget-contract-v1.md)。
184
177
 
185
- ## 发布状态
178
+ ## 许可证
186
179
 
187
- 当前 package metadata 配置为 Bohrium 内部受限 prerelease:Registry 为
188
- `https://registry.npmjs.org/`、访问级别为 `public`、许可证为 `MIT`。
189
- 如果未来要发布到公开 npm Registry,必须先同步确认许可证、访问级别、
190
- Registry 和 CI 发布规则,再更新本 README 与 package metadata。
180
+ MIT。发布到 [npmjs](https://www.npmjs.com/package/@dp-bohrium/widget-contracts),
181
+ `publishConfig.access` `public`。
package/package.json CHANGED
@@ -1,13 +1,29 @@
1
1
  {
2
2
  "name": "@dp-bohrium/widget-contracts",
3
- "version": "0.0.1",
4
- "description": "Versioned Widget schemas and generated contract types.",
3
+ "version": "0.0.3",
4
+ "description": "Bohrium Widget 平台的版本化 Schema 与生成类型(Manifest / Host Runtime Config / Bridge)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "engines": {
8
8
  "node": ">=20"
9
9
  },
10
+ "keywords": [
11
+ "bohrium",
12
+ "dp-bohrium",
13
+ "widget",
14
+ "contracts",
15
+ "schema",
16
+ "json-schema",
17
+ "typescript",
18
+ "iframe",
19
+ "host-runtime"
20
+ ],
21
+ "author": "Bohrium",
22
+ "homepage": "https://www.npmjs.com/package/@dp-bohrium/widget-contracts",
10
23
  "types": "./dist/index.d.ts",
24
+ "bin": {
25
+ "check-no-legacy-bohrium-widget-scope": "./scripts/check-no-legacy-bohrium-widget-scope.mjs"
26
+ },
11
27
  "exports": {
12
28
  ".": {
13
29
  "types": "./dist/index.d.ts",
@@ -21,9 +37,11 @@
21
37
  "dist",
22
38
  "schemas",
23
39
  "conformance",
40
+ "scripts",
24
41
  "README.md",
25
42
  "LICENSE"
26
43
  ],
44
+ "sideEffects": false,
27
45
  "publishConfig": {
28
46
  "access": "public"
29
47
  },
@@ -43,8 +61,8 @@
43
61
  "test": "vitest run",
44
62
  "test:coverage": "vitest run --coverage",
45
63
  "test:watch": "vitest",
46
- "lint": "biome check src test",
47
- "format:check": "biome check --linter-enabled=false src test",
64
+ "lint": "biome check src test scripts",
65
+ "format:check": "biome check --linter-enabled=false src test scripts",
48
66
  "build": "tsc -b tsconfig.build.json --pretty false",
49
67
  "check:surface": "node ../../scripts/quality/check-contract-surface.mjs",
50
68
  "check:no-coupling": "node ../../scripts/quality/check-no-coupling.mjs",
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Fail if a consumer still depends on or imports deprecated internal packages:
4
+ * @bohrium/widget-contracts
5
+ * @bohrium/widget-sdk
6
+ *
7
+ * Usage:
8
+ * node path/to/check-no-legacy-bohrium-widget-scope.mjs [repoRoot]
9
+ *
10
+ * Does not flag @bohrium/widget-runtime or @bohrium/widget-runtime-protocol.
11
+ */
12
+ import { lstatSync, readdirSync, readFileSync, statSync } from "node:fs";
13
+ import { join, relative, resolve } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const legacyNames = ["@bohrium/widget-contracts", "@bohrium/widget-sdk"];
17
+ const skipDirNames = new Set([
18
+ ".git",
19
+ ".next",
20
+ ".pnpm-store",
21
+ ".turbo",
22
+ ".worktrees",
23
+ "coverage",
24
+ "dist",
25
+ "node_modules",
26
+ ".artifacts",
27
+ ]);
28
+ const sourceExt = /\.(cjs|mjs|js|jsx|ts|tsx|json|md|yml|yaml)$/;
29
+ const findings = [];
30
+ const selfPath = resolve(fileURLToPath(import.meta.url));
31
+
32
+ const root = resolve(process.argv[2] ?? process.cwd());
33
+
34
+ function scanPackageJson(path) {
35
+ let pkg;
36
+ try {
37
+ pkg = JSON.parse(readFileSync(path, "utf8"));
38
+ } catch {
39
+ findings.push(`${relative(root, path)}: invalid JSON`);
40
+ return;
41
+ }
42
+ for (const field of [
43
+ "dependencies",
44
+ "devDependencies",
45
+ "peerDependencies",
46
+ "optionalDependencies",
47
+ ]) {
48
+ for (const name of Object.keys(pkg[field] ?? {})) {
49
+ if (legacyNames.includes(name)) {
50
+ findings.push(`${relative(root, path)} ${field}: ${name}`);
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ function scanSource(path) {
57
+ const text = readFileSync(path, "utf8");
58
+ for (const name of legacyNames) {
59
+ if (text.includes(name)) {
60
+ findings.push(`${relative(root, path)} contains ${name}`);
61
+ }
62
+ }
63
+ }
64
+
65
+ function walk(directory) {
66
+ let entries;
67
+ try {
68
+ entries = readdirSync(directory, { withFileTypes: true });
69
+ } catch (error) {
70
+ if (error && (error.code === "ENOENT" || error.code === "EACCES")) return;
71
+ throw error;
72
+ }
73
+ for (const entry of entries) {
74
+ if (skipDirNames.has(entry.name)) continue;
75
+ const path = join(directory, entry.name);
76
+ // Skip dangling / opaque symlinks from package-manager caches.
77
+ let linkStat;
78
+ try {
79
+ linkStat = lstatSync(path);
80
+ } catch (error) {
81
+ if (error && (error.code === "ENOENT" || error.code === "EACCES")) continue;
82
+ throw error;
83
+ }
84
+ if (linkStat.isSymbolicLink()) continue;
85
+ let stat;
86
+ try {
87
+ stat = statSync(path);
88
+ } catch (error) {
89
+ if (error && (error.code === "ENOENT" || error.code === "EACCES")) continue;
90
+ throw error;
91
+ }
92
+ if (stat.isDirectory()) {
93
+ walk(path);
94
+ continue;
95
+ }
96
+ if (resolve(path) === selfPath) continue;
97
+ if (
98
+ entry.name === "pnpm-lock.yaml" ||
99
+ entry.name === "package-lock.json" ||
100
+ entry.name === "yarn.lock" ||
101
+ entry.name === "bun.lock" ||
102
+ entry.name === "bun.lockb"
103
+ ) {
104
+ // Lockfiles may still list transitive @bohrium/widget-* until upstream
105
+ // consumers migrate; policy is enforced on package manifests + source.
106
+ continue;
107
+ }
108
+ if (entry.name === "package.json") {
109
+ scanPackageJson(path);
110
+ continue;
111
+ }
112
+ // Docs that name the banned packages on purpose (migration guide / package README).
113
+ if (
114
+ entry.name.endsWith(".md") &&
115
+ (path.includes(`${join("docs", "superpowers")}`) ||
116
+ path.includes(`${join("docs", "operations", "consumer-governance")}`) ||
117
+ path.endsWith(`${join("packages", "contracts", "README.md")}`))
118
+ ) {
119
+ continue;
120
+ }
121
+ if (sourceExt.test(entry.name)) scanSource(path);
122
+ }
123
+ }
124
+
125
+ walk(root);
126
+
127
+ if (findings.length > 0) {
128
+ console.error("Legacy @bohrium/widget-{contracts,sdk} references found:");
129
+ console.error(findings.map((line) => `- ${line}`).join("\n"));
130
+ console.error(
131
+ "\nMigrate to @dp-bohrium/widget-* on npmjs. See the @dp-bohrium/widget-contracts README.",
132
+ );
133
+ process.exit(1);
134
+ }
135
+
136
+ console.log("no legacy @bohrium/widget-contracts|widget-sdk OK");