@vizejs / plugin-sdk
编写同步规则、事实提供程序、本地模板转换和编译
输出钩子。安装 @vizejs/native 0.650.0或更新版本 执行插件。
可选的本机对等体允许该包独立安装以进行创作;
它的帮助程序本身并不编译或检测Vue文件。需要Node 22或更新版本。
类型化访问者功能描述符
@vizejs/plugin-sdk/visitor 定义稳定版本的描述符边界
visitor-style插件。v1功能词汇表包括SFC、模板、
script, style, virtual TypeScript, diagnostics, lint, format和devtools trace
事件。每个声明的功能都需要一个匹配的同步回调,并且
TypeScript将回调负载缩小到该功能。
import {
VISITOR_API_VERSION,
defineVisitorPlugin,
negotiateVisitorPlugin,
} from "@vizejs/plugin-sdk/visitor";
const observer = defineVisitorPlugin({
apiVersion: VISITOR_API_VERSION,
name: "virtual-ts-observer",
version: "1.0.0",
capabilities: ["virtual-ts", "diagnostics"] as const,
cacheInputs: [],
visitors: {
"virtual-ts"(event) {
console.log(event.payload.virtualFile, event.payload.mappings.length);
},
diagnostics(event) {
console.log(event.payload.diagnostics.length);
},
},
});
negotiateVisitorPlugin(observer, {
apiVersion: VISITOR_API_VERSION,
capabilities: ["virtual-ts", "diagnostics"],
});
定义失败关闭未知或重复的功能,缺失或
未声明的回调函数、异步函数、保留的缓存输入名称和API
版本不匹配。 runVisitorFixture 冻结一个已编写的事件并强制执行
包测试的同步返回契约。
这个模块只创建不可变的描述符和作者fixture。事实并非如此 在本机编译器、过滤器或语言服务器中注册回调,以便导入 它不会给这些路径增加功。生产主机必须显式地协商 描述符并拥有取消、截止日期、隔离和事件构造。 虚拟TypeScript和devtools跟踪观察者使用单独的可选主机 entrypoints;导入该模块永远不会全局注册这两个回调。
Lint规则和自动修复
import * as native from "@vizejs/native";
import { definePlugin, applyFixes } from "@vizejs/plugin-sdk";
const rule = definePlugin({
name: "team-rule",
version: "1.0.0",
visit: ["ui.bind"],
demands: [],
cacheInputs: [],
rules: {
check(ctx) {
for (const node of ctx.nodes) {
if (node.name === "disabled" && node.value === "true") {
ctx.report(node, "Use a literal boolean attribute.", "disabled");
}
}
},
},
});
const output = native.lintWithPlugins(source, [rule], {
filename: "Button.vue",
cache: true,
validateDeterminism: true,
});
const fixed = applyFixes(source, output.fixes);
报告为访问的L2节点命名。Rust分配它自己编写的UTF-8字节范围;
修复将替换整个范围。 applyFixes 保存其他资源;
重复删除相同的建议并自动拒绝冲突的编辑。
慎重地应用建议,然后重新运行编译器和筛选器。
规则接收不可变的批。 ctx.facts(name) 的组
静态 demands 列表;没有未声明的表越过边界。本地组
包括 templateScopes 以及注册的Croquis生产商 bindings,
undefined-refs, component-usages, reactivity, provide-inject 和
race-conditions 和 unused-bindings。后者计算其注册
bindings 依赖。这个 bindings 和 unused-bindings 跨度是创建的
SFC UTF-8字节范围,由共享生成器映射,即使是重新排序分割
脚本。其他主要位置字段保留其Croquis分析框架:
未定义的引用/组件使用是相对于模板的;反应活性,
提供/注入和比赛位置是相对于脚本的(合并的正常/设置)
脚本(当两者都存在时)。报告和修复总是使用主机的SFC范围。公共组件接口页面有 component-signature,
prop-types, emit-types, slot-types, reactivity-classes 和
component-references。每个接口值都保留了生产者的模式,
可空的未知数和类型依赖的完整性。签名的
props_complete 单独记录是否枚举了所有属性名。
只有源代码的SDK路由没有已解析的目录证明,因此它报告false
不从磁盘读取导入的文件。导入的类型
分析无法解决仍然明确的未知数。基本的Croquis事实要求
JavaScript或TypeScript脚本;其他脚本方言被明确拒绝。
插件访问需要内联HTML模板。撰写外国模板方言 外部模板块在回调之前被拒绝;SDK没有 假装它们的源是HTML,或者为预处理过程发明源映射。
TypeScript推断出每个原生组的精确映射键和深度只读值
从 ctx.facts("prop-types"),包括授权接口顺序和所有发出
过载。包导出 FactGroups, FactKey, FactValue, FactEntry
以及个体的本地契约。自定义提供程序组可以使用
ctx.facts<MyFact>("design/labels"); 未知组默认为 unknown.
事实上供应商
import { defineFactProvider, definePlugin } from "@vizejs/plugin-sdk";
const labels = defineFactProvider({
name: "design",
version: "1",
provides: ["design/labels"],
visit: ["ui.element"],
demands: ["bindings"],
cacheInputs: [],
provide(batch) {
return { "design/labels": batch.nodes.map((node) => [node.id, node.name]) };
},
});
const consumer = definePlugin({
name: "labels",
version: "1",
demands: ["design/labels"],
cacheInputs: [],
rules: {
check(ctx) {
const labels = ctx.facts("design/labels");
},
},
});
native.lintWithPlugins(source, [consumer], { cache: true, factProviders: [labels] });
提供者将每个输出组声明为 provider-name/group,这是必需的。
事实和节点访问。主机计算依赖闭包并拒绝
在使用事实之前,循环、冲突、未声明的输出和格式错误的表。
每个表包含 [stringOrNumericKey, jsonValue] 具有唯一键的行。
提供程序依赖戳记自动输入消费者缓存键。
原生模板转换
import { defineTransformPlugin } from "@vizejs/plugin-sdk";
const design = defineTransformPlugin({
name: "design-system",
version: "1",
cacheInputs: [],
transform(batch) {
return batch.nodes
.filter((node) =>
node.attrs.some((attr) => attr.name === "class" && attr.value === "legacy-btn"),
)
.map((node) => ({
kind: "replace-static-attribute",
node: node.id,
name: "class",
value: "ds-button",
}));
},
});
const transformed = native.compileWithTransformPlugins(template, [design], {
filename: "Button.vue",
sourceMap: true,
cache: true,
cacheDir: ".vize-cache",
});
钩子在原生规范前的L2点运行。它可以取代现有的
静态HTML属性从主机的允许设置;动态属性,
结构编辑、模板载体和外部命名空间拒绝。值是
语义文本,而不是实体拼写。未知目标或重复编辑拒绝
整个响应。编译器将类型化编辑应用于它的真实竞技场和
发出代码和绘制的地图;不接受客户AST JSON。结果是
带有前缀标识符的模块。 plugins 包含每个插件的成本。
格式化程序和输出挂钩
import { defineOutputPlugin } from "@vizejs/plugin-sdk";
const license = defineOutputPlugin({
name: "license",
version: "1",
family: "output",
cacheInputs: [],
output() {
return [{ placement: "prepend", comment: "Copyright Example" }];
},
});
const compiled = native.compileWithOutputPlugins(template, [license], options);
const decorated = native.applyOutputPlugins(transformed.result, [license], { cache: true });
family: "formatter" 返回 {start,end,text} 使用UTF-8字节偏移量进行编辑。
只有保留已解析程序和注释的空白格式
接受。 family: "output" 附加或前置普通块注释;
源映射指令和可执行添加拒绝。主机已存在
映射锚定并保留源内容。每个管线键包含上述内容
输出。功能模式结果携带 preamble 分开 code.
决定论,缓存和成本
声明每个捕获的配置或环境输入 cacheInputs,甚至
当列表为空时。的名字开始 @vize/ host-reserved。源,
文件名,原生构建,SDK运行时字节,插件版本/代码,静态需求,
访问和输入参与键。缓存的lint漏检总是审计两个
相同的批次。提供和转换审计失误。缓存的输出挂钩也总是审计;
默认情况下,非缓存输出挂钩审计。不同的验证输出在缓存之前拒绝。所有钩族
有有限的进程内缓存和选择加入吗 cacheDir 持久性。磁盘点击
在重用之前验证它们的模式、键和受主机限制的输出。
成本包括占用的主机工作时间和JavaScript调用时间,包括审计调用。
缓存命中不执行回调;它的 jsNs 批处理交叉字节为零。
确定性审计观察重复输出。可信回调可以隐藏
环境读取;他们的声明仍然是作者的责任。
隔离的回调源
import {
createSandboxRunner,
SANDBOX_IMAGE,
SandboxRuntimeError,
} from "@vizejs/plugin-sdk/sandbox";
const isolated = createSandboxRunner(
{
name: "isolated-rule",
version: "1",
cacheInputs: [],
configuration: { message: "Use our design system" },
rules: { check: "(ctx, config) => { ctx.report(ctx.nodes[0], config.message); }" },
},
{ timeoutMs: 5000, maxBytes: 1048576 },
);
native.lintWithPlugins(source, [isolated], { cache: true });
安装Docker,启动它的守护进程并拉出导出的pinned SANDBOX_IMAGE
之前使用。回调源代码和显式JSON配置跨stdin;主人
闭包和导入则不然。每次调用都使用一个非根的只读容器
没有主机挂载、主机环境、外部网络或功能,有
内存/ CPU / PID /文件描述符的限制。主机限制请求/输出字节和
执行时间,然后确认容器移除。运行时检查和清理
每次最多增加5秒 timeoutMs.
SandboxRuntimeError.code 区分 runtime_unavailable,
execution_stopped, execution_failed 和 cleanup_failed。不可用的码头工人
或者缺失的图像拒绝执行;它永远不会将来宾作为受信任代码运行。
映像自己的文件系统仍然是可读的。Docker提供隔离;
此API不要求虚拟机隔离。
definePlugin 其他普通的帮助程序执行受信任的应用程序代码
在调用Node进程中同步执行,并且没有执行截止日期。
冻结批次和审计输出并不能隔离这些回调。测量
代理句柄保持峰值兼容性。 @vizejs/extension-sdk 是
单独版本的guest接口。
虚拟TypeScript访客
defineVisitorPlugin 描述符中只有 virtual-ts 能力可以是
为本机类型检查主机协商。普通的 typeCheck 入口点
仍然是plugin-free;呼叫者通过单独的访问者入口点选择加入。
import { typeCheckWithVirtualTsVisitors } from "@vizejs/native";
import {
VISITOR_API_VERSION,
createVirtualTsVisitorHost,
defineVisitorPlugin,
} from "@vizejs/plugin-sdk/visitor";
const observer = defineVisitorPlugin({
apiVersion: VISITOR_API_VERSION,
name: "virtual-ts-observer",
version: "1",
capabilities: ["virtual-ts"],
cacheInputs: [],
visitors: {
"virtual-ts"({ payload }) {
console.log(payload.virtualFile, payload.code, payload.mappings);
},
},
});
typeCheckWithVirtualTsVisitors(source, [createVirtualTsVisitorHost(observer)], {
filename: "src/App.vue",
});
回调接收不可变生成的代码和源/生成的UTF-8字节 在构建实际类型检查投影之后的范围。返回一个值, 请求其他功能或伪造不完整的主机标识拒绝 调用。
Devtools跟踪访问者
devtools-trace 描述符显式附加到请求本地
@vizejs/devtools 录音机。记录器序列化每个提交的跟踪事件
通过协商适配器;禁用的记录器不会调用已配置的
主机,而普通的录音机没有 visitorHosts 不要检查插件
描述符。
import { createDevtoolsTraceRecorder } from "@vizejs/devtools";
import {
VISITOR_API_VERSION,
createDevtoolsTraceVisitorHost,
defineVisitorPlugin,
} from "@vizejs/plugin-sdk/visitor";
const observer = defineVisitorPlugin({
apiVersion: VISITOR_API_VERSION,
name: "trace-observer",
version: "1",
capabilities: ["devtools-trace"],
cacheInputs: [],
visitors: {
"devtools-trace"({ file, payload }) {
console.log(file, payload.events);
},
},
});
const trace = createDevtoolsTraceRecorder({
sessionId: "request-1",
visitorHosts: [createDevtoolsTraceVisitorHost(observer)],
});
每个交付的事件都有一个确定的会话/序列ID,这是派生的阶段
从其跟踪类型中,将毫秒时间戳标准化为纳秒,以及
其余记录器字段为不可变的 data。访问者异常或非void
Result在记录进入快照之前拒绝该记录。