@mbws/plugin-sdk 0.2.1 → 0.2.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/dist/client.d.ts +24 -6
- package/dist/client.js +4 -2
- package/dist/index.js +3 -0
- package/dist/schema-types.d.ts +14 -0
- package/dist/schema-types.js +67 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/vite.d.ts +3 -0
- package/dist/vite.js +36 -0
- package/package.json +2 -1
package/dist/client.d.ts
CHANGED
|
@@ -16,20 +16,38 @@
|
|
|
16
16
|
import { type FetchContractOptions, type PluginContract } from "./contract.js";
|
|
17
17
|
import { type MbwsErrorCode } from "./errors.js";
|
|
18
18
|
import type { MbwsErrorPayload } from "./protocol.js";
|
|
19
|
+
/**
|
|
20
|
+
* 插件契约类型形状——mbws.contract.gen.ts 生成的 `MbwsContract` 满足它,
|
|
21
|
+
* `createMbws<MbwsContract>()` 据此把 data.read / data.apply 类型化;
|
|
22
|
+
* 不传泛型时退宽类型(Record<string, unknown>),与生成前的用法完全兼容。
|
|
23
|
+
*/
|
|
24
|
+
export interface MbwsContractTypes {
|
|
25
|
+
inputs: Record<string, unknown>;
|
|
26
|
+
outputs: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/** C 的 inputs 面(C 未声明时退宽 Record) */
|
|
29
|
+
export type MbwsContractInputs<C> = C extends {
|
|
30
|
+
inputs: infer I;
|
|
31
|
+
} ? I : Record<string, unknown>;
|
|
32
|
+
/** C 的 outputs 面(C 未声明时退宽 Record) */
|
|
33
|
+
export type MbwsContractOutputs<C> = C extends {
|
|
34
|
+
outputs: infer O;
|
|
35
|
+
} ? O : Record<string, unknown>;
|
|
19
36
|
/**
|
|
20
37
|
* createMbws() 的返回形态(设计稿 §6.3 命名空间方法面)。
|
|
21
38
|
* 未授予的命名空间在对象上不存在(未装/未授 → 属性 undefined);caps.* 由能力包
|
|
22
39
|
* 动态注册(M3 起),协议固定面不硬编码。
|
|
23
40
|
*/
|
|
24
|
-
export interface MbwsClient {
|
|
25
|
-
/** 工人会话数据面:read 读 slot 值 / blob 拿签名 URL / apply 经 write gate
|
|
41
|
+
export interface MbwsClient<C extends MbwsContractTypes = MbwsContractTypes> {
|
|
42
|
+
/** 工人会话数据面:read 读 slot 值 / blob 拿签名 URL / apply 经 write gate 写回。
|
|
43
|
+
* 泛型 C 来自契约快照(mbws.contract.gen.ts)时,read/apply 的键与值类型随之收紧 */
|
|
26
44
|
data?: {
|
|
27
|
-
read(key:
|
|
28
|
-
blob(key:
|
|
45
|
+
read<K extends string & keyof MbwsContractInputs<C>>(key: K): Promise<MbwsContractInputs<C>[K]>;
|
|
46
|
+
blob<K extends string & keyof MbwsContractInputs<C>>(key: K): Promise<{
|
|
29
47
|
url: string;
|
|
30
48
|
mime?: string;
|
|
31
49
|
}>;
|
|
32
|
-
apply(outputs:
|
|
50
|
+
apply(outputs: MbwsContractOutputs<C>): Promise<void>;
|
|
33
51
|
};
|
|
34
52
|
/** 运行时:进度上报 / 日志 / 取消信号(桥 mbws:event cancel) */
|
|
35
53
|
runtime?: {
|
|
@@ -96,4 +114,4 @@ export declare function connectMbwsPort(port: MessagePort, init: {
|
|
|
96
114
|
export declare function bootstrapFromWindow(win: Pick<Window, "parent" | "addEventListener" | "removeEventListener"> & {
|
|
97
115
|
document?: Document;
|
|
98
116
|
}, opts?: CreateMbwsOptions): Promise<MbwsClient>;
|
|
99
|
-
export declare function createMbws(opts?: CreateMbwsOptions): Promise<MbwsClient
|
|
117
|
+
export declare function createMbws<C extends MbwsContractTypes = MbwsContractTypes>(opts?: CreateMbwsOptions): Promise<MbwsClient<C>>;
|
package/dist/client.js
CHANGED
|
@@ -203,8 +203,10 @@ export async function createMbws(opts = {}) {
|
|
|
203
203
|
}
|
|
204
204
|
acquired = true;
|
|
205
205
|
const win = typeof window !== "undefined" ? window : undefined;
|
|
206
|
-
// 无 window(纯 node)也走 dev mock(bootstrapFromWindow
|
|
206
|
+
// 无 window(纯 node)也走 dev mock(bootstrapFromWindow 内含顶窗口分支)。
|
|
207
|
+
// 泛型只作用于编辑期(data.read/apply 的键值类型),运行时形态与 C 无关——
|
|
208
|
+
// dev mock / 端口客户端原样透传即可
|
|
207
209
|
if (!win)
|
|
208
210
|
return createDevMockMbws();
|
|
209
|
-
return bootstrapFromWindow(win, opts);
|
|
211
|
+
return (await bootstrapFromWindow(win, opts));
|
|
210
212
|
}
|
package/dist/index.js
CHANGED
|
@@ -12,5 +12,8 @@ export * from "./dev-mock.js";
|
|
|
12
12
|
export * from "./errors.js";
|
|
13
13
|
export * from "./manifest.js";
|
|
14
14
|
export * from "./protocol.js";
|
|
15
|
+
// schema-types(契约→TS codegen)不进根入口:它依赖 json-schema-to-typescript +
|
|
16
|
+
// prettier(Node 端),浏览器 bundle 拉根入口会炸(0.2.2 打包 bug)——
|
|
17
|
+
// 只经 ./vite 子路径暴露(Node 工具链场景)
|
|
15
18
|
export * from "./uuid.js";
|
|
16
19
|
export * from "./version.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** 契约拉取响应里类型生成关心的字段(snake_case 原样,见 fetchContract) */
|
|
2
|
+
export interface ContractTypesInput {
|
|
3
|
+
pluginCode: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
/** ISO 时间;仅写进文件头注释作契约版本参考 */
|
|
6
|
+
updatedAt?: string;
|
|
7
|
+
inputs: Record<string, unknown>;
|
|
8
|
+
outputs: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 生成 mbws.contract.gen.ts 全文(与文件现状 diff 后由调用方决定是否落盘)。
|
|
12
|
+
* compile 是 async(内部 prettier 格式化),调用方 await。
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateContractTypes(contract: ContractTypesInput): Promise<string>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 契约 → TS 类型快照生成 —— 服务端按插件编号实时派生的 inputs/outputs JSON Schema
|
|
3
|
+
* 转成 TS 源码(mbws.contract.gen.ts),配合 createMbws<MbwsContract>() 让
|
|
4
|
+
* data.read / data.apply 在编辑期就有类型。
|
|
5
|
+
*
|
|
6
|
+
* 转换本体委托 json-schema-to-typescript(业界标准实现,allOf/$ref/enum/naming
|
|
7
|
+
* 等边角全覆盖)——本模块只负责「契约响应 → 组装成单一 schema → 加文件头」。
|
|
8
|
+
*
|
|
9
|
+
* 诚实边界:类型是拉取时刻的快照,不实时跟随服务端契约变更——真变更以运行时
|
|
10
|
+
* write-gate 校验为准,快照只提供「编辑期提前报错」的第一道。
|
|
11
|
+
*/
|
|
12
|
+
import { compile } from "json-schema-to-typescript";
|
|
13
|
+
/** 契约键 → 合法 TS 标识符(PascalCase;非标识符字符压成下划线,数字开头补前缀) */
|
|
14
|
+
function pascalName(key) {
|
|
15
|
+
const ident = key.replace(/[^\w$]/g, "_");
|
|
16
|
+
const pascal = `${ident.charAt(0).toUpperCase()}${ident.slice(1)}`;
|
|
17
|
+
return /^[A-Za-z_$]/.test(pascal) ? pascal : `_${pascal}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* inputs/outputs 顶层键在生成的类型里全部必填(键集即契约面)。
|
|
21
|
+
* 每个顶层 schema 注入 PascalCase title:json-schema-to-typescript 把带
|
|
22
|
+
* additionalProperties:false 的匿名对象抽成独立声明,名字取 title——不注入
|
|
23
|
+
* 会得到 NoName/NoName1(契约自带的中文 title 不是合法标识符,同样触发)。
|
|
24
|
+
* 包一层对象不直接改原 schema(浅拷贝足够,嵌套结构原样引用)。
|
|
25
|
+
*/
|
|
26
|
+
function asRequiredObject(properties, side) {
|
|
27
|
+
const titled = Object.fromEntries(Object.entries(properties).map(([key, schema]) => [
|
|
28
|
+
key,
|
|
29
|
+
{ ...schema, title: pascalName(key) },
|
|
30
|
+
]));
|
|
31
|
+
return {
|
|
32
|
+
type: "object",
|
|
33
|
+
title: `MbwsContract${side}`,
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
properties: titled,
|
|
36
|
+
required: Object.keys(properties),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 生成 mbws.contract.gen.ts 全文(与文件现状 diff 后由调用方决定是否落盘)。
|
|
41
|
+
* compile 是 async(内部 prettier 格式化),调用方 await。
|
|
42
|
+
*/
|
|
43
|
+
export async function generateContractTypes(contract) {
|
|
44
|
+
const banner = `/**
|
|
45
|
+
* mbws 契约类型(自动生成,勿手改)。
|
|
46
|
+
* 插件:${contract.pluginCode}${contract.title ? `(${contract.title})` : ""}${contract.updatedAt ? ` · 契约更新于 ${contract.updatedAt}` : ""}
|
|
47
|
+
* 生成时机:dev server 启动时按 mbws.config.ts 的 id 拉服务端契约,变更后重启 dev 即同步。
|
|
48
|
+
* 权威以服务端实时契约 + 运行时 write-gate 校验为准,本文件仅编辑期提示。
|
|
49
|
+
*/`;
|
|
50
|
+
// 单一 schema 一次编译:顶层即 MbwsContract(inputs/outputs 两属性),
|
|
51
|
+
// 顶层键注入 PascalCase title 作声明名,x-* 平台扩展键被库忽略
|
|
52
|
+
const body = await compile({
|
|
53
|
+
type: "object",
|
|
54
|
+
title: "MbwsContract",
|
|
55
|
+
required: ["inputs", "outputs"],
|
|
56
|
+
additionalProperties: false,
|
|
57
|
+
properties: {
|
|
58
|
+
inputs: asRequiredObject(contract.inputs, "Inputs"),
|
|
59
|
+
outputs: asRequiredObject(contract.outputs, "Outputs"),
|
|
60
|
+
},
|
|
61
|
+
}, "MbwsContract", {
|
|
62
|
+
bannerComment: banner,
|
|
63
|
+
enableConstEnums: false,
|
|
64
|
+
style: { singleQuote: false, semi: true, trailingComma: "all" },
|
|
65
|
+
});
|
|
66
|
+
return `${body}\n`;
|
|
67
|
+
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/vite.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import { type MbwsUserConfig } from "./config.js";
|
|
3
|
+
export { type ContractTypesInput, generateContractTypes } from "./schema-types.js";
|
|
3
4
|
export interface MbwsVitePluginOptions {
|
|
4
5
|
/** mbws.config.ts 的配置(defineConfig 回传值)——静态合同与动态开发配置同住 */
|
|
5
6
|
config: MbwsUserConfig;
|
|
7
|
+
/** dev 启动时拉契约生成 mbws.contract.gen.ts 类型快照(默认 true;离线/后端不可达自动跳过) */
|
|
8
|
+
generateTypes?: boolean;
|
|
6
9
|
}
|
|
7
10
|
/**
|
|
8
11
|
* mbws vite 插件。dev 预览下契约拉取同源化:SDK fetchContract 读到注入的
|
package/dist/vite.js
CHANGED
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
import fs from "node:fs";
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import { buildManifest } from "./config.js";
|
|
20
|
+
import { generateContractTypes } from "./schema-types.js";
|
|
21
|
+
// 契约类型生成经本子路径暴露(Node 端工具链用;依赖 prettier,不进根入口)
|
|
22
|
+
export { generateContractTypes } from "./schema-types.js";
|
|
20
23
|
/** dev 契约拉取的专属命名空间:同源走插件中间件转发,免 CORS */
|
|
21
24
|
const DEV_CONTRACT_BASE = "/__mbws__";
|
|
22
25
|
/** 后端缺省地址:插件开发者缺省连线上(拉线上 spec),本地联调走 env 或 apiBaseUrl */
|
|
@@ -41,6 +44,7 @@ function readRequestBody(req) {
|
|
|
41
44
|
*/
|
|
42
45
|
export function mbwsVitePlugin(opts) {
|
|
43
46
|
const { config } = opts;
|
|
47
|
+
const generateTypes = opts.generateTypes ?? true;
|
|
44
48
|
// 工程 root:config 钩子里记(用户显式 root 优先),closeBundle 写产物时用
|
|
45
49
|
let projectRoot = process.cwd();
|
|
46
50
|
// manifest 是纯派生物,构建/供给共用同一序列化姿势(尾换行对齐文件写习惯)
|
|
@@ -90,6 +94,11 @@ export function mbwsVitePlugin(opts) {
|
|
|
90
94
|
return incremental;
|
|
91
95
|
},
|
|
92
96
|
configureServer(server) {
|
|
97
|
+
// 契约类型快照生成(fire-and-forget:离线/后端不可达只告警,绝不阻塞 dev)
|
|
98
|
+
if (generateTypes) {
|
|
99
|
+
// logger 缺席(单测的极简 server mock)退 console,访问本身不抛
|
|
100
|
+
void writeContractTypesFile(config, projectRoot, (msg) => server.config?.logger?.info(msg));
|
|
101
|
+
}
|
|
93
102
|
server.middlewares.use((req, res, next) => {
|
|
94
103
|
const pathname = (req.url ?? "").split("?")[0];
|
|
95
104
|
if (pathname === "/manifest.json") {
|
|
@@ -115,6 +124,33 @@ export function mbwsVitePlugin(opts) {
|
|
|
115
124
|
},
|
|
116
125
|
};
|
|
117
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* 拉服务端契约生成 mbws.contract.gen.ts(内容有变才落盘——重启 dev 不产生无谓改动)。
|
|
129
|
+
* 契约端点公开(按插件编号实时派生),失败只在 dev 控制台提示,不影响任何构建行为。
|
|
130
|
+
*/
|
|
131
|
+
async function writeContractTypesFile(config, root, log) {
|
|
132
|
+
try {
|
|
133
|
+
const response = await fetch(`${resolveApiBase(config)}/api/plugin-dev-tasks/contract/by-plugin/${encodeURIComponent(config.id)}`);
|
|
134
|
+
if (!response.ok)
|
|
135
|
+
throw new Error(`HTTP ${response.status}`);
|
|
136
|
+
const data = (await response.json());
|
|
137
|
+
const source = await generateContractTypes({
|
|
138
|
+
pluginCode: config.id,
|
|
139
|
+
title: typeof data.title === "string" ? data.title : undefined,
|
|
140
|
+
updatedAt: typeof data.updated_at === "string" ? data.updated_at : undefined,
|
|
141
|
+
inputs: data.inputs ?? {},
|
|
142
|
+
outputs: data.outputs ?? {},
|
|
143
|
+
});
|
|
144
|
+
const file = path.resolve(root, "mbws.contract.gen.ts");
|
|
145
|
+
if (!fs.existsSync(file) || fs.readFileSync(file, "utf8") !== source) {
|
|
146
|
+
fs.writeFileSync(file, source);
|
|
147
|
+
log("[mbws] 契约类型已生成/更新:mbws.contract.gen.ts(createMbws<MbwsContract>() 即获类型)");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
log(`[mbws] 契约类型生成跳过:${error instanceof Error ? error.message : error}(不影响 dev)`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
118
154
|
/** /__mbws__/<rest> → <apiBase>/<rest>:方法/头透传,响应状态码/content-type/body 透传 */
|
|
119
155
|
async function forwardApi(config, req, res) {
|
|
120
156
|
const pathname = (req.url ?? "").split("?")[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mbws/plugin-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Moye 插件开发 SDK——panel/viewer 与宿主的类型定义与运行时端口适配",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"dist"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"json-schema-to-typescript": "^16.0.0",
|
|
26
27
|
"zod": "^4.4.3"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|