core by vercel-labs/json-render
npx skills add https://github.com/vercel-labs/json-render --skill core用于模式定义、目录创建和规范流式传输的核心包。
defineSchema)defineCatalog)import { defineSchema } from "@json-render/core";
export const schema = defineSchema((s) => ({
spec: s.object({
// 定义规范结构
}),
catalog: s.object({
components: s.map({
props: s.zod(),
description: s.string(),
}),
}),
}), {
promptTemplate: myPromptTemplate, // 可选的自定义 AI 提示
});
import { defineCatalog } from "@json-render/core";
import { schema } from "./schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Button: {
props: z.object({
label: z.string(),
variant: z.enum(["primary", "secondary"]).nullable(),
}),
description: "可点击的按钮组件",
},
},
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
const systemPrompt = catalog.prompt(); // 使用模式的 promptTemplate
const systemPrompt = catalog.prompt({ customRules: ["规则 1", "规则 2"] });
用于流式传输 AI 响应(JSONL 补丁):
import { createSpecStreamCompiler } from "@json-render/core";
const compiler = createSpecStreamCompiler<MySpec>();
// 处理流式数据块
const { result, newPatches } = compiler.push(chunk);
// 获取最终结果
const finalSpec = compiler.getResult();
任何属性值都可以是在渲染时解析的动态表达式:
{ "$state": "/state/key" } - 从状态模型中读取值(单向读取){ "$bindState": "/path" } - 双向绑定:从状态读取并允许写回。用于表单组件的自然值属性(value、checked、pressed 等)。{ "$bindItem": "field" } - 与重复项字段的双向绑定。在重复作用域内使用。{ "$cond":<condition>, "$then": <value>, "$else": <value> } - 评估可见性条件并选择分支{ "$template": "Hello, ${/user/name}!" } - 使用状态值插值 ${/path} 引用{ "$computed": "fnName", "args": { "key":<expression> } } - 使用解析后的参数调用已注册的函数$cond 使用与可见性条件相同的语法($state、eq、neq、not、用于 AND 的数组)。$then 和 $else 本身也可以是表达式(递归)。
组件不使用 statePath 属性进行双向绑定。相反,在自然值属性(例如 value、checked、pressed)上使用 { "$bindState": "/path" }。
{
"color": {
"$cond": { "$state": "/activeTab", "eq": "home" },
"$then": "#007AFF",
"$else": "#8E8E93"
},
"label": { "$template": "Welcome, ${/user/name}!" },
"fullName": {
"$computed": "fullName",
"args": {
"first": { "$state": "/form/firstName" },
"last": { "$state": "/form/lastName" }
}
}
}
import { resolvePropValue, resolveElementProps } from "@json-render/core";
const resolved = resolveElementProps(element.props, { stateModel: myState });
元素可以声明一个 watch 字段(顶层,与 type/props/children 同级),以便在状态值更改时触发操作:
{
"type": "Select",
"props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
"watch": {
"/form/country": { "action": "loadCities", "params": { "country": { "$state": "/form/country" } } }
},
"children": []
}
监视器仅在值更改时触发,而不是在初始渲染时。
内置验证函数:required、email、url、numeric、minLength、maxLength、min、max、pattern、matches、equalTo、lessThan、greaterThan、requiredIf。
跨字段验证在参数中使用 $state 表达式:
import { check } from "@json-render/core";
check.required("字段为必填项");
check.matches("/form/password", "密码必须匹配");
check.lessThan("/form/endDate", "必须在结束日期之前");
check.greaterThan("/form/startDate", "必须在开始日期之后");
check.requiredIf("/form/enableNotifications", "启用时为必填项");
使用可选的规范优化和状态上下文构建结构化的用户提示:
import { buildUserPrompt } from "@json-render/core";
// 全新生成
buildUserPrompt({ prompt: "创建一个待办事项应用" });
// 使用编辑模式进行优化(默认:仅补丁)
buildUserPrompt({ prompt: "添加一个切换开关", currentSpec: spec, editModes: ["patch", "merge"] });
// 包含运行时状态
buildUserPrompt({ prompt: "显示数据", state: { todos: [] } });
可用的编辑模式:"patch"(RFC 6902 JSON 补丁)、"merge"(RFC 7396 合并补丁)、"diff"(统一差异)。
验证规范结构并自动修复常见问题:
import { validateSpec, autoFixSpec } from "@json-render/core";
const { valid, issues } = validateSpec(spec);
const fixed = autoFixSpec(spec);
使用基于状态的条件控制元素可见性。VisibilityContext 是 { stateModel: StateModel }。
import { visibility } from "@json-render/core";
// 语法
{ "$state": "/path" } // 真值性
{ "$state": "/path", "not": true } // 假值
{ "$state": "/path", "eq": value } // 相等性
[ cond1, cond2 ] // 隐式 AND
// 辅助函数
visibility.when("/path") // { $state: "/path" }
visibility.unless("/path") // { $state: "/path", not: true }
visibility.eq("/path", val) // { $state: "/path", eq: val }
visibility.and(cond1, cond2) // { $and: [cond1, cond2] }
visibility.or(cond1, cond2) // { $or: [cond1, cond2] }
visibility.always // true
visibility.never // false
模式可以声明 builtInActions —— 在运行时始终可用并自动注入到提示中的操作:
const schema = defineSchema(builder, {
builtInActions: [
{ name: "setState", description: "更新状态模型中的一个值" },
],
});
这些在提示中显示为 [内置],并且不需要在 defineRegistry 中定义处理程序。
StateStore 接口允许将外部状态管理库(Redux、Zustand、XState 等)插入到 json-render 渲染器中。createStateStore 工厂创建一个简单的内存实现:
import { createStateStore, type StateStore } from "@json-render/core";
const store = createStateStore({ count: 0 });
store.get("/count"); // 0
store.set("/count", 1); // 更新并通知订阅者
store.update({ "/a": 1, "/b": 2 }); // 批量更新
store.subscribe(() => {
console.log(store.getSnapshot()); // { count: 1 }
});
StateStore 接口:get(path)、set(path, value)、update(updates)、getSnapshot()、subscribe(listener)。
| 导出 | 用途 |
|---|---|
defineSchema | 创建新模式 |
defineCatalog | 从模式创建目录 |
createStateStore | 创建与框架无关的内存 StateStore |
resolvePropValue | 根据数据解析单个属性表达式 |
resolveElementProps | 解析元素中的所有属性表达式 |
buildUserPrompt | 使用优化和状态上下文构建用户提示 |
buildEditUserPrompt | 为编辑现有规范构建用户提示 |
buildEditInstructions | 为可用编辑模式生成提示部分 |
isNonEmptySpec | 检查规范是否具有根元素和至少一个元素 |
deepMergeSpec | RFC 7396 深度合并(null 删除,数组替换,对象递归) |
diffToPatches | 从对象差异生成 RFC 6902 JSON 补丁操作 |
EditMode | 类型:`"patch" |
validateSpec | 验证规范结构 |
autoFixSpec | 自动修复常见规范问题 |
createSpecStreamCompiler | 将 JSONL 补丁流式传输到规范中 |
createJsonRenderTransform | 在混合流中分离文本和 JSONL 的 TransformStream |
parseSpecStreamLine | 解析单行 JSONL |
applySpecStreamPatch | 将补丁应用于对象 |
StateStore | 用于插入外部状态管理的接口 |
ComputedFunction | $computed 表达式的函数签名 |
check | 用于创建验证检查的 TypeScript 辅助函数 |
BuiltInAction | 内置操作定义的类型(name + description) |
ActionBinding | 操作绑定类型(包含 preventDefault 字段) |
每周安装量
449
代码仓库
GitHub 星标数
13.3K
首次出现
2026年3月7日
安全审计
安装于
codex442
opencode436
cursor436
kimi-cli435
gemini-cli435
github-copilot435
Core package for schema definition, catalog creation, and spec streaming.
defineSchema)defineCatalog)import { defineSchema } from "@json-render/core";
export const schema = defineSchema((s) => ({
spec: s.object({
// Define spec structure
}),
catalog: s.object({
components: s.map({
props: s.zod(),
description: s.string(),
}),
}),
}), {
promptTemplate: myPromptTemplate, // Optional custom AI prompt
});
import { defineCatalog } from "@json-render/core";
import { schema } from "./schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Button: {
props: z.object({
label: z.string(),
variant: z.enum(["primary", "secondary"]).nullable(),
}),
description: "Clickable button component",
},
},
});
const systemPrompt = catalog.prompt(); // Uses schema's promptTemplate
const systemPrompt = catalog.prompt({ customRules: ["Rule 1", "Rule 2"] });
For streaming AI responses (JSONL patches):
import { createSpecStreamCompiler } from "@json-render/core";
const compiler = createSpecStreamCompiler<MySpec>();
// Process streaming chunks
const { result, newPatches } = compiler.push(chunk);
// Get final result
const finalSpec = compiler.getResult();
Any prop value can be a dynamic expression resolved at render time:
{ "$state": "/state/key" } - reads a value from the state model (one-way read){ "$bindState": "/path" } - two-way binding: reads from state and enables write-back. Use on the natural value prop (value, checked, pressed, etc.) of form components.{ "$bindItem": "field" } - two-way binding to a repeat item field. Use inside repeat scopes.{ "$cond":<condition>, "$then": <value>, "$else": <value> } - evaluates a visibility condition and picks a branch{ "$template": "Hello, ${/user/name}!" } - interpolates ${/path} references with state values{ "$computed": "fnName", "args": { "key":<expression> } } - calls a registered function with resolved args$cond uses the same syntax as visibility conditions ($state, eq, neq, not, arrays for AND). $then and $else can themselves be expressions (recursive).
Components do not use a statePath prop for two-way binding. Instead, use { "$bindState": "/path" } on the natural value prop (e.g. value, checked, pressed).
{
"color": {
"$cond": { "$state": "/activeTab", "eq": "home" },
"$then": "#007AFF",
"$else": "#8E8E93"
},
"label": { "$template": "Welcome, ${/user/name}!" },
"fullName": {
"$computed": "fullName",
"args": {
"first": { "$state": "/form/firstName" },
"last": { "$state": "/form/lastName" }
}
}
}
import { resolvePropValue, resolveElementProps } from "@json-render/core";
const resolved = resolveElementProps(element.props, { stateModel: myState });
Elements can declare a watch field (top-level, sibling of type/props/children) to trigger actions when state values change:
{
"type": "Select",
"props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
"watch": {
"/form/country": { "action": "loadCities", "params": { "country": { "$state": "/form/country" } } }
},
"children": []
}
Watchers only fire on value changes, not on initial render.
Built-in validation functions: required, email, url, numeric, minLength, maxLength, min, max, pattern, matches, equalTo, lessThan, , .
Cross-field validation uses $state expressions in args:
import { check } from "@json-render/core";
check.required("Field is required");
check.matches("/form/password", "Passwords must match");
check.lessThan("/form/endDate", "Must be before end date");
check.greaterThan("/form/startDate", "Must be after start date");
check.requiredIf("/form/enableNotifications", "Required when enabled");
Build structured user prompts with optional spec refinement and state context:
import { buildUserPrompt } from "@json-render/core";
// Fresh generation
buildUserPrompt({ prompt: "create a todo app" });
// Refinement with edit modes (default: patch-only)
buildUserPrompt({ prompt: "add a toggle", currentSpec: spec, editModes: ["patch", "merge"] });
// With runtime state
buildUserPrompt({ prompt: "show data", state: { todos: [] } });
Available edit modes: "patch" (RFC 6902 JSON Patch), "merge" (RFC 7396 Merge Patch), "diff" (unified diff).
Validate spec structure and auto-fix common issues:
import { validateSpec, autoFixSpec } from "@json-render/core";
const { valid, issues } = validateSpec(spec);
const fixed = autoFixSpec(spec);
Control element visibility with state-based conditions. VisibilityContext is { stateModel: StateModel }.
import { visibility } from "@json-render/core";
// Syntax
{ "$state": "/path" } // truthiness
{ "$state": "/path", "not": true } // falsy
{ "$state": "/path", "eq": value } // equality
[ cond1, cond2 ] // implicit AND
// Helpers
visibility.when("/path") // { $state: "/path" }
visibility.unless("/path") // { $state: "/path", not: true }
visibility.eq("/path", val) // { $state: "/path", eq: val }
visibility.and(cond1, cond2) // { $and: [cond1, cond2] }
visibility.or(cond1, cond2) // { $or: [cond1, cond2] }
visibility.always // true
visibility.never // false
Schemas can declare builtInActions -- actions that are always available at runtime and auto-injected into prompts:
const schema = defineSchema(builder, {
builtInActions: [
{ name: "setState", description: "Update a value in the state model" },
],
});
These appear in prompts as [built-in] and don't require handlers in defineRegistry.
The StateStore interface allows external state management libraries (Redux, Zustand, XState, etc.) to be plugged into json-render renderers. The createStateStore factory creates a simple in-memory implementation:
import { createStateStore, type StateStore } from "@json-render/core";
const store = createStateStore({ count: 0 });
store.get("/count"); // 0
store.set("/count", 1); // updates and notifies subscribers
store.update({ "/a": 1, "/b": 2 }); // batch update
store.subscribe(() => {
console.log(store.getSnapshot()); // { count: 1 }
});
The StateStore interface: get(path), set(path, value), update(updates), getSnapshot(), subscribe(listener).
| Export | Purpose |
|---|---|
defineSchema | Create a new schema |
defineCatalog | Create a catalog from schema |
createStateStore | Create a framework-agnostic in-memory StateStore |
resolvePropValue | Resolve a single prop expression against data |
resolveElementProps | Resolve all prop expressions in an element |
Weekly Installs
449
Repository
GitHub Stars
13.3K
First Seen
Mar 7, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex442
opencode436
cursor436
kimi-cli435
gemini-cli435
github-copilot435
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
103,800 周安装
专业咨询分析技能:AI生成麦肯锡级研究报告,支持市场分析、财务分析、行业研究
430 周安装
Gemini CLI 更新日志自动化流程指南 | 技术文档版本管理最佳实践
430 周安装
tsdown - 基于Rolldown的极速TypeScript/JavaScript库打包工具,支持ESM/CJS/IIFE/UMD
430 周安装
PDF OCR技能:双引擎文字提取,支持影印PDF和图片识别
430 周安装
MUI v7 使用指南:组件样式、主题定制与响应式设计模式详解
431 周安装
HubSpot CRM 集成指南:使用 Membrane CLI 自动化销售、营销与客户服务
431 周安装
greaterThanrequiredIfbuildUserPrompt| Build user prompts with refinement and state context |
buildEditUserPrompt | Build user prompt for editing existing specs |
buildEditInstructions | Generate prompt section for available edit modes |
isNonEmptySpec | Check if spec has root and at least one element |
deepMergeSpec | RFC 7396 deep merge (null deletes, arrays replace, objects recurse) |
diffToPatches | Generate RFC 6902 JSON Patch operations from object diff |
EditMode | Type: `"patch" |
validateSpec | Validate spec structure |
autoFixSpec | Auto-fix common spec issues |
createSpecStreamCompiler | Stream JSONL patches into spec |
createJsonRenderTransform | TransformStream separating text from JSONL in mixed streams |
parseSpecStreamLine | Parse single JSONL line |
applySpecStreamPatch | Apply patch to object |
StateStore | Interface for plugging in external state management |
ComputedFunction | Function signature for $computed expressions |
check | TypeScript helpers for creating validation checks |
BuiltInAction | Type for built-in action definitions (name + description) |
ActionBinding | Action binding type (includes preventDefault field) |