@mbws/plugin-sdk 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/README.md +95 -14
- package/dist/contract.js +6 -2
- package/dist/vite.d.ts +12 -0
- package/dist/vite.js +145 -0
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -1,28 +1,109 @@
|
|
|
1
1
|
# @mbws/plugin-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MBWS 数据加工插件协议 SDK——为插件面板提供 `createMbws()` 与宿主完成握手,返回带
|
|
4
|
+
`data` / `runtime` / `storage` / `ui` / `panel` / `contract` 命名空间的客户端对象。
|
|
5
|
+
通常你不需要手动安装本包:用 `pnpm create @mbws/plugin` 脚手架生成的工程已自带依赖;
|
|
6
|
+
手动集成时再 `pnpm add @mbws/plugin-sdk`。
|
|
7
|
+
|
|
8
|
+
## 安装
|
|
4
9
|
|
|
5
10
|
```bash
|
|
6
11
|
pnpm add @mbws/plugin-sdk
|
|
7
12
|
```
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
要求 Node ≥18(或现代浏览器环境);包内零运行时依赖(类型与运行时均为自带实现)。
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
共用同一套类型源
|
|
13
|
-
- **运行时**:宿主端口注入适配(桌面/网页宿主零感知),dev 环境自动降级 mock
|
|
14
|
-
(`data.read` 读 `samples/*.json`,本地 `pnpm dev` 即可跑通面板)
|
|
15
|
-
- **校验**:`validateManifest`(构建期与装载期单一权威校验源)
|
|
16
|
+
## 最小面板示例
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
```ts
|
|
19
|
+
import { createMbws } from "@mbws/plugin-sdk";
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
const mbws = await createMbws();
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
// 读输入数据(key 见关联任务的契约 inputs)
|
|
24
|
+
const value = await mbws.data.read("input");
|
|
25
|
+
|
|
26
|
+
// 面板内容变化后按内容自适应高度,宿主会同步调整 iframe 高度
|
|
27
|
+
mbws.panel.resize(document.body.scrollHeight);
|
|
28
|
+
|
|
29
|
+
// 计算完成,写回输出(outputs 的 key 集须与契约 outputs 对齐,越界会被拒)
|
|
30
|
+
await mbws.data.apply({ result: transform(value) });
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
注意 `createMbws()` 全局只能调用一次(与 VS Code `acquireVsCodeApi` 同心智),二次调用
|
|
34
|
+
会抛 `MbwsInvokeError`(`E_PROTOCOL_VIOLATION`)。
|
|
35
|
+
|
|
36
|
+
## API 速查
|
|
37
|
+
|
|
38
|
+
握手成功后返回 `MbwsClient`。除 `panel` / `contract` 恒存在外,其余命名空间按
|
|
39
|
+
manifest 权限授予情况存在——未声明/未授予的命名空间在对象上为 `undefined`,使用前
|
|
40
|
+
建议判空。
|
|
41
|
+
|
|
42
|
+
| 命名空间.方法 | 签名 | 用途 |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| `data.read` | `read(key: string): Promise<unknown>` | 读当前任务 slot 的输入值 |
|
|
45
|
+
| `data.blob` | `blob(key: string): Promise<{ url: string; mime?: string }>` | 拿文件类输入的签名访问 URL |
|
|
46
|
+
| `data.apply` | `apply(outputs: Record<string, unknown>): Promise<void>` | 写回输出(经宿主 write gate 校验) |
|
|
47
|
+
| `runtime.progress` | `progress(ratio?: number, message?: string): Promise<void>` | 上报进度(0~1)与状态文案 |
|
|
48
|
+
| `runtime.log` | `log(...args: unknown[]): Promise<void>` | 写运行日志(宿主侧可查看) |
|
|
49
|
+
| `runtime.signal` | `signal(): AbortSignal` | 取消信号——用户取消任务时 abort |
|
|
50
|
+
| `storage.get` | `get(key: string): Promise<unknown>` | 读插件专属配额 KV |
|
|
51
|
+
| `storage.set` | `set(key: string, value: unknown): Promise<void>` | 写插件专属配额 KV(配额超限抛错) |
|
|
52
|
+
| `ui.confirm` | `confirm(opts: { title?: string; message: string }): Promise<boolean>` | 宿主渲染的确认弹窗 |
|
|
53
|
+
| `ui.toast` | `toast(message: string, opts?: { type?: "info" \| "success" \| "error" }): Promise<void>` | 宿主渲染的轻提示 |
|
|
54
|
+
| `panel.resize` | `resize(height: number): void` | 上报面板期望高度 |
|
|
55
|
+
| `panel.onBeforeClose` | `onBeforeClose(cb: () => void): void` | 注册关闭前询问回调 |
|
|
56
|
+
| `panel.replyBeforeClose` | `replyBeforeClose(dirty: boolean): void` | 应答关闭询问(dirty=true 宿主先弹确认) |
|
|
57
|
+
| `contract.get` | `get(opts?: FetchContractOptions): Promise<PluginContract>` | 拉关联任务的最新数据契约 |
|
|
58
|
+
|
|
59
|
+
`contract.get` 不经宿主端口,直接走 HTTP 按插件编号拉取:返回的
|
|
60
|
+
`PluginContract` 含 `inputs` / `outputs`(key → JSON Schema,`data.read` / `data.apply`
|
|
61
|
+
的对齐基准)、`title`、`status`、`updatedAt` 等。`FetchContractOptions` 可传
|
|
62
|
+
`pluginCode`(缺省从工程 `manifest.json` 读)、`baseUrl`、`devKey`、`signal`。
|
|
63
|
+
|
|
64
|
+
## 运行形态
|
|
65
|
+
|
|
66
|
+
插件代码零环境分支——`createMbws()` 内部自动分辨:
|
|
67
|
+
|
|
68
|
+
- **生产(宿主 sandbox iframe 内)**:等待宿主经 `window.postMessage` 递来的
|
|
69
|
+
`MessagePort`,完成 init 握手后按授权构造命名空间。此后所有调用都走端口消息。
|
|
70
|
+
- **开发(本地 `pnpm dev` / 顶窗口 / 端口等待超时)**:自动降级为 dev mock——
|
|
71
|
+
`data.read` 读工程内 `samples/<key>.json` 夹具数据;`data.apply` 只在控制台打印不入库;
|
|
72
|
+
其余命名空间基本 no-op。`contract.get` 仍真实走 HTTP 拉线上契约。
|
|
73
|
+
|
|
74
|
+
握手等待端口默认 3000ms(`createMbws({ timeoutMs })` 可调),单次调用默认 30s 超时
|
|
75
|
+
(`invokeTimeoutMs` 可调)。
|
|
76
|
+
|
|
77
|
+
## 错误处理
|
|
78
|
+
|
|
79
|
+
调用被拒时抛 `MbwsInvokeError`(`Error` 子类),`error.code` 为以下九个错误码之一:
|
|
80
|
+
|
|
81
|
+
| 错误码 | 含义 |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `E_INVALID_ARGS` | 调用参数不符合方法签名 |
|
|
84
|
+
| `E_UNKNOWN_METHOD` | 调用了命名空间下不存在的方法 |
|
|
85
|
+
| `E_PERMISSION_DENIED` | manifest 未声明该权限,或宿主未授予 |
|
|
86
|
+
| `E_QUOTA_EXCEEDED` | 配额超限(AI 次数/费用、指令预算、wall-clock 超时等) |
|
|
87
|
+
| `E_WRITE_GATE_REJECTED` | `apply` 写回被拒(key 越界 / outputSchema 校验失败) |
|
|
88
|
+
| `E_CAPABILITY_UNAVAILABLE` | 依赖的能力包未安装或版本不满足 |
|
|
89
|
+
| `E_TIMEOUT` | 调用超时 |
|
|
90
|
+
| `E_CANCELLED` | 任务被取消后的在途调用收尾 |
|
|
91
|
+
| `E_PROTOCOL_VIOLATION` | 消息违反协议(含 `createMbws()` 二次调用) |
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { createMbws, MbwsInvokeError } from "@mbws/plugin-sdk";
|
|
95
|
+
|
|
96
|
+
const mbws = await createMbws();
|
|
97
|
+
try {
|
|
98
|
+
await mbws.data.apply({ result: 1 });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error instanceof MbwsInvokeError && error.code === "E_WRITE_GATE_REJECTED") {
|
|
101
|
+
// outputs key 集与契约不对齐,按 error.data 提示修正
|
|
102
|
+
}
|
|
103
|
+
}
|
|
23
104
|
```
|
|
24
105
|
|
|
25
|
-
##
|
|
106
|
+
## 另请参阅
|
|
26
107
|
|
|
27
|
-
|
|
28
|
-
|
|
108
|
+
- 工程脚手架:[`@mbws/create-plugin`](https://www.npmjs.com/package/@mbws/create-plugin)
|
|
109
|
+
(`pnpm create @mbws/plugin <目录>` 一条命令生成带本 SDK 的完整插件工程)
|
package/dist/contract.js
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
function injectedPluginCode() {
|
|
13
13
|
return typeof __MBWS_PLUGIN_CODE__ !== "undefined" ? __MBWS_PLUGIN_CODE__ : undefined;
|
|
14
14
|
}
|
|
15
|
+
function injectedDevContractBase() {
|
|
16
|
+
return typeof __MBWS_DEV_CONTRACT_BASE__ !== "undefined" ? __MBWS_DEV_CONTRACT_BASE__ : undefined;
|
|
17
|
+
}
|
|
15
18
|
/** manifest.id 按 baseURI 记忆化——同一页面重复调用不再多发 manifest 请求 */
|
|
16
19
|
const manifestIdCache = new Map();
|
|
17
20
|
/** 从本工程根读 manifest.id(dev server / 解包产物内 manifest.json 均在 baseURI 根) */
|
|
@@ -38,11 +41,12 @@ async function readManifestId() {
|
|
|
38
41
|
/** 按插件编号拉关联任务的最新契约。非 2xx 抛带状态码与后端 message 的 Error。 */
|
|
39
42
|
export async function fetchContract(opts = {}) {
|
|
40
43
|
const pluginCode = opts.pluginCode ?? injectedPluginCode() ?? (await readManifestId());
|
|
41
|
-
|
|
44
|
+
// URL 前缀:dev 注入值优先(同源走插件中间件,免 CORS),否则 baseUrl(缺省同源相对)
|
|
45
|
+
const prefix = injectedDevContractBase() ?? (opts.baseUrl ?? "").replace(/\/+$/, "");
|
|
42
46
|
const headers = {};
|
|
43
47
|
if (opts.devKey)
|
|
44
48
|
headers["X-Dev-Key"] = opts.devKey;
|
|
45
|
-
const response = await fetch(`${
|
|
49
|
+
const response = await fetch(`${prefix}/api/plugin-dev-tasks/contract/by-plugin/${encodeURIComponent(pluginCode)}`, { headers, signal: opts.signal });
|
|
46
50
|
if (!response.ok) {
|
|
47
51
|
let message = `契约拉取失败(HTTP ${response.status})`;
|
|
48
52
|
try {
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import { type MbwsUserConfig } from "./config.js";
|
|
3
|
+
export interface MbwsVitePluginOptions {
|
|
4
|
+
/** mbws.config.ts 的配置(defineConfig 回传值)——静态合同与动态开发配置同住 */
|
|
5
|
+
config: MbwsUserConfig;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* mbws vite 插件。dev 预览下契约拉取同源化:SDK fetchContract 读到注入的
|
|
9
|
+
* `__MBWS_DEV_CONTRACT_BASE__` 后改打 `/__mbws__/api/...`,由本插件的中间件
|
|
10
|
+
* 转发到真实后端——插件 dev 端口不在后端 CORS 白名单的问题由此消解。
|
|
11
|
+
*/
|
|
12
|
+
export declare function mbwsVitePlugin(opts: MbwsVitePluginOptions): Plugin;
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 插件工程的 vite 插件——把平台机械(manifest 派生 / define 注入 / dev 虚拟供给与
|
|
3
|
+
* 后端转发)收敛进 SDK,工程 vite.config.ts 只留 `mbwsVitePlugin({ config })` 一行。
|
|
4
|
+
*
|
|
5
|
+
* 承担四件事(对齐原脚手架模板内联版语义):
|
|
6
|
+
* - define 注入插件编号(build/serve 都注入),serve 额外注入 dev 契约前缀;
|
|
7
|
+
* - 缺省补 base: "./"(产物在 OSS 子目录 / registry 代理路径下托管)与双入口
|
|
8
|
+
* rollupOptions.input(panel.html / viewer.html),用户已设项不覆盖;
|
|
9
|
+
* - dev 虚拟供给 /manifest.json(buildManifest 派生,与 build 产物同源);
|
|
10
|
+
* - dev 转发 /__mbws__/api/* 到后端(Node 全局 fetch,不走 server.proxy——
|
|
11
|
+
* 用户自己的 proxy 配置自由,互不干扰);
|
|
12
|
+
* - build 后往 dist/<id>@<version>/ 写 manifest.json(产物直出解包形态目录)。
|
|
13
|
+
*
|
|
14
|
+
* vite 只进 devDependencies 供类型与测试(type-only import),SDK 产物不依赖 vite。
|
|
15
|
+
*/
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { buildManifest } from "./config.js";
|
|
19
|
+
/** dev 契约拉取的专属命名空间:同源走插件中间件转发,免 CORS */
|
|
20
|
+
const DEV_CONTRACT_BASE = "/__mbws__";
|
|
21
|
+
/** 后端缺省地址:插件开发者缺省连线上(拉线上 spec),本地联调走 env 或 apiBaseUrl */
|
|
22
|
+
const DEFAULT_API_BASE = "https://union.mobiwusi.com";
|
|
23
|
+
/** dev 转发目标:config.apiBaseUrl > shell env > 线上(发包即线上,地址不是工程配置项) */
|
|
24
|
+
function resolveApiBase(config) {
|
|
25
|
+
return (config.apiBaseUrl ?? process.env.MBWS_API_BASE_URL ?? DEFAULT_API_BASE).replace(/\/+$/, "");
|
|
26
|
+
}
|
|
27
|
+
/** 读请求体(POST 等带 body 的转发用;GET/HEAD 直接跳过) */
|
|
28
|
+
function readRequestBody(req) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const chunks = [];
|
|
31
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
32
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
33
|
+
req.on("error", reject);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* mbws vite 插件。dev 预览下契约拉取同源化:SDK fetchContract 读到注入的
|
|
38
|
+
* `__MBWS_DEV_CONTRACT_BASE__` 后改打 `/__mbws__/api/...`,由本插件的中间件
|
|
39
|
+
* 转发到真实后端——插件 dev 端口不在后端 CORS 白名单的问题由此消解。
|
|
40
|
+
*/
|
|
41
|
+
export function mbwsVitePlugin(opts) {
|
|
42
|
+
const { config } = opts;
|
|
43
|
+
// 工程 root:config 钩子里记(用户显式 root 优先),closeBundle 写产物时用
|
|
44
|
+
let projectRoot = process.cwd();
|
|
45
|
+
// manifest 是纯派生物,构建/供给共用同一序列化姿势(尾换行对齐文件写习惯)
|
|
46
|
+
const manifestJson = () => `${JSON.stringify(buildManifest(config), null, 2)}\n`;
|
|
47
|
+
return {
|
|
48
|
+
name: "mbws-plugin",
|
|
49
|
+
config(userConfig, { command }) {
|
|
50
|
+
projectRoot = userConfig.root ?? process.cwd();
|
|
51
|
+
const define = {
|
|
52
|
+
__MBWS_PLUGIN_CODE__: JSON.stringify(config.id),
|
|
53
|
+
};
|
|
54
|
+
// dev 专用前缀只在 serve 注入——build 产物绝不含 /__mbws__(宿主内无此路由)
|
|
55
|
+
if (command === "serve") {
|
|
56
|
+
define.__MBWS_DEV_CONTRACT_BASE__ = JSON.stringify(DEV_CONTRACT_BASE);
|
|
57
|
+
}
|
|
58
|
+
// 增量配置(vite 浅合并,不覆盖用户已设项)
|
|
59
|
+
const incremental = { define };
|
|
60
|
+
// 相对 base:产物在 OSS 子目录 / registry 代理路径下托管,资源引用必须是 ./ 相对路径
|
|
61
|
+
if (!userConfig.base)
|
|
62
|
+
incremental.base = "./";
|
|
63
|
+
// 只打包宿主要装载的两个入口;根 index.html 欢迎页是 dev 导航,不进产物
|
|
64
|
+
if (!userConfig.build?.rollupOptions?.input) {
|
|
65
|
+
incremental.build = {
|
|
66
|
+
rollupOptions: {
|
|
67
|
+
input: [
|
|
68
|
+
path.resolve(projectRoot, "panel.html"),
|
|
69
|
+
path.resolve(projectRoot, "viewer.html"),
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// 依赖预构建不消费顶层 define,漏了 SDK 里的注入读取在 dev 侧失效
|
|
75
|
+
if (command === "serve") {
|
|
76
|
+
incremental.optimizeDeps = {
|
|
77
|
+
esbuildOptions: { define: { __MBWS_PLUGIN_CODE__: JSON.stringify(config.id) } },
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return incremental;
|
|
81
|
+
},
|
|
82
|
+
configureServer(server) {
|
|
83
|
+
server.middlewares.use((req, res, next) => {
|
|
84
|
+
const pathname = (req.url ?? "").split("?")[0];
|
|
85
|
+
if (pathname === "/manifest.json") {
|
|
86
|
+
// dev 虚拟供给:SDK fetchContract 的 manifest 兜底读取在 dev/产物两形态行为一致
|
|
87
|
+
res.setHeader("content-type", "application/json");
|
|
88
|
+
res.end(manifestJson());
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (pathname.startsWith(`${DEV_CONTRACT_BASE}/api`)) {
|
|
92
|
+
// 转发异步进行,失败交 next(connect 约定);返回 promise 供测试 await
|
|
93
|
+
return forwardApi(config, req, res).catch(next);
|
|
94
|
+
}
|
|
95
|
+
next();
|
|
96
|
+
return undefined;
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
closeBundle() {
|
|
100
|
+
// 产物直出解包形态目录 <id>@<version>/,桌面 MBWS_DEV_PLUGIN_DIR 指向 dist 即装载
|
|
101
|
+
const outDir = path.resolve(projectRoot, `dist/${config.id}@${config.version}`);
|
|
102
|
+
// mkdir 容错:在线构建场景 outDir 被平台覆盖,本目录可能不存在(写失败会炸构建)
|
|
103
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
104
|
+
fs.writeFileSync(path.join(outDir, "manifest.json"), manifestJson());
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** /__mbws__/<rest> → <apiBase>/<rest>:方法/头透传,响应状态码/content-type/body 透传 */
|
|
109
|
+
async function forwardApi(config, req, res) {
|
|
110
|
+
const pathname = (req.url ?? "").split("?")[0];
|
|
111
|
+
const rest = pathname.slice(DEV_CONTRACT_BASE.length);
|
|
112
|
+
try {
|
|
113
|
+
// 头透传(host/connection 是逐跳头,指向 dev server 自身,不能带给后端)
|
|
114
|
+
const headers = {};
|
|
115
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
116
|
+
if (value === undefined || key === "host" || key === "connection")
|
|
117
|
+
continue;
|
|
118
|
+
headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
119
|
+
}
|
|
120
|
+
const method = req.method ?? "GET";
|
|
121
|
+
const body = method === "GET" || method === "HEAD"
|
|
122
|
+
? undefined
|
|
123
|
+
: (await readRequestBody(req));
|
|
124
|
+
// 查询串原样保留(/api/x?k=v 转发不丢参)
|
|
125
|
+
const search = (req.url ?? "").slice(pathname.length);
|
|
126
|
+
const upstream = await fetch(`${resolveApiBase(config)}${rest}${search}`, {
|
|
127
|
+
method,
|
|
128
|
+
headers,
|
|
129
|
+
body,
|
|
130
|
+
});
|
|
131
|
+
res.statusCode = upstream.status;
|
|
132
|
+
const contentType = upstream.headers.get("content-type");
|
|
133
|
+
if (contentType)
|
|
134
|
+
res.setHeader("content-type", contentType);
|
|
135
|
+
res.end(Buffer.from(await upstream.arrayBuffer()));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
// 转发失败按网关错误处理:JSON 错误体对齐后端统一错误格式
|
|
139
|
+
res.statusCode = 502;
|
|
140
|
+
res.setHeader("content-type", "application/json");
|
|
141
|
+
res.end(JSON.stringify({
|
|
142
|
+
message: `mbws dev forward failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mbws/plugin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Moye 插件开发 SDK——panel/viewer 与宿主的类型定义与运行时端口适配",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,24 +10,27 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./vite": {
|
|
15
|
+
"types": "./dist/vite.d.ts",
|
|
16
|
+
"default": "./dist/vite.js"
|
|
13
17
|
}
|
|
14
18
|
},
|
|
15
19
|
"publishConfig": {
|
|
16
20
|
"access": "public"
|
|
17
21
|
},
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/mobiwusi-dev/Union.git",
|
|
21
|
-
"directory": "packages/plugin-sdk"
|
|
22
|
-
},
|
|
23
22
|
"files": [
|
|
24
23
|
"dist"
|
|
25
24
|
],
|
|
26
25
|
"dependencies": {
|
|
27
26
|
"zod": "^4.4.3"
|
|
28
27
|
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vite": "^8.0.14"
|
|
30
|
+
},
|
|
29
31
|
"scripts": {
|
|
30
32
|
"build": "tsc -p tsconfig.build.json",
|
|
33
|
+
"test": "vitest run",
|
|
31
34
|
"pack:sdk": "pnpm build && pnpm pack"
|
|
32
35
|
}
|
|
33
36
|
}
|