@wevu/json-render 0.0.0 → 0.1.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/dist/catalog.mjs.map +1 -1
- package/dist/compat.mjs.map +1 -1
- package/dist/path.mjs.map +1 -1
- package/dist/projection.mjs.map +1 -1
- package/dist/renderer.mjs.map +1 -1
- package/dist/resolver.mjs.map +1 -1
- package/dist/stream.mjs.map +1 -1
- package/dist/useRenderer.mjs.map +1 -1
- package/dist/validation.mjs.map +1 -1
- package/package.json +4 -4
package/dist/catalog.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.mjs","names":[],"sources":["../src/catalog.ts"],"sourcesContent":["import type { RendererCatalog } from './types'\nimport { z } from 'zod'\nimport './compat'\n\n/** 保留组件、动作及其参数 schema 的类型推导。 */\nexport function defineRendererCatalog<const C extends RendererCatalog>(catalog: C): C {\n return catalog\n}\n\nexport const standardComponents = {\n Stack: { props: z.object({}).strict(), container: true },\n Card: { props: z.object({ title: z.string() }).strict(), container: true },\n Text: { props: z.object({ text: z.string() }).strict() },\n Input: {\n props: z.object({ label: z.string(), placeholder: z.string(), value: z.string() }).strict(),\n events: ['input'],\n bindings: { value: 'input' },\n },\n Button: {\n props: z.object({ label: z.string(), disabled: z.boolean().optional() }).strict(),\n events: ['press'],\n },\n} as const\n"],"mappings":"6CAKA,
|
|
1
|
+
{"version":3,"file":"catalog.mjs","names":["defineRendererCatalog","catalog","standardComponents","z"],"sources":["../src/catalog.ts"],"sourcesContent":["import type { RendererCatalog } from './types'\nimport { z } from 'zod'\nimport './compat'\n\n/** 保留组件、动作及其参数 schema 的类型推导。 */\nexport function defineRendererCatalog<const C extends RendererCatalog>(catalog: C): C {\n return catalog\n}\n\nexport const standardComponents = {\n Stack: { props: z.object({}).strict(), container: true },\n Card: { props: z.object({ title: z.string() }).strict(), container: true },\n Text: { props: z.object({ text: z.string() }).strict() },\n Input: {\n props: z.object({ label: z.string(), placeholder: z.string(), value: z.string() }).strict(),\n events: ['input'],\n bindings: { value: 'input' },\n },\n Button: {\n props: z.object({ label: z.string(), disabled: z.boolean().optional() }).strict(),\n events: ['press'],\n },\n} as const\n"],"mappings":"6CAKA,SAAgBA,EAAuD,EAAe,CACpF,OAAOC,CACT,CAEA,MAAaC,EAAqB,CAChC,MAAO,CAAE,MAAOC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAG,UAAW,EAAK,EACvD,KAAM,CAAE,MAAOA,EAAE,OAAO,CAAE,MAAOA,EAAE,OAAO,CAAE,CAAC,CAAC,CAAC,OAAO,EAAG,UAAW,EAAK,EACzE,KAAM,CAAE,MAAOA,EAAE,OAAO,CAAE,KAAMA,EAAE,OAAO,CAAE,CAAC,CAAC,CAAC,OAAO,CAAE,EACvD,MAAO,CACL,MAAOA,EAAE,OAAO,CAAE,MAAOA,EAAE,OAAO,EAAG,YAAaA,EAAE,OAAO,EAAG,MAAOA,EAAE,OAAO,CAAE,CAAC,CAAC,CAAC,OAAO,EAC1F,OAAQ,CAAC,OAAO,EAChB,SAAU,CAAE,MAAO,OAAQ,CAC7B,EACA,OAAQ,CACN,MAAOA,EAAE,OAAO,CAAE,MAAOA,EAAE,OAAO,EAAG,SAAUA,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAE,CAAC,CAAC,CAAC,OAAO,EAChF,OAAQ,CAAC,OAAO,CAClB,CACF"}
|
package/dist/compat.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compat.mjs","names":[],"sources":["../src/compat.ts"],"sourcesContent":["import { z } from 'zod'\n\n// 必须先于 Core 的模块初始化执行,避免 Zod 构造 schema 时探测动态求值。\nz.config({ jitless: true })\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"compat.mjs","names":["z"],"sources":["../src/compat.ts"],"sourcesContent":["import { z } from 'zod'\n\n// 必须先于 Core 的模块初始化执行,避免 Zod 构造 schema 时探测动态求值。\nz.config({ jitless: true })\n"],"mappings":"wBAGAA,EAAE,OAAO,CAAE,QAAS,EAAK,CAAC"}
|
package/dist/path.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.mjs","names":[],"sources":["../src/path.ts"],"sourcesContent":["import type { JsonValue } from './types'\n\n/** 解析 JSON Pointer,拒绝原型链键及不规范的转义。 */\nexport function parsePointer(path: string) {\n if (!path.startsWith('/') || /~(?![01])/u.test(path)) {\n throw new Error(`无效的 JSON Pointer:${path}`)\n }\n const parts = path.slice(1).split('/').map(part => part.replace(/~1/g, '/').replace(/~0/g, '~'))\n if (parts.some(part => ['__proto__', 'prototype', 'constructor'].includes(part))) {\n throw new Error('路径不能包含原型链键')\n }\n return parts\n}\n\nexport function readState(state: object, path: string): unknown {\n let current: unknown = state\n for (const part of parsePointer(path)) {\n if (Array.isArray(current) && !/^(?:0|[1-9]\\d*)$/.test(part)) {\n throw new Error(`数组路径必须使用索引:${path}`)\n }\n if (!current || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, part)) {\n throw new Error(`状态路径不存在:${path}`)\n }\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\n/** 在进入宿主数据层之前拒绝函数、循环、非有限数及非普通对象。 */\nexport function assertJson(value: unknown, ancestors = new Set<object>()): asserts value is JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') {\n return\n }\n if (typeof value === 'number' && Number.isFinite(value)) {\n return\n }\n if (!value || typeof value !== 'object' || ancestors.has(value)) {\n throw new Error('值必须是可序列化的 JSON 数据')\n }\n const prototype = Object.getPrototypeOf(value)\n if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {\n throw new Error('值必须是普通 JSON 对象')\n }\n const next = new Set(ancestors).add(value)\n for (const child of Object.values(value)) {\n assertJson(child, next)\n }\n}\n\nexport function cloneJson<T>(value: T): T {\n assertJson(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nexport function writeState(state: object, path: string, value: JsonValue) {\n readState(state, path)\n const parts = parsePointer(path)\n let parent = state as Record<string, unknown>\n for (const part of parts.slice(0, -1)) {\n parent = parent[part] as Record<string, unknown>\n }\n parent[parts[parts.length - 1]!] = cloneJson(value)\n}\n"],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"path.mjs","names":["parsePointer","path","parts","part","readState","current","state","assertJson","value","ancestors","prototype","next","child","cloneJson","writeState","parent"],"sources":["../src/path.ts"],"sourcesContent":["import type { JsonValue } from './types'\n\n/** 解析 JSON Pointer,拒绝原型链键及不规范的转义。 */\nexport function parsePointer(path: string) {\n if (!path.startsWith('/') || /~(?![01])/u.test(path)) {\n throw new Error(`无效的 JSON Pointer:${path}`)\n }\n const parts = path.slice(1).split('/').map(part => part.replace(/~1/g, '/').replace(/~0/g, '~'))\n if (parts.some(part => ['__proto__', 'prototype', 'constructor'].includes(part))) {\n throw new Error('路径不能包含原型链键')\n }\n return parts\n}\n\nexport function readState(state: object, path: string): unknown {\n let current: unknown = state\n for (const part of parsePointer(path)) {\n if (Array.isArray(current) && !/^(?:0|[1-9]\\d*)$/.test(part)) {\n throw new Error(`数组路径必须使用索引:${path}`)\n }\n if (!current || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, part)) {\n throw new Error(`状态路径不存在:${path}`)\n }\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\n/** 在进入宿主数据层之前拒绝函数、循环、非有限数及非普通对象。 */\nexport function assertJson(value: unknown, ancestors = new Set<object>()): asserts value is JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') {\n return\n }\n if (typeof value === 'number' && Number.isFinite(value)) {\n return\n }\n if (!value || typeof value !== 'object' || ancestors.has(value)) {\n throw new Error('值必须是可序列化的 JSON 数据')\n }\n const prototype = Object.getPrototypeOf(value)\n if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {\n throw new Error('值必须是普通 JSON 对象')\n }\n const next = new Set(ancestors).add(value)\n for (const child of Object.values(value)) {\n assertJson(child, next)\n }\n}\n\nexport function cloneJson<T>(value: T): T {\n assertJson(value)\n return JSON.parse(JSON.stringify(value)) as T\n}\n\nexport function writeState(state: object, path: string, value: JsonValue) {\n readState(state, path)\n const parts = parsePointer(path)\n let parent = state as Record<string, unknown>\n for (const part of parts.slice(0, -1)) {\n parent = parent[part] as Record<string, unknown>\n }\n parent[parts[parts.length - 1]!] = cloneJson(value)\n}\n"],"mappings":"AAGA,SAAgBA,EAAa,EAAc,CACzC,GAAI,CAACC,EAAK,WAAW,GAAG,GAAK,aAAa,KAAKA,CAAI,EACjD,MAAU,MAAM,oBAAoBA,GAAM,EAE5C,IAAMC,EAAQD,EAAK,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,GAAQE,EAAK,QAAQ,MAAO,GAAG,CAAC,CAAC,QAAQ,MAAO,GAAG,CAAC,EAC/F,GAAID,EAAM,KAAK,GAAQ,CAAC,YAAa,YAAa,aAAa,CAAC,CAAC,SAASC,CAAI,CAAC,EAC7E,MAAU,MAAM,YAAY,EAE9B,OAAOD,CACT,CAEA,SAAgBE,EAAU,EAAe,EAAuB,CAC9D,IAAIC,EAAmBC,EACvB,IAAK,IAAMH,KAAQH,EAAaC,CAAI,EAAG,CACrC,GAAI,MAAM,QAAQI,CAAO,GAAK,CAAC,mBAAmB,KAAKF,CAAI,EACzD,MAAU,MAAM,cAAcF,GAAM,EAEtC,GAAI,CAACI,GAAW,OAAOA,GAAY,UAAY,CAAC,OAAO,UAAU,eAAe,KAAKA,EAASF,CAAI,EAChG,MAAU,MAAM,WAAWF,GAAM,EAEnC,EAAWI,EAAoCF,EACjD,CACA,OAAOE,CACT,CAGA,SAAgBE,EAAW,EAAgB,kBAAY,IAAI,IAA2C,CAIpG,GAHIC,IAAU,MAAQ,OAAOA,GAAU,UAAY,OAAOA,GAAU,WAGhE,OAAOA,GAAU,UAAY,OAAO,SAASA,CAAK,EACpD,OAEF,GAAI,CAACA,GAAS,OAAOA,GAAU,UAAYC,EAAU,IAAID,CAAK,EAC5D,MAAU,MAAM,mBAAmB,EAErC,IAAME,EAAY,OAAO,eAAeF,CAAK,EAC7C,GAAI,CAAC,MAAM,QAAQA,CAAK,GAAKE,IAAc,OAAO,WAAaA,IAAc,KAC3E,MAAU,MAAM,gBAAgB,EAElC,IAAMC,EAAO,IAAI,IAAIF,CAAS,CAAC,CAAC,IAAID,CAAK,EACzC,IAAK,IAAMI,KAAS,OAAO,OAAOJ,CAAK,EACrCD,EAAWK,EAAOD,CAAI,CAE1B,CAEA,SAAgBE,EAAa,EAAa,CAExC,OADAN,EAAWC,CAAK,EACT,KAAK,MAAM,KAAK,UAAUA,CAAK,CAAC,CACzC,CAEA,SAAgBM,EAAW,EAAe,EAAc,EAAkB,CACxEV,EAAUE,EAAOL,CAAI,EACrB,IAAMC,EAAQF,EAAaC,CAAI,EAC3Bc,EAAST,EACb,IAAK,IAAMH,KAAQD,EAAM,MAAM,EAAG,EAAE,EAClC,EAASa,EAAOZ,GAElB,EAAOD,EAAMA,EAAM,OAAS,IAAOW,EAAUL,CAAK,CACpD"}
|
package/dist/projection.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection.mjs","names":[],"sources":["../src/projection.ts"],"sourcesContent":["import type { RendererCatalog, RendererSpec, RenderNode } from './types'\nimport { evaluateVisibility } from './core'\nimport { resolveProps } from './validation'\n\nexport function projectRendererSpec(spec: RendererSpec, catalog: RendererCatalog, state: object): RenderNode | null {\n function project(id: string): RenderNode | null {\n const node = spec.elements[id]!\n if (!evaluateVisibility(node.visible, { stateModel: state as Record<string, unknown> })) {\n return null\n }\n return {\n id,\n type: node.type,\n props: resolveProps(node, catalog, state),\n children: (node.children ?? []).map(project).filter((child): child is RenderNode => child !== null),\n }\n }\n return project(spec.root)\n}\n\nexport function findRenderNode(tree: RenderNode | null, id: string): RenderNode | undefined {\n if (!tree) {\n return undefined\n }\n if (tree.id === id) {\n return tree\n }\n for (const child of tree.children) {\n const found = findRenderNode(child, id)\n if (found) {\n return found\n }\n }\n}\n"],"mappings":"gGAIA,
|
|
1
|
+
{"version":3,"file":"projection.mjs","names":["projectRendererSpec","project","_node$children","node","spec","id","evaluateVisibility","state","resolveProps","catalog","child","findRenderNode","tree","found"],"sources":["../src/projection.ts"],"sourcesContent":["import type { RendererCatalog, RendererSpec, RenderNode } from './types'\nimport { evaluateVisibility } from './core'\nimport { resolveProps } from './validation'\n\nexport function projectRendererSpec(spec: RendererSpec, catalog: RendererCatalog, state: object): RenderNode | null {\n function project(id: string): RenderNode | null {\n const node = spec.elements[id]!\n if (!evaluateVisibility(node.visible, { stateModel: state as Record<string, unknown> })) {\n return null\n }\n return {\n id,\n type: node.type,\n props: resolveProps(node, catalog, state),\n children: (node.children ?? []).map(project).filter((child): child is RenderNode => child !== null),\n }\n }\n return project(spec.root)\n}\n\nexport function findRenderNode(tree: RenderNode | null, id: string): RenderNode | undefined {\n if (!tree) {\n return undefined\n }\n if (tree.id === id) {\n return tree\n }\n for (const child of tree.children) {\n const found = findRenderNode(child, id)\n if (found) {\n return found\n }\n }\n}\n"],"mappings":"gGAIA,SAAgBA,EAAoB,EAAoB,EAA0B,EAAkC,CAClH,SAASC,EAAQ,EAA+B,OAC9C,IAAME,EAAOC,EAAK,SAASC,GAI3B,OAHKC,EAAmBH,EAAK,QAAS,CAAE,WAAYI,CAAiC,CAAC,EAG/E,CACL,KACA,KAAMJ,EAAK,KACX,MAAOK,EAAaL,EAAMM,EAASF,CAAK,EACxC,WAAA,EAAWJ,EAAK,WAAA,KAAY,CAAC,EAAbD,EAAa,CAAG,IAAID,CAAO,CAAC,CAAC,OAAQ,GAA+BS,IAAU,IAAI,CACpG,EAPS,IAQX,CACA,OAAOT,EAAQG,EAAK,IAAI,CAC1B,CAEA,SAAgBO,EAAe,EAAyB,EAAoC,CAC1F,GAAKC,EAGL,IAAIA,EAAK,KAAOP,EACd,OAAOO,EAET,IAAK,IAAMF,KAASE,EAAK,SAAU,CACjC,IAAMC,EAAQF,EAAeD,EAAOL,CAAE,EACtC,GAAIQ,EACF,OAAOA,CAEX,CAPS,CAQX"}
|
package/dist/renderer.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.mjs","names":[],"sources":["../src/renderer.ts"],"sourcesContent":["import type { ActionContext, CatalogSpec, JsonValue, RendererCatalog, RendererEvent, RendererOptions, RendererSpec } from './types'\nimport { computed, reactive, shallowRef } from 'wevu'\nimport { resolveBindings, resolveElementProps } from './core'\nimport { cloneJson, writeState } from './path'\nimport { findRenderNode, projectRendererSpec } from './projection'\nimport { createSpecStream } from './stream'\nimport { validateRendererSpec } from './validation'\n\n/** 创建与页面生命周期解耦的渲染会话;动作只通过上下文提交有效状态更新。 */\nexport function createJsonRenderer<C extends RendererCatalog, State extends object>(options: RendererOptions<C, State>) {\n const state = reactive(cloneJson(options.initialState)) as State\n const spec = shallowRef<RendererSpec>(validateRendererSpec(options.spec, options.catalog, state, options.limits).spec)\n const error = shallowRef<string | null>(null)\n const pending = shallowRef<string[]>([])\n const tree = computed(() => projectRendererSpec(spec.value, options.catalog, state))\n let disposed = false\n let generation = 0\n let streamGeneration = 0\n let currentStream: ReturnType<typeof createSpecStream> | undefined\n const cleanups = new Set<() => void>()\n\n function report(reason: unknown) {\n error.value = reason instanceof Error ? reason.message : String(reason)\n }\n\n function cancel() {\n generation++\n streamGeneration++\n currentStream?.dispose()\n currentStream = undefined\n for (const cleanup of [...cleanups]) {\n try {\n cleanup()\n }\n catch (reason) {\n report(reason)\n }\n }\n cleanups.clear()\n pending.value = []\n }\n\n function setState(path: string, value: JsonValue) {\n if (disposed) {\n return\n }\n const draft = cloneJson(state)\n writeState(draft, path, value)\n // 同时验证投影,拒绝导致宿主 props 类型不匹配的状态更新。\n projectRendererSpec(spec.value, options.catalog, draft)\n writeState(state, path, value)\n }\n\n function load(input: unknown, nextState?: State) {\n if (disposed) {\n return false\n }\n try {\n const draftState = cloneJson(nextState ?? state)\n const checked = validateRendererSpec(input, options.catalog, draftState, options.limits)\n cancel()\n if (nextState) {\n for (const key of Object.keys(state)) {\n Reflect.deleteProperty(state, key)\n }\n Object.assign(state, draftState)\n }\n spec.value = checked.spec\n error.value = null\n return true\n }\n catch (reason) {\n report(reason)\n return false\n }\n }\n\n async function dispatch(event: RendererEvent): Promise<boolean> {\n if (disposed || !findRenderNode(tree.value, event.id)) {\n return false\n }\n const node = spec.value.elements[event.id]!\n const definition = options.catalog.components[node.type]!\n if (!definition.events?.includes(event.name)) {\n return false\n }\n try {\n const bindings = resolveBindings(node.props, { stateModel: state as Record<string, unknown> })\n for (const [prop, name] of Object.entries(definition.bindings ?? {})) {\n if (name === event.name && bindings?.[prop]) {\n if (event.value === undefined) {\n throw new Error(`绑定事件缺少 value:${event.name}`)\n }\n setState(bindings[prop], event.value)\n }\n }\n const binding = node.on?.[event.name]\n if (!binding) {\n return true\n }\n const key = `${event.id}:${binding.action}`\n if (pending.value.includes(key)) {\n return false\n }\n const handler = options.actions[binding.action]\n if (!Object.prototype.hasOwnProperty.call(options.actions, binding.action) || typeof handler !== 'function') {\n throw new TypeError(`动作缺少处理器:${binding.action}`)\n }\n const params = options.catalog.actions[binding.action]!.parse(resolveElementProps(binding.params ?? {}, { stateModel: state as Record<string, unknown> }))\n const ownGeneration = generation\n const isActive = () => !disposed && generation === ownGeneration\n const actionCleanups = new Set<() => void>()\n const context: ActionContext<State> = {\n state,\n event,\n isActive,\n setState(path, value) {\n if (isActive()) {\n setState(path, value)\n }\n },\n onCleanup(cleanup) {\n if (isActive()) {\n cleanups.add(cleanup)\n actionCleanups.add(cleanup)\n }\n else {\n cleanup()\n }\n },\n }\n pending.value = [...pending.value, key]\n error.value = null\n try {\n await handler(params as Parameters<typeof handler>[0], context)\n return isActive()\n }\n catch (reason) {\n if (isActive()) {\n report(reason)\n }\n return false\n }\n finally {\n for (const cleanup of actionCleanups) {\n if (cleanups.delete(cleanup)) {\n try {\n cleanup()\n }\n catch (reason) {\n report(reason)\n }\n }\n }\n if (isActive()) {\n pending.value = pending.value.filter(item => item !== key)\n }\n }\n }\n catch (reason) {\n report(reason)\n return false\n }\n }\n\n function createStream(initialSpec?: CatalogSpec<C>) {\n const initial = validateRendererSpec(initialSpec ?? spec.value, options.catalog, state, options.limits).spec\n const stream = createSpecStream(initial, options.catalog, state, options.limits)\n currentStream?.dispose()\n const ownGeneration = ++streamGeneration\n spec.value = initial\n currentStream = stream\n error.value = null\n return {\n push(chunk: string, done = false) {\n if (disposed || ownGeneration !== streamGeneration) {\n return false\n }\n try {\n const next = stream.push(chunk, done)\n if (next) {\n spec.value = next\n }\n return next !== null\n }\n catch (reason) {\n report(reason)\n return false\n }\n },\n dispose: () => stream.dispose(),\n }\n }\n\n return {\n state,\n spec,\n tree,\n error,\n pending,\n setState,\n load,\n dispatch,\n createStream,\n dispose() {\n if (!disposed) {\n disposed = true\n cancel()\n }\n },\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"renderer.mjs","names":["createJsonRenderer","state","reactive","cloneJson","options","spec","shallowRef","validateRendererSpec","error","pending","tree","computed","projectRendererSpec","disposed","generation","streamGeneration","currentStream","cleanups","report","reason","cancel","cleanup","setState","draft","writeState","path","value","load","draftState","nextState","checked","input","key","dispatch","_definition$events","findRenderNode","event","node","definition","_definition$bindings","_node$on","_binding$params","bindings","resolveBindings","prop","name","binding","handler","params","resolveElementProps","ownGeneration","isActive","actionCleanups","context","item","createStream","initial","initialSpec","stream","createSpecStream","next","chunk","done"],"sources":["../src/renderer.ts"],"sourcesContent":["import type { ActionContext, CatalogSpec, JsonValue, RendererCatalog, RendererEvent, RendererOptions, RendererSpec } from './types'\nimport { computed, reactive, shallowRef } from 'wevu'\nimport { resolveBindings, resolveElementProps } from './core'\nimport { cloneJson, writeState } from './path'\nimport { findRenderNode, projectRendererSpec } from './projection'\nimport { createSpecStream } from './stream'\nimport { validateRendererSpec } from './validation'\n\n/** 创建与页面生命周期解耦的渲染会话;动作只通过上下文提交有效状态更新。 */\nexport function createJsonRenderer<C extends RendererCatalog, State extends object>(options: RendererOptions<C, State>) {\n const state = reactive(cloneJson(options.initialState)) as State\n const spec = shallowRef<RendererSpec>(validateRendererSpec(options.spec, options.catalog, state, options.limits).spec)\n const error = shallowRef<string | null>(null)\n const pending = shallowRef<string[]>([])\n const tree = computed(() => projectRendererSpec(spec.value, options.catalog, state))\n let disposed = false\n let generation = 0\n let streamGeneration = 0\n let currentStream: ReturnType<typeof createSpecStream> | undefined\n const cleanups = new Set<() => void>()\n\n function report(reason: unknown) {\n error.value = reason instanceof Error ? reason.message : String(reason)\n }\n\n function cancel() {\n generation++\n streamGeneration++\n currentStream?.dispose()\n currentStream = undefined\n for (const cleanup of [...cleanups]) {\n try {\n cleanup()\n }\n catch (reason) {\n report(reason)\n }\n }\n cleanups.clear()\n pending.value = []\n }\n\n function setState(path: string, value: JsonValue) {\n if (disposed) {\n return\n }\n const draft = cloneJson(state)\n writeState(draft, path, value)\n // 同时验证投影,拒绝导致宿主 props 类型不匹配的状态更新。\n projectRendererSpec(spec.value, options.catalog, draft)\n writeState(state, path, value)\n }\n\n function load(input: unknown, nextState?: State) {\n if (disposed) {\n return false\n }\n try {\n const draftState = cloneJson(nextState ?? state)\n const checked = validateRendererSpec(input, options.catalog, draftState, options.limits)\n cancel()\n if (nextState) {\n for (const key of Object.keys(state)) {\n Reflect.deleteProperty(state, key)\n }\n Object.assign(state, draftState)\n }\n spec.value = checked.spec\n error.value = null\n return true\n }\n catch (reason) {\n report(reason)\n return false\n }\n }\n\n async function dispatch(event: RendererEvent): Promise<boolean> {\n if (disposed || !findRenderNode(tree.value, event.id)) {\n return false\n }\n const node = spec.value.elements[event.id]!\n const definition = options.catalog.components[node.type]!\n if (!definition.events?.includes(event.name)) {\n return false\n }\n try {\n const bindings = resolveBindings(node.props, { stateModel: state as Record<string, unknown> })\n for (const [prop, name] of Object.entries(definition.bindings ?? {})) {\n if (name === event.name && bindings?.[prop]) {\n if (event.value === undefined) {\n throw new Error(`绑定事件缺少 value:${event.name}`)\n }\n setState(bindings[prop], event.value)\n }\n }\n const binding = node.on?.[event.name]\n if (!binding) {\n return true\n }\n const key = `${event.id}:${binding.action}`\n if (pending.value.includes(key)) {\n return false\n }\n const handler = options.actions[binding.action]\n if (!Object.prototype.hasOwnProperty.call(options.actions, binding.action) || typeof handler !== 'function') {\n throw new TypeError(`动作缺少处理器:${binding.action}`)\n }\n const params = options.catalog.actions[binding.action]!.parse(resolveElementProps(binding.params ?? {}, { stateModel: state as Record<string, unknown> }))\n const ownGeneration = generation\n const isActive = () => !disposed && generation === ownGeneration\n const actionCleanups = new Set<() => void>()\n const context: ActionContext<State> = {\n state,\n event,\n isActive,\n setState(path, value) {\n if (isActive()) {\n setState(path, value)\n }\n },\n onCleanup(cleanup) {\n if (isActive()) {\n cleanups.add(cleanup)\n actionCleanups.add(cleanup)\n }\n else {\n cleanup()\n }\n },\n }\n pending.value = [...pending.value, key]\n error.value = null\n try {\n await handler(params as Parameters<typeof handler>[0], context)\n return isActive()\n }\n catch (reason) {\n if (isActive()) {\n report(reason)\n }\n return false\n }\n finally {\n for (const cleanup of actionCleanups) {\n if (cleanups.delete(cleanup)) {\n try {\n cleanup()\n }\n catch (reason) {\n report(reason)\n }\n }\n }\n if (isActive()) {\n pending.value = pending.value.filter(item => item !== key)\n }\n }\n }\n catch (reason) {\n report(reason)\n return false\n }\n }\n\n function createStream(initialSpec?: CatalogSpec<C>) {\n const initial = validateRendererSpec(initialSpec ?? spec.value, options.catalog, state, options.limits).spec\n const stream = createSpecStream(initial, options.catalog, state, options.limits)\n currentStream?.dispose()\n const ownGeneration = ++streamGeneration\n spec.value = initial\n currentStream = stream\n error.value = null\n return {\n push(chunk: string, done = false) {\n if (disposed || ownGeneration !== streamGeneration) {\n return false\n }\n try {\n const next = stream.push(chunk, done)\n if (next) {\n spec.value = next\n }\n return next !== null\n }\n catch (reason) {\n report(reason)\n return false\n }\n },\n dispose: () => stream.dispose(),\n }\n }\n\n return {\n state,\n spec,\n tree,\n error,\n pending,\n setState,\n load,\n dispatch,\n createStream,\n dispose() {\n if (!disposed) {\n disposed = true\n cancel()\n }\n },\n }\n}\n"],"mappings":"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"}
|
package/dist/resolver.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.mjs","names":[],"sources":["../src/resolver.ts"],"sourcesContent":["const componentPath = '@wevu/json-render-components/renderer/index'\n\n/** 在消费项目中注册已经由 lib 模式编译的组件,不向 AppService 引入构建依赖。 */\nexport function JsonRendererResolver() {\n const components: Readonly<Record<string, string>> = Object.freeze({\n 'json-renderer': componentPath,\n 'json-render-node': componentPath,\n })\n return {\n components,\n resolve(name: string) {\n const from = components[name]\n if (!from) {\n return undefined\n }\n return { name, from, sourceType: 'native' as const, typeImport: false }\n },\n }\n}\n"],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"resolver.mjs","names":["componentPath","JsonRendererResolver","components","from","name"],"sources":["../src/resolver.ts"],"sourcesContent":["const componentPath = '@wevu/json-render-components/renderer/index'\n\n/** 在消费项目中注册已经由 lib 模式编译的组件,不向 AppService 引入构建依赖。 */\nexport function JsonRendererResolver() {\n const components: Readonly<Record<string, string>> = Object.freeze({\n 'json-renderer': componentPath,\n 'json-render-node': componentPath,\n })\n return {\n components,\n resolve(name: string) {\n const from = components[name]\n if (!from) {\n return undefined\n }\n return { name, from, sourceType: 'native' as const, typeImport: false }\n },\n }\n}\n"],"mappings":"AAAA,MAAMA,EAAgB,8CAGtB,SAAgBC,GAAuB,CACrC,IAAMC,EAA+C,OAAO,OAAO,CACjE,gBAAiBF,EACjB,mBAAoBA,CACtB,CAAC,EACD,MAAO,CACL,aACA,QAAQ,EAAc,CACpB,IAAMG,EAAOD,EAAWE,GACxB,GAAKD,EAGL,MAAO,CAAE,OAAM,OAAM,WAAY,SAAmB,WAAY,EAAM,CACxE,CACF,CACF"}
|
package/dist/stream.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.mjs","names":[],"sources":["../src/stream.ts"],"sourcesContent":["import type { RendererCatalog, RendererLimits, RendererSpec } from './types'\nimport { createSpecStreamCompiler } from './core'\nimport { cloneJson, parsePointer } from './path'\nimport { validateRendererSpec } from './validation'\n\n/** 按批应用描述 Patch,保留上一次完整界面并等待暂缺的节点引用。 */\nexport function createSpecStream(initial: RendererSpec, catalog: RendererCatalog, state: object, limits: RendererLimits = {}) {\n let candidate = cloneJson(initial)\n let buffer = ''\n let stopped = false\n const maxBufferedCharacters = limits.maxBufferedCharacters ?? 65_536\n if (!Number.isInteger(maxBufferedCharacters) || maxBufferedCharacters < 1) {\n throw new Error('流缓冲上限必须是正整数')\n }\n return {\n push(chunk: string, done = false): RendererSpec | null {\n if (stopped) {\n throw new Error('流已停止,请创建新的流')\n }\n try {\n buffer += chunk\n if (buffer.length > maxBufferedCharacters) {\n throw new Error('单批流数据过大')\n }\n const lines = buffer.split('\\n')\n buffer = done ? '' : lines.pop()!\n let draft = cloneJson(candidate)\n let changed = false\n for (const line of lines) {\n if (!line.trim()) {\n continue\n }\n const patch = JSON.parse(line) as Record<string, unknown>\n if (!patch || !['add', 'replace', 'remove'].includes(String(patch.op)) || typeof patch.path !== 'string'\n || !/^\\/(?:root|elements)(?:\\/|$)/.test(patch.path)\n || Object.keys(patch).some(key => !['op', 'path', 'value'].includes(key))\n || (patch.op !== 'remove' && !Object.prototype.hasOwnProperty.call(patch, 'value'))) {\n throw new Error('不支持的 Patch,只允许更新 root/elements')\n }\n parsePointer(patch.path)\n // 每行独立编译,避免上游按文本去重吞掉合法的重复数组操作。\n draft = createSpecStreamCompiler<RendererSpec>(draft).push(`${line}\\n`).result\n changed = true\n }\n const checked = validateRendererSpec(draft, catalog, state, limits, !done)\n candidate = checked.spec\n stopped = done\n return checked.complete && changed ? checked.spec : null\n }\n catch (error) {\n stopped = true\n throw error\n }\n },\n dispose() {\n stopped = true\n buffer = ''\n },\n }\n}\n"],"mappings":"uKAMA,
|
|
1
|
+
{"version":3,"file":"stream.mjs","names":["createSpecStream","_limits$maxBufferedCh","candidate","cloneJson","initial","buffer","stopped","maxBufferedCharacters","limits","chunk","lines","done","draft","changed","line","patch","key","parsePointer","createSpecStreamCompiler","checked","validateRendererSpec","catalog","state","error"],"sources":["../src/stream.ts"],"sourcesContent":["import type { RendererCatalog, RendererLimits, RendererSpec } from './types'\nimport { createSpecStreamCompiler } from './core'\nimport { cloneJson, parsePointer } from './path'\nimport { validateRendererSpec } from './validation'\n\n/** 按批应用描述 Patch,保留上一次完整界面并等待暂缺的节点引用。 */\nexport function createSpecStream(initial: RendererSpec, catalog: RendererCatalog, state: object, limits: RendererLimits = {}) {\n let candidate = cloneJson(initial)\n let buffer = ''\n let stopped = false\n const maxBufferedCharacters = limits.maxBufferedCharacters ?? 65_536\n if (!Number.isInteger(maxBufferedCharacters) || maxBufferedCharacters < 1) {\n throw new Error('流缓冲上限必须是正整数')\n }\n return {\n push(chunk: string, done = false): RendererSpec | null {\n if (stopped) {\n throw new Error('流已停止,请创建新的流')\n }\n try {\n buffer += chunk\n if (buffer.length > maxBufferedCharacters) {\n throw new Error('单批流数据过大')\n }\n const lines = buffer.split('\\n')\n buffer = done ? '' : lines.pop()!\n let draft = cloneJson(candidate)\n let changed = false\n for (const line of lines) {\n if (!line.trim()) {\n continue\n }\n const patch = JSON.parse(line) as Record<string, unknown>\n if (!patch || !['add', 'replace', 'remove'].includes(String(patch.op)) || typeof patch.path !== 'string'\n || !/^\\/(?:root|elements)(?:\\/|$)/.test(patch.path)\n || Object.keys(patch).some(key => !['op', 'path', 'value'].includes(key))\n || (patch.op !== 'remove' && !Object.prototype.hasOwnProperty.call(patch, 'value'))) {\n throw new Error('不支持的 Patch,只允许更新 root/elements')\n }\n parsePointer(patch.path)\n // 每行独立编译,避免上游按文本去重吞掉合法的重复数组操作。\n draft = createSpecStreamCompiler<RendererSpec>(draft).push(`${line}\\n`).result\n changed = true\n }\n const checked = validateRendererSpec(draft, catalog, state, limits, !done)\n candidate = checked.spec\n stopped = done\n return checked.complete && changed ? checked.spec : null\n }\n catch (error) {\n stopped = true\n throw error\n }\n },\n dispose() {\n stopped = true\n buffer = ''\n },\n }\n}\n"],"mappings":"uKAMA,SAAgBA,EAAiB,EAAuB,EAA0B,EAAe,EAAyB,CAAC,EAAG,OAC5H,IAAIE,EAAYC,EAAUC,CAAO,EAC7BC,EAAS,GACTC,EAAU,GACRC,GAAA,EAAwBC,EAAO,wBAAA,KAAyB,MAAzBP,EACrC,GAAI,CAAC,OAAO,UAAUM,CAAqB,GAAKA,EAAwB,EACtE,MAAU,MAAM,aAAa,EAE/B,MAAO,CACL,KAAK,EAAe,EAAO,GAA4B,CACrD,GAAID,EACF,MAAU,MAAM,aAAa,EAE/B,GAAI,CAEF,GADA,GAAUG,EACNJ,EAAO,OAASE,EAClB,MAAU,MAAM,SAAS,EAE3B,IAAMG,EAAQL,EAAO,MAAM;CAAI,EAC/B,EAASM,EAAO,GAAKD,EAAM,IAAI,EAC/B,IAAIE,EAAQT,EAAUD,CAAS,EAC3BW,EAAU,GACd,IAAK,IAAMC,KAAQJ,EAAO,CACxB,GAAI,CAACI,EAAK,KAAK,EACb,SAEF,IAAMC,EAAQ,KAAK,MAAMD,CAAI,EAC7B,GAAI,CAACC,GAAS,CAAC,CAAC,MAAO,UAAW,QAAQ,CAAC,CAAC,SAAS,OAAOA,EAAM,EAAE,CAAC,GAAK,OAAOA,EAAM,MAAS,UAC3F,CAAC,+BAA+B,KAAKA,EAAM,IAAI,GAC/C,OAAO,KAAKA,CAAK,CAAC,CAAC,KAAK,GAAO,CAAC,CAAC,KAAM,OAAQ,OAAO,CAAC,CAAC,SAASC,CAAG,CAAC,GACpED,EAAM,KAAO,UAAY,CAAC,OAAO,UAAU,eAAe,KAAKA,EAAO,OAAO,EACjF,MAAU,MAAM,gCAAgC,EAElDE,EAAaF,EAAM,IAAI,EAEvB,EAAQG,EAAuCN,CAAK,CAAC,CAAC,KAAK,GAAGE,EAAK,GAAG,CAAC,CAAC,OACxE,EAAU,EACZ,CACA,IAAMK,EAAUC,EAAqBR,EAAOS,EAASC,EAAOd,EAAQ,CAACG,CAAI,EAGzE,MAFA,GAAYQ,EAAQ,KACpB,EAAUR,EACHQ,EAAQ,UAAYN,EAAUM,EAAQ,KAAO,IACtD,OACOI,EAAO,CAEZ,KADA,GAAU,GACJA,CACR,CACF,EACA,SAAU,CACR,EAAU,GACV,EAAS,EACX,CACF,CACF"}
|
package/dist/useRenderer.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRenderer.mjs","names":[],"sources":["../src/useRenderer.ts"],"sourcesContent":["import type { RendererCatalog, RendererOptions } from './types'\nimport { onUnload, onUnmounted } from 'wevu'\nimport { createJsonRenderer } from './renderer'\n\n/** 在同步 setup 中创建会话,页面和组件卸载时均释放动作及流。 */\nexport function useJsonRenderer<C extends RendererCatalog, State extends object>(options: RendererOptions<C, State>) {\n const renderer = createJsonRenderer(options)\n onUnload(renderer.dispose)\n onUnmounted(renderer.dispose)\n return renderer\n}\n"],"mappings":"qGAKA,
|
|
1
|
+
{"version":3,"file":"useRenderer.mjs","names":["useJsonRenderer","renderer","createJsonRenderer","options","onUnload","onUnmounted"],"sources":["../src/useRenderer.ts"],"sourcesContent":["import type { RendererCatalog, RendererOptions } from './types'\nimport { onUnload, onUnmounted } from 'wevu'\nimport { createJsonRenderer } from './renderer'\n\n/** 在同步 setup 中创建会话,页面和组件卸载时均释放动作及流。 */\nexport function useJsonRenderer<C extends RendererCatalog, State extends object>(options: RendererOptions<C, State>) {\n const renderer = createJsonRenderer(options)\n onUnload(renderer.dispose)\n onUnmounted(renderer.dispose)\n return renderer\n}\n"],"mappings":"qGAKA,SAAgBA,EAAiE,EAAoC,CACnH,IAAMC,EAAWC,EAAmBC,CAAO,EAG3C,OAFAC,EAASH,EAAS,OAAO,EACzBI,EAAYJ,EAAS,OAAO,EACrBA,CACT"}
|
package/dist/validation.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.mjs","names":[],"sources":["../src/validation.ts"],"sourcesContent":["import type { RendererCatalog, RendererLimits, RendererSpec, SpecElement } from './types'\nimport { z } from 'zod'\nimport { resolveElementProps } from './core'\nimport { assertJson, parsePointer } from './path'\n\nconst visibleSchema = z.union([z.boolean(), z.object({ $state: z.string(), not: z.literal(true).optional(), eq: z.unknown().optional() }).strict()])\nconst specSchema = z.object({\n root: z.string().min(1),\n elements: z.record(z.string().regex(/^[a-z][\\w-]*$/i), z.object({\n type: z.string(),\n props: z.record(z.string(), z.unknown()),\n children: z.array(z.string().min(1)).optional(),\n visible: visibleSchema.optional(),\n on: z.record(z.string(), z.object({ action: z.string(), params: z.record(z.string(), z.unknown()).optional() }).strict()).optional(),\n }).strict()),\n}).strict()\n\n/** v1 只解释状态读取和输入绑定,拒绝静默接受未实现的表达式。 */\nfunction validateExpressions(value: unknown, binding = false) {\n if (!value || typeof value !== 'object') {\n return\n }\n for (const [key, child] of Object.entries(value)) {\n if (key.startsWith('$')) {\n if (!['$state', ...(binding ? ['$bindState'] : [])].includes(key)\n || Object.keys(value).length !== 1 || typeof child !== 'string') {\n throw new Error(`不支持的表达式:${key}`)\n }\n parsePointer(child)\n }\n else {\n validateExpressions(child)\n }\n }\n}\n\nexport function resolveProps(node: SpecElement, catalog: RendererCatalog, state: object) {\n const resolved = resolveElementProps(node.props, { stateModel: state as Record<string, unknown> })\n const parsed: unknown = catalog.components[node.type]!.props.parse(resolved)\n assertJson(parsed)\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('组件 props schema 必须输出对象')\n }\n return parsed\n}\n\n/** 完整描述与流式中间态共用目录和图结构校验。 */\nexport function validateRendererSpec(\n input: unknown,\n catalog: RendererCatalog,\n state: object,\n limits: RendererLimits = {},\n partial = false,\n): { spec: RendererSpec, complete: boolean } {\n assertJson(input)\n const spec = specSchema.parse(input) as RendererSpec\n const maxNodes = limits.maxNodes ?? 200\n const maxDepth = limits.maxDepth ?? 8\n if (!Number.isInteger(maxNodes) || maxNodes < 1 || !Number.isInteger(maxDepth) || maxDepth < 1) {\n throw new Error('节点及深度上限必须是正整数')\n }\n const ids = Object.keys(spec.elements)\n if (ids.length > maxNodes) {\n throw new Error(`节点数量不能超过 ${maxNodes}`)\n }\n const parents = new Set<string>()\n let complete = Object.prototype.hasOwnProperty.call(spec.elements, spec.root)\n for (const [id, node] of Object.entries(spec.elements)) {\n if (!Object.prototype.hasOwnProperty.call(catalog.components, node.type)) {\n throw new Error(`未注册组件:${node.type}`)\n }\n const definition = catalog.components[node.type]!\n if (!definition.container && node.children?.length) {\n throw new Error(`${node.type} 不支持 children`)\n }\n for (const [key, value] of Object.entries(node.props)) {\n validateExpressions(value, Object.prototype.hasOwnProperty.call(definition.bindings ?? {}, key))\n }\n if (typeof node.visible === 'object') {\n parsePointer(node.visible.$state)\n }\n resolveProps(node, catalog, state)\n for (const [event, action] of Object.entries(node.on ?? {})) {\n if (!definition.events?.includes(event)) {\n throw new Error(`${node.type} 未声明事件:${event}`)\n }\n if (!Object.prototype.hasOwnProperty.call(catalog.actions, action.action)) {\n throw new Error(`未注册动作:${action.action}`)\n }\n validateExpressions(action.params ?? {})\n }\n for (const child of node.children ?? []) {\n if (parents.has(child)) {\n throw new Error(`节点重复引用:${child}`)\n }\n parents.add(child)\n }\n parsePointer(`/elements/${id}`)\n }\n function visit(id: string, ancestors: Set<string>) {\n if (ancestors.has(id)) {\n throw new Error(`节点循环引用:${id}`)\n }\n if (ancestors.size >= maxDepth) {\n throw new Error(`节点深度不能超过 ${maxDepth}`)\n }\n if (!Object.prototype.hasOwnProperty.call(spec.elements, id)) {\n complete = false\n return\n }\n const next = new Set(ancestors).add(id)\n for (const child of spec.elements[id]!.children ?? []) {\n visit(child, next)\n }\n }\n ids.forEach(id => visit(id, new Set()))\n if (!partial && !complete) {\n throw new Error('节点引用不存在')\n }\n return { spec, complete }\n}\n"],"mappings":"mIAKA,
|
|
1
|
+
{"version":3,"file":"validation.mjs","names":["visibleSchema","z","specSchema","validateExpressions","value","key","child","binding","parsePointer","resolveProps","resolved","resolveElementProps","node","state","parsed","catalog","assertJson","validateRendererSpec","_limits$maxNodes","_limits$maxDepth","input","spec","maxNodes","limits","maxDepth","ids","parents","complete","id","_node$children","_node$on","_node$children2","definition","_definition$bindings","event","action","_definition$events","_action$params","visit","_children","ancestors","next","partial"],"sources":["../src/validation.ts"],"sourcesContent":["import type { RendererCatalog, RendererLimits, RendererSpec, SpecElement } from './types'\nimport { z } from 'zod'\nimport { resolveElementProps } from './core'\nimport { assertJson, parsePointer } from './path'\n\nconst visibleSchema = z.union([z.boolean(), z.object({ $state: z.string(), not: z.literal(true).optional(), eq: z.unknown().optional() }).strict()])\nconst specSchema = z.object({\n root: z.string().min(1),\n elements: z.record(z.string().regex(/^[a-z][\\w-]*$/i), z.object({\n type: z.string(),\n props: z.record(z.string(), z.unknown()),\n children: z.array(z.string().min(1)).optional(),\n visible: visibleSchema.optional(),\n on: z.record(z.string(), z.object({ action: z.string(), params: z.record(z.string(), z.unknown()).optional() }).strict()).optional(),\n }).strict()),\n}).strict()\n\n/** v1 只解释状态读取和输入绑定,拒绝静默接受未实现的表达式。 */\nfunction validateExpressions(value: unknown, binding = false) {\n if (!value || typeof value !== 'object') {\n return\n }\n for (const [key, child] of Object.entries(value)) {\n if (key.startsWith('$')) {\n if (!['$state', ...(binding ? ['$bindState'] : [])].includes(key)\n || Object.keys(value).length !== 1 || typeof child !== 'string') {\n throw new Error(`不支持的表达式:${key}`)\n }\n parsePointer(child)\n }\n else {\n validateExpressions(child)\n }\n }\n}\n\nexport function resolveProps(node: SpecElement, catalog: RendererCatalog, state: object) {\n const resolved = resolveElementProps(node.props, { stateModel: state as Record<string, unknown> })\n const parsed: unknown = catalog.components[node.type]!.props.parse(resolved)\n assertJson(parsed)\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('组件 props schema 必须输出对象')\n }\n return parsed\n}\n\n/** 完整描述与流式中间态共用目录和图结构校验。 */\nexport function validateRendererSpec(\n input: unknown,\n catalog: RendererCatalog,\n state: object,\n limits: RendererLimits = {},\n partial = false,\n): { spec: RendererSpec, complete: boolean } {\n assertJson(input)\n const spec = specSchema.parse(input) as RendererSpec\n const maxNodes = limits.maxNodes ?? 200\n const maxDepth = limits.maxDepth ?? 8\n if (!Number.isInteger(maxNodes) || maxNodes < 1 || !Number.isInteger(maxDepth) || maxDepth < 1) {\n throw new Error('节点及深度上限必须是正整数')\n }\n const ids = Object.keys(spec.elements)\n if (ids.length > maxNodes) {\n throw new Error(`节点数量不能超过 ${maxNodes}`)\n }\n const parents = new Set<string>()\n let complete = Object.prototype.hasOwnProperty.call(spec.elements, spec.root)\n for (const [id, node] of Object.entries(spec.elements)) {\n if (!Object.prototype.hasOwnProperty.call(catalog.components, node.type)) {\n throw new Error(`未注册组件:${node.type}`)\n }\n const definition = catalog.components[node.type]!\n if (!definition.container && node.children?.length) {\n throw new Error(`${node.type} 不支持 children`)\n }\n for (const [key, value] of Object.entries(node.props)) {\n validateExpressions(value, Object.prototype.hasOwnProperty.call(definition.bindings ?? {}, key))\n }\n if (typeof node.visible === 'object') {\n parsePointer(node.visible.$state)\n }\n resolveProps(node, catalog, state)\n for (const [event, action] of Object.entries(node.on ?? {})) {\n if (!definition.events?.includes(event)) {\n throw new Error(`${node.type} 未声明事件:${event}`)\n }\n if (!Object.prototype.hasOwnProperty.call(catalog.actions, action.action)) {\n throw new Error(`未注册动作:${action.action}`)\n }\n validateExpressions(action.params ?? {})\n }\n for (const child of node.children ?? []) {\n if (parents.has(child)) {\n throw new Error(`节点重复引用:${child}`)\n }\n parents.add(child)\n }\n parsePointer(`/elements/${id}`)\n }\n function visit(id: string, ancestors: Set<string>) {\n if (ancestors.has(id)) {\n throw new Error(`节点循环引用:${id}`)\n }\n if (ancestors.size >= maxDepth) {\n throw new Error(`节点深度不能超过 ${maxDepth}`)\n }\n if (!Object.prototype.hasOwnProperty.call(spec.elements, id)) {\n complete = false\n return\n }\n const next = new Set(ancestors).add(id)\n for (const child of spec.elements[id]!.children ?? []) {\n visit(child, next)\n }\n }\n ids.forEach(id => visit(id, new Set()))\n if (!partial && !complete) {\n throw new Error('节点引用不存在')\n }\n return { spec, complete }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wevu/json-render",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"description": "json-render 的 Wevu 小程序渲染与交互适配层",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/weapp-vite/weapp-vite#readme",
|
|
@@ -44,16 +44,16 @@
|
|
|
44
44
|
"node": "^20.19.0 || >=22.12.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"wevu": "7.
|
|
47
|
+
"wevu": "7.4.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@json-render/core": "0.21.0",
|
|
51
|
-
"@wevu/json-render-components": "0.
|
|
51
|
+
"@wevu/json-render-components": "0.1.0",
|
|
52
52
|
"zod": "^4.6.5"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"miniprogram-api-typings": "^5.2.3",
|
|
56
|
-
"wevu": "7.
|
|
56
|
+
"wevu": "7.4.0"
|
|
57
57
|
},
|
|
58
58
|
"tsd": {
|
|
59
59
|
"compilerOptions": {
|