核心套件,用於定義 json-render 的 schema、catalog 和 AI 提示生成。當使用 @json-render/core、定義 schema、建立 catalog 或建構用於 UI/影片生成的 JSON spec 時使用。
@json-render/core
核心套件,用於 schema 定義、catalog 建立和 spec 串流。
關鍵概念
- Schema:定義 spec 和 catalog 的結構(使用
defineSchema) - Catalog:將元件/動作名稱對應到其定義(使用
defineCatalog) - Spec:AI 輸出且符合 schema 的 JSON
- SpecStream:用於逐步建構 spec 的 JSONL 串流格式
定義 Schema
import { defineSchema } from "@json-render/core";
export const schema = defineSchema((s) => ({
spec: s.object({
// 定義 spec 結構
}),
catalog: s.object({
components: s.map({
props: s.zod(),
description: s.string(),
}),
}),
}), {
promptTemplate: myPromptTemplate, // 可選的自訂 AI 提示
});
建立 Catalog
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(); // 使用 schema 的 promptTemplate
const systemPrompt = catalog.prompt({ customRules: ["規則 1", "規則 2"] });
SpecStream 工具
用於串流 AI 回應(JSONL 修補):
import { createSpecStreamCompiler } from "@json-render/core";
const compiler = createSpecStreamCompiler<MySpec>();
// 處理串流區塊
const { result, newPatches } = compiler.push(chunk);
// 取得最終結果
const finalSpec = compiler.getResult();
動態 Prop 表達式
任何 prop 值都可以是動態表達式,在渲染時解析:
{ "$state": "/state/key" }- 從狀態模型讀取值(單向讀取){ "$bindState": "/path" }- 雙向綁定:從狀態讀取並允許寫回。用於表單元件的自然值 prop(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 prop 進行雙向綁定。請改用 { "$bindState": "/path" } 放在自然值 prop(例如 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 });
狀態監聽器
元素可以宣告 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", "啟用時為必填");
使用者提示建構器
建構結構化的使用者提示,可選的 spec 精煉和狀態上下文:
import { buildUserPrompt } from "@json-render/core";
// 全新生成
buildUserPrompt({ prompt: "建立一個待辦事項應用" });
// 精煉,使用編輯模式(預設:僅 patch)
buildUserPrompt({ prompt: "新增一個切換開關", currentSpec: spec, editModes: ["patch", "merge"] });
// 包含執行時期狀態
buildUserPrompt({ prompt: "顯示資料", state: { todos: [] } });
可用的編輯模式:"patch"(RFC 6902 JSON Patch)、"merge"(RFC 7396 Merge Patch)、"diff"(統一 diff)。
Spec 驗證
驗證 spec 結構並自動修復常見問題:
import { validateSpec, autoFixSpec } from "@json-render/core";
const { valid, issues } = validateSpec(spec);
// issues 包含:missing_child、invalid_visible(格式錯誤的條件)、
// repeat_without_children、repeat_state_mismatch(statePath 在狀態中不是陣列)
const { spec: fixed, fixDetails } = autoFixSpec(spec);
// fixDetails 項目為 { message, lossy }。無損修復會重新放置錯置的欄位;
// 有損修復會修剪懸空的子元素參考。
// 在修復迴圈中,應保留有損修復直到重試耗盡:
const attempt = autoFixSpec(spec, { lossy: retriesExhausted });
可見性條件
使用基於狀態的條件控制元素可見性。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
Schema 中的內建動作
Schema 可以宣告 builtInActions——這些動作在執行時期始終可用,並會自動注入到提示中:
const schema = defineSchema(builder, {
builtInActions: [
{ name: "setState", description: "更新狀態模型中的值" },
],
});
這些動作在提示中顯示為 [built-in],且不需要在 defineRegistry 中定義處理器。
StateStore
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 |
建立新的 schema |
defineCatalog |
從 schema 建立 catalog |
createStateStore |
建立框架無關的記憶體內 StateStore |
resolvePropValue |
根據資料解析單一 prop 表達式 |
resolveElementProps |
解析元素中所有 prop 表達式 |
buildUserPrompt |
建構使用者提示,包含精煉和狀態上下文 |
buildEditUserPrompt |
建構用於編輯現有 spec 的使用者提示 |
buildEditInstructions |
生成可用編輯模式的提示區段 |
isNonEmptySpec |
檢查 spec 是否有根節點且至少一個元素 |
deepMergeSpec |
RFC 7396 深度合併(null 刪除、陣列取代、物件遞迴) |
diffToPatches |
從物件差異生成 RFC 6902 JSON Patch 操作 |
EditMode |
型別:"patch" | "merge" | "diff" |
validateSpec |
驗證 spec 結構 |
autoFixSpec |
自動修復常見 spec 問題;將修復分類為有損/無損,{ lossy: false } 會保留修剪 |
createSpecStreamCompiler |
將 JSONL 修補串流編譯為 spec |
createJsonRenderTransform |
TransformStream,從混合串流中分離文字和 JSONL |
parseSpecStreamLine |
解析單行 JSONL |
applySpecStreamPatch |
將修補套用到物件 |
StateStore |
用於插入外部狀態管理的介面 |
ComputedFunction |
$computed 表達式的函式簽名 |
check |
用於建立驗證檢查的 TypeScript 輔助函式 |
BuiltInAction |
內建動作定義的型別(name + description) |
ActionBinding |
動作綁定型別(包含 preventDefault 欄位) |






