@djvlc/contracts-validators 1.4.5 → 1.4.6
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/index.d.mts +3 -8
- package/dist/index.d.ts +3 -8
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -9,11 +9,6 @@ export { actionSpecSchema, componentMetaSchema, dataQuerySpecSchema, pageSchema
|
|
|
9
9
|
* - 发布期校验(Editor 发布页面时)
|
|
10
10
|
* - 运行时校验(Runtime 加载组件时)
|
|
11
11
|
* - API 校验(Platform 接收请求时)
|
|
12
|
-
*
|
|
13
|
-
* V2 版本更新:
|
|
14
|
-
* - 支持 PageSchema V2 Runtime Core 校验
|
|
15
|
-
* - 新增表达式引用校验(支持 binding 类型)
|
|
16
|
-
* - 优化错误信息格式
|
|
17
12
|
*/
|
|
18
13
|
/**
|
|
19
14
|
* 校验结果
|
|
@@ -88,21 +83,21 @@ declare function validateComponentReferences(pageSchema: unknown, availableCompo
|
|
|
88
83
|
* 校验表达式引用
|
|
89
84
|
*
|
|
90
85
|
* @description
|
|
91
|
-
*
|
|
86
|
+
* 校验 state、binding、local、template、computed 表达式类型的引用
|
|
92
87
|
*/
|
|
93
88
|
declare function validateExpressionReferences(pageSchema: unknown, availableFields: Set<string>): ValidationResult;
|
|
94
89
|
/**
|
|
95
90
|
* 校验数据绑定配置
|
|
96
91
|
*
|
|
97
92
|
* @description
|
|
98
|
-
*
|
|
93
|
+
* 校验 dataBindings 中的 targetState 是否在 state.fields 中定义
|
|
99
94
|
*/
|
|
100
95
|
declare function validateDataBindingReferences(pageSchema: unknown): ValidationResult;
|
|
101
96
|
/**
|
|
102
97
|
* 校验动作引用
|
|
103
98
|
*
|
|
104
99
|
* @description
|
|
105
|
-
*
|
|
100
|
+
* 校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一
|
|
106
101
|
*/
|
|
107
102
|
declare function validateActionReferences(pageSchema: unknown): ValidationResult;
|
|
108
103
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,6 @@ export { actionSpecSchema, componentMetaSchema, dataQuerySpecSchema, pageSchema
|
|
|
9
9
|
* - 发布期校验(Editor 发布页面时)
|
|
10
10
|
* - 运行时校验(Runtime 加载组件时)
|
|
11
11
|
* - API 校验(Platform 接收请求时)
|
|
12
|
-
*
|
|
13
|
-
* V2 版本更新:
|
|
14
|
-
* - 支持 PageSchema V2 Runtime Core 校验
|
|
15
|
-
* - 新增表达式引用校验(支持 binding 类型)
|
|
16
|
-
* - 优化错误信息格式
|
|
17
12
|
*/
|
|
18
13
|
/**
|
|
19
14
|
* 校验结果
|
|
@@ -88,21 +83,21 @@ declare function validateComponentReferences(pageSchema: unknown, availableCompo
|
|
|
88
83
|
* 校验表达式引用
|
|
89
84
|
*
|
|
90
85
|
* @description
|
|
91
|
-
*
|
|
86
|
+
* 校验 state、binding、local、template、computed 表达式类型的引用
|
|
92
87
|
*/
|
|
93
88
|
declare function validateExpressionReferences(pageSchema: unknown, availableFields: Set<string>): ValidationResult;
|
|
94
89
|
/**
|
|
95
90
|
* 校验数据绑定配置
|
|
96
91
|
*
|
|
97
92
|
* @description
|
|
98
|
-
*
|
|
93
|
+
* 校验 dataBindings 中的 targetState 是否在 state.fields 中定义
|
|
99
94
|
*/
|
|
100
95
|
declare function validateDataBindingReferences(pageSchema: unknown): ValidationResult;
|
|
101
96
|
/**
|
|
102
97
|
* 校验动作引用
|
|
103
98
|
*
|
|
104
99
|
* @description
|
|
105
|
-
*
|
|
100
|
+
* 校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一
|
|
106
101
|
*/
|
|
107
102
|
declare function validateActionReferences(pageSchema: unknown): ValidationResult;
|
|
108
103
|
/**
|
package/dist/index.js
CHANGED
|
@@ -198,7 +198,7 @@ function validateExpressionReferences(pageSchema3, availableFields) {
|
|
|
198
198
|
function traverse(obj, path) {
|
|
199
199
|
if (!obj || typeof obj !== "object") return;
|
|
200
200
|
const record = obj;
|
|
201
|
-
if (record.type && record.value && ["state", "binding", "computed"].includes(record.type)) {
|
|
201
|
+
if (record.type && record.value && ["state", "binding", "local", "template", "computed"].includes(record.type)) {
|
|
202
202
|
checkExpression(record, path);
|
|
203
203
|
}
|
|
204
204
|
for (const [key, value] of Object.entries(record)) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @djvlc/contracts-validators\n *\n * DJVLC 低代码平台预编译 JSON Schema 校验器\n *\n * 提供高性能的 Ajv 校验器,用于:\n * - 发布期校验(Editor 发布页面时)\n * - 运行时校验(Runtime 加载组件时)\n * - API 校验(Platform 接收请求时)\n *\n * V2 版本更新:\n * - 支持 PageSchema V2 Runtime Core 校验\n * - 新增表达式引用校验(支持 binding 类型)\n * - 优化错误信息格式\n */\n\nimport Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n\n// ============================================================\n// 校验器实例\n// ============================================================\n\n/**\n * 创建配置好的 Ajv 实例\n */\nfunction createAjv(): Ajv {\n const ajv = new Ajv({\n strict: true,\n allErrors: true,\n verbose: true,\n removeAdditional: false,\n useDefaults: true,\n coerceTypes: false,\n allowUnionTypes: true,\n });\n\n // 添加格式支持\n addFormats(ajv);\n\n // 添加自定义格式\n ajv.addFormat('semver', /^\\d+\\.\\d+\\.\\d+$/);\n ajv.addFormat('sha384', /^sha384-[A-Za-z0-9+/=]+$/);\n\n return ajv;\n}\n\n// 单例 Ajv 实例\nconst ajv = createAjv();\n\n// 注册所有 Schema\najv.addSchema(pageSchema, pageSchema.$id);\najv.addSchema(componentMetaSchema, componentMetaSchema.$id);\najv.addSchema(actionSpecSchema, actionSpecSchema.$id);\najv.addSchema(dataQuerySpecSchema, dataQuerySpecSchema.$id);\n\n// ============================================================\n// 校验函数\n// ============================================================\n\n/**\n * 校验结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误列表 */\n errors: ValidationError[];\n}\n\n/**\n * 校验错误\n */\nexport interface ValidationError {\n /** 错误路径 */\n path: string;\n /** 错误消息 */\n message: string;\n /** JSON Schema 关键字 */\n keyword: string;\n /** 错误参数 */\n params: Record<string, unknown>;\n /** Schema 路径 */\n schemaPath: string;\n}\n\n/**\n * 将 Ajv 错误转换为校验错误\n */\nfunction toValidationErrors(errors: ErrorObject[] | null | undefined): ValidationError[] {\n if (!errors) return [];\n\n return errors.map(error => ({\n path: error.instancePath || '/',\n message: error.message || 'Unknown error',\n keyword: error.keyword,\n params: error.params as Record<string, unknown>,\n schemaPath: error.schemaPath,\n }));\n}\n\n/**\n * 通用校验函数\n */\nfunction validate(validator: ValidateFunction, data: unknown): ValidationResult {\n const valid = validator(data);\n return {\n valid,\n errors: toValidationErrors(validator.errors),\n };\n}\n\n// ============================================================\n// 导出的校验函数\n// ============================================================\n\n// 预编译校验函数\nconst _validatePageSchema = ajv.compile(pageSchema);\nconst _validateComponentMeta = ajv.compile(componentMetaSchema);\nconst _validateActionSpec = ajv.compile(actionSpecSchema);\nconst _validateDataQuerySpec = ajv.compile(dataQuerySpecSchema);\n\n/**\n * 校验页面 Schema(V2 Runtime Core)\n */\nexport function validatePageSchema(data: unknown): ValidationResult {\n return validate(_validatePageSchema, data);\n}\n\n/**\n * 校验组件元数据\n */\nexport function validateComponentMeta(data: unknown): ValidationResult {\n return validate(_validateComponentMeta, data);\n}\n\n/**\n * 校验动作规格\n */\nexport function validateActionSpec(data: unknown): ValidationResult {\n return validate(_validateActionSpec, data);\n}\n\n/**\n * 校验数据查询规格\n */\nexport function validateDataQuerySpec(data: unknown): ValidationResult {\n return validate(_validateDataQuerySpec, data);\n}\n\n// ============================================================\n// 高级校验功能\n// ============================================================\n\n/**\n * 批量校验结果\n */\nexport interface BatchValidationResult {\n /** 总数 */\n total: number;\n /** 通过数 */\n passed: number;\n /** 失败数 */\n failed: number;\n /** 详细结果 */\n results: {\n index: number;\n valid: boolean;\n errors: ValidationError[];\n }[];\n}\n\n/**\n * 批量校验\n */\nexport function batchValidate(\n validator: (data: unknown) => ValidationResult,\n items: unknown[],\n): BatchValidationResult {\n const results = items.map((item, index) => {\n const result = validator(item);\n return {\n index,\n valid: result.valid,\n errors: result.errors,\n };\n });\n\n const passed = results.filter(r => r.valid).length;\n\n return {\n total: items.length,\n passed,\n failed: items.length - passed,\n results,\n };\n}\n\n/**\n * 校验并抛出异常\n */\nexport function validateOrThrow(\n validator: (data: unknown) => ValidationResult,\n data: unknown,\n errorMessage?: string,\n): void {\n const result = validator(data);\n if (!result.valid) {\n const message = errorMessage || 'Validation failed';\n const details = result.errors.map(e => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`${message}: ${details}`);\n }\n}\n\n// ============================================================\n// Schema 引用校验\n// ============================================================\n\n/**\n * 校验组件节点树中引用的组件版本\n */\nexport function validateComponentReferences(\n pageSchema: unknown,\n availableComponents: Map<string, Set<string>>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function traverse(node: Record<string, unknown>, path: string): void {\n const componentType = node.componentType as string;\n const componentVersion = node.componentVersion as string;\n\n if (componentType && componentVersion) {\n const versions = availableComponents.get(componentType);\n if (!versions) {\n errors.push({\n path: `${path}/componentType`,\n message: `Component \"${componentType}\" not found in registry`,\n keyword: 'componentReference',\n params: { componentType },\n schemaPath: '',\n });\n } else if (!versions.has(componentVersion)) {\n errors.push({\n path: `${path}/componentVersion`,\n message: `Version \"${componentVersion}\" of component \"${componentType}\" not found`,\n keyword: 'componentVersion',\n params: { componentType, componentVersion },\n schemaPath: '',\n });\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = node.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverse(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverse(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验表达式引用\n *\n * @description\n * V2 版本更新:支持 state、binding、computed 三种表达式类型的引用校验\n */\nexport function validateExpressionReferences(\n pageSchema: unknown,\n availableFields: Set<string>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkExpression(expr: Record<string, unknown>, path: string): void {\n const meta = expr.meta as Record<string, unknown> | undefined;\n const dependencies = meta?.dependencies as string[] | undefined;\n\n if (dependencies) {\n for (const dep of dependencies) {\n if (!availableFields.has(dep)) {\n errors.push({\n path,\n message: `Expression references unknown field: \"${dep}\"`,\n keyword: 'expressionReference',\n params: { field: dep },\n schemaPath: '',\n });\n }\n }\n }\n }\n\n function traverse(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查是否是表达式对象(V2 版本支持 state, binding, computed)\n if (\n record.type &&\n record.value &&\n ['state', 'binding', 'computed'].includes(record.type as string)\n ) {\n checkExpression(record, path);\n }\n\n // 递归遍历\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n traverse(item, `${path}/${key}/${index}`);\n });\n } else if (typeof value === 'object' && value !== null) {\n traverse(value, `${path}/${key}`);\n }\n }\n }\n\n traverse(pageSchema, '');\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验数据绑定配置\n *\n * @description\n * V2 新增:校验 dataBindings 中的 targetState 是否在 state.fields 中定义\n */\nexport function validateDataBindingReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const schema = pageSchema as Record<string, unknown>;\n\n // 获取所有状态字段\n const state = schema.state as Record<string, unknown> | undefined;\n const fields = state?.fields as Record<string, unknown> | undefined;\n const stateFields = new Set(fields ? Object.keys(fields) : []);\n\n // 校验数据绑定的 targetState\n const dataBindings = schema.dataBindings as Record<string, unknown>[] | undefined;\n if (Array.isArray(dataBindings)) {\n dataBindings.forEach((binding, index) => {\n const targetState = binding.targetState as string;\n if (targetState && !stateFields.has(targetState)) {\n errors.push({\n path: `/dataBindings/${index}/targetState`,\n message: `Data binding targetState \"${targetState}\" not found in state.fields`,\n keyword: 'dataBindingReference',\n params: { targetState },\n schemaPath: '',\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验动作引用\n *\n * @description\n * V2 新增:校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一\n */\nexport function validateActionReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkActionRef(action: Record<string, unknown>, path: string): void {\n const hasDefinition = !!action.actionDefinitionVersionId;\n const hasBuiltin = !!action.builtinAction;\n\n if (!hasDefinition && !hasBuiltin) {\n errors.push({\n path,\n message: 'ActionRef must specify either actionDefinitionVersionId or builtinAction',\n keyword: 'actionReference',\n params: {},\n schemaPath: '',\n });\n }\n\n // 递归检查 onSuccess 和 onError\n const onSuccess = action.onSuccess as Record<string, unknown>[] | undefined;\n if (Array.isArray(onSuccess)) {\n onSuccess.forEach((a, i) => checkActionRef(a, `${path}/onSuccess/${i}`));\n }\n\n const onError = action.onError as Record<string, unknown>[] | undefined;\n if (Array.isArray(onError)) {\n onError.forEach((a, i) => checkActionRef(a, `${path}/onError/${i}`));\n }\n }\n\n function traverseActions(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查事件处理器中的动作\n const eventHandlers = record.eventHandlers as Record<string, unknown>[] | undefined;\n if (Array.isArray(eventHandlers)) {\n eventHandlers.forEach((handler, hIndex) => {\n const actions = handler.actions as Record<string, unknown>[] | undefined;\n if (Array.isArray(actions)) {\n actions.forEach((action, aIndex) => {\n checkActionRef(action, `${path}/eventHandlers/${hIndex}/actions/${aIndex}`);\n });\n }\n });\n }\n\n // 检查生命周期钩子中的动作\n const lifecycle = record.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `${path}/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = record.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverseActions(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n\n // 从页面级生命周期开始检查\n const lifecycle = schema.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 从根节点开始遍历组件树\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverseActions(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 完整校验(结构 + 引用)\n *\n * @description\n * 执行完整的页面 Schema 校验,包括:\n * 1. JSON Schema 结构校验\n * 2. 组件引用校验\n * 3. 表达式引用校验\n * 4. 数据绑定引用校验\n * 5. 动作引用校验\n */\nexport function validatePageSchemaFull(\n data: unknown,\n availableComponents?: Map<string, Set<string>>,\n availableFields?: Set<string>,\n): ValidationResult {\n const allErrors: ValidationError[] = [];\n\n // 1. 结构校验\n const structureResult = validatePageSchema(data);\n allErrors.push(...structureResult.errors);\n\n // 如果结构校验失败,后续校验可能不准确,直接返回\n if (!structureResult.valid) {\n return { valid: false, errors: allErrors };\n }\n\n // 2. 组件引用校验(如果提供了可用组件列表)\n if (availableComponents) {\n const componentResult = validateComponentReferences(data, availableComponents);\n allErrors.push(...componentResult.errors);\n }\n\n // 3. 表达式引用校验(如果提供了可用字段列表)\n if (availableFields) {\n const expressionResult = validateExpressionReferences(data, availableFields);\n allErrors.push(...expressionResult.errors);\n }\n\n // 4. 数据绑定引用校验\n const bindingResult = validateDataBindingReferences(data);\n allErrors.push(...bindingResult.errors);\n\n // 5. 动作引用校验\n const actionResult = validateActionReferences(data);\n allErrors.push(...actionResult.errors);\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n };\n}\n\n// ============================================================\n// 导出版本信息\n// ============================================================\n\nexport const VERSION = '2.0.0';\n\n// 重新导出 Schema\nexport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n"],"mappings":"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","names":["import_contracts_schemas","ajv","Ajv","addFormats","pageSchema","lifecycle"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @djvlc/contracts-validators\n *\n * DJVLC 低代码平台预编译 JSON Schema 校验器\n *\n * 提供高性能的 Ajv 校验器,用于:\n * - 发布期校验(Editor 发布页面时)\n * - 运行时校验(Runtime 加载组件时)\n * - API 校验(Platform 接收请求时)\n */\n\nimport Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n\n// ============================================================\n// 校验器实例\n// ============================================================\n\n/**\n * 创建配置好的 Ajv 实例\n */\nfunction createAjv(): Ajv {\n const ajv = new Ajv({\n strict: true,\n allErrors: true,\n verbose: true,\n removeAdditional: false,\n useDefaults: true,\n coerceTypes: false,\n allowUnionTypes: true,\n });\n\n // 添加格式支持\n addFormats(ajv);\n\n // 添加自定义格式\n ajv.addFormat('semver', /^\\d+\\.\\d+\\.\\d+$/);\n ajv.addFormat('sha384', /^sha384-[A-Za-z0-9+/=]+$/);\n\n return ajv;\n}\n\n// 单例 Ajv 实例\nconst ajv = createAjv();\n\n// 注册所有 Schema\najv.addSchema(pageSchema, pageSchema.$id);\najv.addSchema(componentMetaSchema, componentMetaSchema.$id);\najv.addSchema(actionSpecSchema, actionSpecSchema.$id);\najv.addSchema(dataQuerySpecSchema, dataQuerySpecSchema.$id);\n\n// ============================================================\n// 校验函数\n// ============================================================\n\n/**\n * 校验结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误列表 */\n errors: ValidationError[];\n}\n\n/**\n * 校验错误\n */\nexport interface ValidationError {\n /** 错误路径 */\n path: string;\n /** 错误消息 */\n message: string;\n /** JSON Schema 关键字 */\n keyword: string;\n /** 错误参数 */\n params: Record<string, unknown>;\n /** Schema 路径 */\n schemaPath: string;\n}\n\n/**\n * 将 Ajv 错误转换为校验错误\n */\nfunction toValidationErrors(errors: ErrorObject[] | null | undefined): ValidationError[] {\n if (!errors) return [];\n\n return errors.map(error => ({\n path: error.instancePath || '/',\n message: error.message || 'Unknown error',\n keyword: error.keyword,\n params: error.params as Record<string, unknown>,\n schemaPath: error.schemaPath,\n }));\n}\n\n/**\n * 通用校验函数\n */\nfunction validate(validator: ValidateFunction, data: unknown): ValidationResult {\n const valid = validator(data);\n return {\n valid,\n errors: toValidationErrors(validator.errors),\n };\n}\n\n// ============================================================\n// 导出的校验函数\n// ============================================================\n\n// 预编译校验函数\nconst _validatePageSchema = ajv.compile(pageSchema);\nconst _validateComponentMeta = ajv.compile(componentMetaSchema);\nconst _validateActionSpec = ajv.compile(actionSpecSchema);\nconst _validateDataQuerySpec = ajv.compile(dataQuerySpecSchema);\n\n/**\n * 校验页面 Schema(V2 Runtime Core)\n */\nexport function validatePageSchema(data: unknown): ValidationResult {\n return validate(_validatePageSchema, data);\n}\n\n/**\n * 校验组件元数据\n */\nexport function validateComponentMeta(data: unknown): ValidationResult {\n return validate(_validateComponentMeta, data);\n}\n\n/**\n * 校验动作规格\n */\nexport function validateActionSpec(data: unknown): ValidationResult {\n return validate(_validateActionSpec, data);\n}\n\n/**\n * 校验数据查询规格\n */\nexport function validateDataQuerySpec(data: unknown): ValidationResult {\n return validate(_validateDataQuerySpec, data);\n}\n\n// ============================================================\n// 高级校验功能\n// ============================================================\n\n/**\n * 批量校验结果\n */\nexport interface BatchValidationResult {\n /** 总数 */\n total: number;\n /** 通过数 */\n passed: number;\n /** 失败数 */\n failed: number;\n /** 详细结果 */\n results: {\n index: number;\n valid: boolean;\n errors: ValidationError[];\n }[];\n}\n\n/**\n * 批量校验\n */\nexport function batchValidate(\n validator: (data: unknown) => ValidationResult,\n items: unknown[],\n): BatchValidationResult {\n const results = items.map((item, index) => {\n const result = validator(item);\n return {\n index,\n valid: result.valid,\n errors: result.errors,\n };\n });\n\n const passed = results.filter(r => r.valid).length;\n\n return {\n total: items.length,\n passed,\n failed: items.length - passed,\n results,\n };\n}\n\n/**\n * 校验并抛出异常\n */\nexport function validateOrThrow(\n validator: (data: unknown) => ValidationResult,\n data: unknown,\n errorMessage?: string,\n): void {\n const result = validator(data);\n if (!result.valid) {\n const message = errorMessage || 'Validation failed';\n const details = result.errors.map(e => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`${message}: ${details}`);\n }\n}\n\n// ============================================================\n// Schema 引用校验\n// ============================================================\n\n/**\n * 校验组件节点树中引用的组件版本\n */\nexport function validateComponentReferences(\n pageSchema: unknown,\n availableComponents: Map<string, Set<string>>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function traverse(node: Record<string, unknown>, path: string): void {\n const componentType = node.componentType as string;\n const componentVersion = node.componentVersion as string;\n\n if (componentType && componentVersion) {\n const versions = availableComponents.get(componentType);\n if (!versions) {\n errors.push({\n path: `${path}/componentType`,\n message: `Component \"${componentType}\" not found in registry`,\n keyword: 'componentReference',\n params: { componentType },\n schemaPath: '',\n });\n } else if (!versions.has(componentVersion)) {\n errors.push({\n path: `${path}/componentVersion`,\n message: `Version \"${componentVersion}\" of component \"${componentType}\" not found`,\n keyword: 'componentVersion',\n params: { componentType, componentVersion },\n schemaPath: '',\n });\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = node.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverse(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverse(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验表达式引用\n *\n * @description\n * 校验 state、binding、local、template、computed 表达式类型的引用\n */\nexport function validateExpressionReferences(\n pageSchema: unknown,\n availableFields: Set<string>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkExpression(expr: Record<string, unknown>, path: string): void {\n const meta = expr.meta as Record<string, unknown> | undefined;\n const dependencies = meta?.dependencies as string[] | undefined;\n\n if (dependencies) {\n for (const dep of dependencies) {\n if (!availableFields.has(dep)) {\n errors.push({\n path,\n message: `Expression references unknown field: \"${dep}\"`,\n keyword: 'expressionReference',\n params: { field: dep },\n schemaPath: '',\n });\n }\n }\n }\n }\n\n function traverse(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查是否是表达式对象(支持 state, binding, local, template, computed)\n if (\n record.type &&\n record.value &&\n ['state', 'binding', 'local', 'template', 'computed'].includes(record.type as string)\n ) {\n checkExpression(record, path);\n }\n\n // 递归遍历\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n traverse(item, `${path}/${key}/${index}`);\n });\n } else if (typeof value === 'object' && value !== null) {\n traverse(value, `${path}/${key}`);\n }\n }\n }\n\n traverse(pageSchema, '');\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验数据绑定配置\n *\n * @description\n * 校验 dataBindings 中的 targetState 是否在 state.fields 中定义\n */\nexport function validateDataBindingReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const schema = pageSchema as Record<string, unknown>;\n\n // 获取所有状态字段\n const state = schema.state as Record<string, unknown> | undefined;\n const fields = state?.fields as Record<string, unknown> | undefined;\n const stateFields = new Set(fields ? Object.keys(fields) : []);\n\n // 校验数据绑定的 targetState\n const dataBindings = schema.dataBindings as Record<string, unknown>[] | undefined;\n if (Array.isArray(dataBindings)) {\n dataBindings.forEach((binding, index) => {\n const targetState = binding.targetState as string;\n if (targetState && !stateFields.has(targetState)) {\n errors.push({\n path: `/dataBindings/${index}/targetState`,\n message: `Data binding targetState \"${targetState}\" not found in state.fields`,\n keyword: 'dataBindingReference',\n params: { targetState },\n schemaPath: '',\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验动作引用\n *\n * @description\n * 校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一\n */\nexport function validateActionReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkActionRef(action: Record<string, unknown>, path: string): void {\n const hasDefinition = !!action.actionDefinitionVersionId;\n const hasBuiltin = !!action.builtinAction;\n\n if (!hasDefinition && !hasBuiltin) {\n errors.push({\n path,\n message: 'ActionRef must specify either actionDefinitionVersionId or builtinAction',\n keyword: 'actionReference',\n params: {},\n schemaPath: '',\n });\n }\n\n // 递归检查 onSuccess 和 onError\n const onSuccess = action.onSuccess as Record<string, unknown>[] | undefined;\n if (Array.isArray(onSuccess)) {\n onSuccess.forEach((a, i) => checkActionRef(a, `${path}/onSuccess/${i}`));\n }\n\n const onError = action.onError as Record<string, unknown>[] | undefined;\n if (Array.isArray(onError)) {\n onError.forEach((a, i) => checkActionRef(a, `${path}/onError/${i}`));\n }\n }\n\n function traverseActions(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查事件处理器中的动作\n const eventHandlers = record.eventHandlers as Record<string, unknown>[] | undefined;\n if (Array.isArray(eventHandlers)) {\n eventHandlers.forEach((handler, hIndex) => {\n const actions = handler.actions as Record<string, unknown>[] | undefined;\n if (Array.isArray(actions)) {\n actions.forEach((action, aIndex) => {\n checkActionRef(action, `${path}/eventHandlers/${hIndex}/actions/${aIndex}`);\n });\n }\n });\n }\n\n // 检查生命周期钩子中的动作\n const lifecycle = record.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `${path}/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = record.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverseActions(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n\n // 从页面级生命周期开始检查\n const lifecycle = schema.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 从根节点开始遍历组件树\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverseActions(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 完整校验(结构 + 引用)\n *\n * @description\n * 执行完整的页面 Schema 校验,包括:\n * 1. JSON Schema 结构校验\n * 2. 组件引用校验\n * 3. 表达式引用校验\n * 4. 数据绑定引用校验\n * 5. 动作引用校验\n */\nexport function validatePageSchemaFull(\n data: unknown,\n availableComponents?: Map<string, Set<string>>,\n availableFields?: Set<string>,\n): ValidationResult {\n const allErrors: ValidationError[] = [];\n\n // 1. 结构校验\n const structureResult = validatePageSchema(data);\n allErrors.push(...structureResult.errors);\n\n // 如果结构校验失败,后续校验可能不准确,直接返回\n if (!structureResult.valid) {\n return { valid: false, errors: allErrors };\n }\n\n // 2. 组件引用校验(如果提供了可用组件列表)\n if (availableComponents) {\n const componentResult = validateComponentReferences(data, availableComponents);\n allErrors.push(...componentResult.errors);\n }\n\n // 3. 表达式引用校验(如果提供了可用字段列表)\n if (availableFields) {\n const expressionResult = validateExpressionReferences(data, availableFields);\n allErrors.push(...expressionResult.errors);\n }\n\n // 4. 数据绑定引用校验\n const bindingResult = validateDataBindingReferences(data);\n allErrors.push(...bindingResult.errors);\n\n // 5. 动作引用校验\n const actionResult = validateActionReferences(data);\n allErrors.push(...actionResult.errors);\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n };\n}\n\n// ============================================================\n// 导出版本信息\n// ============================================================\n\nexport const VERSION = '2.0.0';\n\n// 重新导出 Schema\nexport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n"],"mappings":"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","names":["import_contracts_schemas","ajv","Ajv","addFormats","pageSchema","lifecycle"]}
|
package/dist/index.mjs
CHANGED
|
@@ -159,7 +159,7 @@ function validateExpressionReferences(pageSchema3, availableFields) {
|
|
|
159
159
|
function traverse(obj, path) {
|
|
160
160
|
if (!obj || typeof obj !== "object") return;
|
|
161
161
|
const record = obj;
|
|
162
|
-
if (record.type && record.value && ["state", "binding", "computed"].includes(record.type)) {
|
|
162
|
+
if (record.type && record.value && ["state", "binding", "local", "template", "computed"].includes(record.type)) {
|
|
163
163
|
checkExpression(record, path);
|
|
164
164
|
}
|
|
165
165
|
for (const [key, value] of Object.entries(record)) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @djvlc/contracts-validators\n *\n * DJVLC 低代码平台预编译 JSON Schema 校验器\n *\n * 提供高性能的 Ajv 校验器,用于:\n * - 发布期校验(Editor 发布页面时)\n * - 运行时校验(Runtime 加载组件时)\n * - API 校验(Platform 接收请求时)\n *\n * V2 版本更新:\n * - 支持 PageSchema V2 Runtime Core 校验\n * - 新增表达式引用校验(支持 binding 类型)\n * - 优化错误信息格式\n */\n\nimport Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n\n// ============================================================\n// 校验器实例\n// ============================================================\n\n/**\n * 创建配置好的 Ajv 实例\n */\nfunction createAjv(): Ajv {\n const ajv = new Ajv({\n strict: true,\n allErrors: true,\n verbose: true,\n removeAdditional: false,\n useDefaults: true,\n coerceTypes: false,\n allowUnionTypes: true,\n });\n\n // 添加格式支持\n addFormats(ajv);\n\n // 添加自定义格式\n ajv.addFormat('semver', /^\\d+\\.\\d+\\.\\d+$/);\n ajv.addFormat('sha384', /^sha384-[A-Za-z0-9+/=]+$/);\n\n return ajv;\n}\n\n// 单例 Ajv 实例\nconst ajv = createAjv();\n\n// 注册所有 Schema\najv.addSchema(pageSchema, pageSchema.$id);\najv.addSchema(componentMetaSchema, componentMetaSchema.$id);\najv.addSchema(actionSpecSchema, actionSpecSchema.$id);\najv.addSchema(dataQuerySpecSchema, dataQuerySpecSchema.$id);\n\n// ============================================================\n// 校验函数\n// ============================================================\n\n/**\n * 校验结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误列表 */\n errors: ValidationError[];\n}\n\n/**\n * 校验错误\n */\nexport interface ValidationError {\n /** 错误路径 */\n path: string;\n /** 错误消息 */\n message: string;\n /** JSON Schema 关键字 */\n keyword: string;\n /** 错误参数 */\n params: Record<string, unknown>;\n /** Schema 路径 */\n schemaPath: string;\n}\n\n/**\n * 将 Ajv 错误转换为校验错误\n */\nfunction toValidationErrors(errors: ErrorObject[] | null | undefined): ValidationError[] {\n if (!errors) return [];\n\n return errors.map(error => ({\n path: error.instancePath || '/',\n message: error.message || 'Unknown error',\n keyword: error.keyword,\n params: error.params as Record<string, unknown>,\n schemaPath: error.schemaPath,\n }));\n}\n\n/**\n * 通用校验函数\n */\nfunction validate(validator: ValidateFunction, data: unknown): ValidationResult {\n const valid = validator(data);\n return {\n valid,\n errors: toValidationErrors(validator.errors),\n };\n}\n\n// ============================================================\n// 导出的校验函数\n// ============================================================\n\n// 预编译校验函数\nconst _validatePageSchema = ajv.compile(pageSchema);\nconst _validateComponentMeta = ajv.compile(componentMetaSchema);\nconst _validateActionSpec = ajv.compile(actionSpecSchema);\nconst _validateDataQuerySpec = ajv.compile(dataQuerySpecSchema);\n\n/**\n * 校验页面 Schema(V2 Runtime Core)\n */\nexport function validatePageSchema(data: unknown): ValidationResult {\n return validate(_validatePageSchema, data);\n}\n\n/**\n * 校验组件元数据\n */\nexport function validateComponentMeta(data: unknown): ValidationResult {\n return validate(_validateComponentMeta, data);\n}\n\n/**\n * 校验动作规格\n */\nexport function validateActionSpec(data: unknown): ValidationResult {\n return validate(_validateActionSpec, data);\n}\n\n/**\n * 校验数据查询规格\n */\nexport function validateDataQuerySpec(data: unknown): ValidationResult {\n return validate(_validateDataQuerySpec, data);\n}\n\n// ============================================================\n// 高级校验功能\n// ============================================================\n\n/**\n * 批量校验结果\n */\nexport interface BatchValidationResult {\n /** 总数 */\n total: number;\n /** 通过数 */\n passed: number;\n /** 失败数 */\n failed: number;\n /** 详细结果 */\n results: {\n index: number;\n valid: boolean;\n errors: ValidationError[];\n }[];\n}\n\n/**\n * 批量校验\n */\nexport function batchValidate(\n validator: (data: unknown) => ValidationResult,\n items: unknown[],\n): BatchValidationResult {\n const results = items.map((item, index) => {\n const result = validator(item);\n return {\n index,\n valid: result.valid,\n errors: result.errors,\n };\n });\n\n const passed = results.filter(r => r.valid).length;\n\n return {\n total: items.length,\n passed,\n failed: items.length - passed,\n results,\n };\n}\n\n/**\n * 校验并抛出异常\n */\nexport function validateOrThrow(\n validator: (data: unknown) => ValidationResult,\n data: unknown,\n errorMessage?: string,\n): void {\n const result = validator(data);\n if (!result.valid) {\n const message = errorMessage || 'Validation failed';\n const details = result.errors.map(e => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`${message}: ${details}`);\n }\n}\n\n// ============================================================\n// Schema 引用校验\n// ============================================================\n\n/**\n * 校验组件节点树中引用的组件版本\n */\nexport function validateComponentReferences(\n pageSchema: unknown,\n availableComponents: Map<string, Set<string>>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function traverse(node: Record<string, unknown>, path: string): void {\n const componentType = node.componentType as string;\n const componentVersion = node.componentVersion as string;\n\n if (componentType && componentVersion) {\n const versions = availableComponents.get(componentType);\n if (!versions) {\n errors.push({\n path: `${path}/componentType`,\n message: `Component \"${componentType}\" not found in registry`,\n keyword: 'componentReference',\n params: { componentType },\n schemaPath: '',\n });\n } else if (!versions.has(componentVersion)) {\n errors.push({\n path: `${path}/componentVersion`,\n message: `Version \"${componentVersion}\" of component \"${componentType}\" not found`,\n keyword: 'componentVersion',\n params: { componentType, componentVersion },\n schemaPath: '',\n });\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = node.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverse(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverse(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验表达式引用\n *\n * @description\n * V2 版本更新:支持 state、binding、computed 三种表达式类型的引用校验\n */\nexport function validateExpressionReferences(\n pageSchema: unknown,\n availableFields: Set<string>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkExpression(expr: Record<string, unknown>, path: string): void {\n const meta = expr.meta as Record<string, unknown> | undefined;\n const dependencies = meta?.dependencies as string[] | undefined;\n\n if (dependencies) {\n for (const dep of dependencies) {\n if (!availableFields.has(dep)) {\n errors.push({\n path,\n message: `Expression references unknown field: \"${dep}\"`,\n keyword: 'expressionReference',\n params: { field: dep },\n schemaPath: '',\n });\n }\n }\n }\n }\n\n function traverse(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查是否是表达式对象(V2 版本支持 state, binding, computed)\n if (\n record.type &&\n record.value &&\n ['state', 'binding', 'computed'].includes(record.type as string)\n ) {\n checkExpression(record, path);\n }\n\n // 递归遍历\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n traverse(item, `${path}/${key}/${index}`);\n });\n } else if (typeof value === 'object' && value !== null) {\n traverse(value, `${path}/${key}`);\n }\n }\n }\n\n traverse(pageSchema, '');\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验数据绑定配置\n *\n * @description\n * V2 新增:校验 dataBindings 中的 targetState 是否在 state.fields 中定义\n */\nexport function validateDataBindingReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const schema = pageSchema as Record<string, unknown>;\n\n // 获取所有状态字段\n const state = schema.state as Record<string, unknown> | undefined;\n const fields = state?.fields as Record<string, unknown> | undefined;\n const stateFields = new Set(fields ? Object.keys(fields) : []);\n\n // 校验数据绑定的 targetState\n const dataBindings = schema.dataBindings as Record<string, unknown>[] | undefined;\n if (Array.isArray(dataBindings)) {\n dataBindings.forEach((binding, index) => {\n const targetState = binding.targetState as string;\n if (targetState && !stateFields.has(targetState)) {\n errors.push({\n path: `/dataBindings/${index}/targetState`,\n message: `Data binding targetState \"${targetState}\" not found in state.fields`,\n keyword: 'dataBindingReference',\n params: { targetState },\n schemaPath: '',\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验动作引用\n *\n * @description\n * V2 新增:校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一\n */\nexport function validateActionReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkActionRef(action: Record<string, unknown>, path: string): void {\n const hasDefinition = !!action.actionDefinitionVersionId;\n const hasBuiltin = !!action.builtinAction;\n\n if (!hasDefinition && !hasBuiltin) {\n errors.push({\n path,\n message: 'ActionRef must specify either actionDefinitionVersionId or builtinAction',\n keyword: 'actionReference',\n params: {},\n schemaPath: '',\n });\n }\n\n // 递归检查 onSuccess 和 onError\n const onSuccess = action.onSuccess as Record<string, unknown>[] | undefined;\n if (Array.isArray(onSuccess)) {\n onSuccess.forEach((a, i) => checkActionRef(a, `${path}/onSuccess/${i}`));\n }\n\n const onError = action.onError as Record<string, unknown>[] | undefined;\n if (Array.isArray(onError)) {\n onError.forEach((a, i) => checkActionRef(a, `${path}/onError/${i}`));\n }\n }\n\n function traverseActions(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查事件处理器中的动作\n const eventHandlers = record.eventHandlers as Record<string, unknown>[] | undefined;\n if (Array.isArray(eventHandlers)) {\n eventHandlers.forEach((handler, hIndex) => {\n const actions = handler.actions as Record<string, unknown>[] | undefined;\n if (Array.isArray(actions)) {\n actions.forEach((action, aIndex) => {\n checkActionRef(action, `${path}/eventHandlers/${hIndex}/actions/${aIndex}`);\n });\n }\n });\n }\n\n // 检查生命周期钩子中的动作\n const lifecycle = record.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `${path}/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = record.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverseActions(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n\n // 从页面级生命周期开始检查\n const lifecycle = schema.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 从根节点开始遍历组件树\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverseActions(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 完整校验(结构 + 引用)\n *\n * @description\n * 执行完整的页面 Schema 校验,包括:\n * 1. JSON Schema 结构校验\n * 2. 组件引用校验\n * 3. 表达式引用校验\n * 4. 数据绑定引用校验\n * 5. 动作引用校验\n */\nexport function validatePageSchemaFull(\n data: unknown,\n availableComponents?: Map<string, Set<string>>,\n availableFields?: Set<string>,\n): ValidationResult {\n const allErrors: ValidationError[] = [];\n\n // 1. 结构校验\n const structureResult = validatePageSchema(data);\n allErrors.push(...structureResult.errors);\n\n // 如果结构校验失败,后续校验可能不准确,直接返回\n if (!structureResult.valid) {\n return { valid: false, errors: allErrors };\n }\n\n // 2. 组件引用校验(如果提供了可用组件列表)\n if (availableComponents) {\n const componentResult = validateComponentReferences(data, availableComponents);\n allErrors.push(...componentResult.errors);\n }\n\n // 3. 表达式引用校验(如果提供了可用字段列表)\n if (availableFields) {\n const expressionResult = validateExpressionReferences(data, availableFields);\n allErrors.push(...expressionResult.errors);\n }\n\n // 4. 数据绑定引用校验\n const bindingResult = validateDataBindingReferences(data);\n allErrors.push(...bindingResult.errors);\n\n // 5. 动作引用校验\n const actionResult = validateActionReferences(data);\n allErrors.push(...actionResult.errors);\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n };\n}\n\n// ============================================================\n// 导出版本信息\n// ============================================================\n\nexport const VERSION = '2.0.0';\n\n// 重新导出 Schema\nexport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n"],"mappings":"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","names":["pageSchema","componentMetaSchema","actionSpecSchema","dataQuerySpecSchema","ajv","lifecycle"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @djvlc/contracts-validators\n *\n * DJVLC 低代码平台预编译 JSON Schema 校验器\n *\n * 提供高性能的 Ajv 校验器,用于:\n * - 发布期校验(Editor 发布页面时)\n * - 运行时校验(Runtime 加载组件时)\n * - API 校验(Platform 接收请求时)\n */\n\nimport Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n\n// ============================================================\n// 校验器实例\n// ============================================================\n\n/**\n * 创建配置好的 Ajv 实例\n */\nfunction createAjv(): Ajv {\n const ajv = new Ajv({\n strict: true,\n allErrors: true,\n verbose: true,\n removeAdditional: false,\n useDefaults: true,\n coerceTypes: false,\n allowUnionTypes: true,\n });\n\n // 添加格式支持\n addFormats(ajv);\n\n // 添加自定义格式\n ajv.addFormat('semver', /^\\d+\\.\\d+\\.\\d+$/);\n ajv.addFormat('sha384', /^sha384-[A-Za-z0-9+/=]+$/);\n\n return ajv;\n}\n\n// 单例 Ajv 实例\nconst ajv = createAjv();\n\n// 注册所有 Schema\najv.addSchema(pageSchema, pageSchema.$id);\najv.addSchema(componentMetaSchema, componentMetaSchema.$id);\najv.addSchema(actionSpecSchema, actionSpecSchema.$id);\najv.addSchema(dataQuerySpecSchema, dataQuerySpecSchema.$id);\n\n// ============================================================\n// 校验函数\n// ============================================================\n\n/**\n * 校验结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误列表 */\n errors: ValidationError[];\n}\n\n/**\n * 校验错误\n */\nexport interface ValidationError {\n /** 错误路径 */\n path: string;\n /** 错误消息 */\n message: string;\n /** JSON Schema 关键字 */\n keyword: string;\n /** 错误参数 */\n params: Record<string, unknown>;\n /** Schema 路径 */\n schemaPath: string;\n}\n\n/**\n * 将 Ajv 错误转换为校验错误\n */\nfunction toValidationErrors(errors: ErrorObject[] | null | undefined): ValidationError[] {\n if (!errors) return [];\n\n return errors.map(error => ({\n path: error.instancePath || '/',\n message: error.message || 'Unknown error',\n keyword: error.keyword,\n params: error.params as Record<string, unknown>,\n schemaPath: error.schemaPath,\n }));\n}\n\n/**\n * 通用校验函数\n */\nfunction validate(validator: ValidateFunction, data: unknown): ValidationResult {\n const valid = validator(data);\n return {\n valid,\n errors: toValidationErrors(validator.errors),\n };\n}\n\n// ============================================================\n// 导出的校验函数\n// ============================================================\n\n// 预编译校验函数\nconst _validatePageSchema = ajv.compile(pageSchema);\nconst _validateComponentMeta = ajv.compile(componentMetaSchema);\nconst _validateActionSpec = ajv.compile(actionSpecSchema);\nconst _validateDataQuerySpec = ajv.compile(dataQuerySpecSchema);\n\n/**\n * 校验页面 Schema(V2 Runtime Core)\n */\nexport function validatePageSchema(data: unknown): ValidationResult {\n return validate(_validatePageSchema, data);\n}\n\n/**\n * 校验组件元数据\n */\nexport function validateComponentMeta(data: unknown): ValidationResult {\n return validate(_validateComponentMeta, data);\n}\n\n/**\n * 校验动作规格\n */\nexport function validateActionSpec(data: unknown): ValidationResult {\n return validate(_validateActionSpec, data);\n}\n\n/**\n * 校验数据查询规格\n */\nexport function validateDataQuerySpec(data: unknown): ValidationResult {\n return validate(_validateDataQuerySpec, data);\n}\n\n// ============================================================\n// 高级校验功能\n// ============================================================\n\n/**\n * 批量校验结果\n */\nexport interface BatchValidationResult {\n /** 总数 */\n total: number;\n /** 通过数 */\n passed: number;\n /** 失败数 */\n failed: number;\n /** 详细结果 */\n results: {\n index: number;\n valid: boolean;\n errors: ValidationError[];\n }[];\n}\n\n/**\n * 批量校验\n */\nexport function batchValidate(\n validator: (data: unknown) => ValidationResult,\n items: unknown[],\n): BatchValidationResult {\n const results = items.map((item, index) => {\n const result = validator(item);\n return {\n index,\n valid: result.valid,\n errors: result.errors,\n };\n });\n\n const passed = results.filter(r => r.valid).length;\n\n return {\n total: items.length,\n passed,\n failed: items.length - passed,\n results,\n };\n}\n\n/**\n * 校验并抛出异常\n */\nexport function validateOrThrow(\n validator: (data: unknown) => ValidationResult,\n data: unknown,\n errorMessage?: string,\n): void {\n const result = validator(data);\n if (!result.valid) {\n const message = errorMessage || 'Validation failed';\n const details = result.errors.map(e => `${e.path}: ${e.message}`).join('; ');\n throw new Error(`${message}: ${details}`);\n }\n}\n\n// ============================================================\n// Schema 引用校验\n// ============================================================\n\n/**\n * 校验组件节点树中引用的组件版本\n */\nexport function validateComponentReferences(\n pageSchema: unknown,\n availableComponents: Map<string, Set<string>>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function traverse(node: Record<string, unknown>, path: string): void {\n const componentType = node.componentType as string;\n const componentVersion = node.componentVersion as string;\n\n if (componentType && componentVersion) {\n const versions = availableComponents.get(componentType);\n if (!versions) {\n errors.push({\n path: `${path}/componentType`,\n message: `Component \"${componentType}\" not found in registry`,\n keyword: 'componentReference',\n params: { componentType },\n schemaPath: '',\n });\n } else if (!versions.has(componentVersion)) {\n errors.push({\n path: `${path}/componentVersion`,\n message: `Version \"${componentVersion}\" of component \"${componentType}\" not found`,\n keyword: 'componentVersion',\n params: { componentType, componentVersion },\n schemaPath: '',\n });\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = node.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverse(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverse(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验表达式引用\n *\n * @description\n * 校验 state、binding、local、template、computed 表达式类型的引用\n */\nexport function validateExpressionReferences(\n pageSchema: unknown,\n availableFields: Set<string>,\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkExpression(expr: Record<string, unknown>, path: string): void {\n const meta = expr.meta as Record<string, unknown> | undefined;\n const dependencies = meta?.dependencies as string[] | undefined;\n\n if (dependencies) {\n for (const dep of dependencies) {\n if (!availableFields.has(dep)) {\n errors.push({\n path,\n message: `Expression references unknown field: \"${dep}\"`,\n keyword: 'expressionReference',\n params: { field: dep },\n schemaPath: '',\n });\n }\n }\n }\n }\n\n function traverse(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查是否是表达式对象(支持 state, binding, local, template, computed)\n if (\n record.type &&\n record.value &&\n ['state', 'binding', 'local', 'template', 'computed'].includes(record.type as string)\n ) {\n checkExpression(record, path);\n }\n\n // 递归遍历\n for (const [key, value] of Object.entries(record)) {\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n traverse(item, `${path}/${key}/${index}`);\n });\n } else if (typeof value === 'object' && value !== null) {\n traverse(value, `${path}/${key}`);\n }\n }\n }\n\n traverse(pageSchema, '');\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验数据绑定配置\n *\n * @description\n * 校验 dataBindings 中的 targetState 是否在 state.fields 中定义\n */\nexport function validateDataBindingReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n const schema = pageSchema as Record<string, unknown>;\n\n // 获取所有状态字段\n const state = schema.state as Record<string, unknown> | undefined;\n const fields = state?.fields as Record<string, unknown> | undefined;\n const stateFields = new Set(fields ? Object.keys(fields) : []);\n\n // 校验数据绑定的 targetState\n const dataBindings = schema.dataBindings as Record<string, unknown>[] | undefined;\n if (Array.isArray(dataBindings)) {\n dataBindings.forEach((binding, index) => {\n const targetState = binding.targetState as string;\n if (targetState && !stateFields.has(targetState)) {\n errors.push({\n path: `/dataBindings/${index}/targetState`,\n message: `Data binding targetState \"${targetState}\" not found in state.fields`,\n keyword: 'dataBindingReference',\n params: { targetState },\n schemaPath: '',\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 校验动作引用\n *\n * @description\n * 校验 ActionRef 必须指定 actionDefinitionVersionId 或 builtinAction 之一\n */\nexport function validateActionReferences(pageSchema: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n function checkActionRef(action: Record<string, unknown>, path: string): void {\n const hasDefinition = !!action.actionDefinitionVersionId;\n const hasBuiltin = !!action.builtinAction;\n\n if (!hasDefinition && !hasBuiltin) {\n errors.push({\n path,\n message: 'ActionRef must specify either actionDefinitionVersionId or builtinAction',\n keyword: 'actionReference',\n params: {},\n schemaPath: '',\n });\n }\n\n // 递归检查 onSuccess 和 onError\n const onSuccess = action.onSuccess as Record<string, unknown>[] | undefined;\n if (Array.isArray(onSuccess)) {\n onSuccess.forEach((a, i) => checkActionRef(a, `${path}/onSuccess/${i}`));\n }\n\n const onError = action.onError as Record<string, unknown>[] | undefined;\n if (Array.isArray(onError)) {\n onError.forEach((a, i) => checkActionRef(a, `${path}/onError/${i}`));\n }\n }\n\n function traverseActions(obj: unknown, path: string): void {\n if (!obj || typeof obj !== 'object') return;\n\n const record = obj as Record<string, unknown>;\n\n // 检查事件处理器中的动作\n const eventHandlers = record.eventHandlers as Record<string, unknown>[] | undefined;\n if (Array.isArray(eventHandlers)) {\n eventHandlers.forEach((handler, hIndex) => {\n const actions = handler.actions as Record<string, unknown>[] | undefined;\n if (Array.isArray(actions)) {\n actions.forEach((action, aIndex) => {\n checkActionRef(action, `${path}/eventHandlers/${hIndex}/actions/${aIndex}`);\n });\n }\n });\n }\n\n // 检查生命周期钩子中的动作\n const lifecycle = record.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `${path}/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 递归遍历插槽中的子节点\n const slots = record.slots as Record<string, Record<string, unknown>[]> | undefined;\n if (slots && typeof slots === 'object') {\n for (const [slotName, slotChildren] of Object.entries(slots)) {\n if (Array.isArray(slotChildren)) {\n slotChildren.forEach((child, index) => {\n traverseActions(child, `${path}/slots/${slotName}/${index}`);\n });\n }\n }\n }\n }\n\n const schema = pageSchema as Record<string, unknown>;\n\n // 从页面级生命周期开始检查\n const lifecycle = schema.lifecycle as Record<string, unknown> | undefined;\n if (lifecycle) {\n for (const [hookName, actions] of Object.entries(lifecycle)) {\n if (Array.isArray(actions)) {\n (actions as Record<string, unknown>[]).forEach((action, index) => {\n checkActionRef(action, `/lifecycle/${hookName}/${index}`);\n });\n }\n }\n }\n\n // 从根节点开始遍历组件树\n const root = schema.root as Record<string, unknown>;\n if (root) {\n traverseActions(root, '/root');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * 完整校验(结构 + 引用)\n *\n * @description\n * 执行完整的页面 Schema 校验,包括:\n * 1. JSON Schema 结构校验\n * 2. 组件引用校验\n * 3. 表达式引用校验\n * 4. 数据绑定引用校验\n * 5. 动作引用校验\n */\nexport function validatePageSchemaFull(\n data: unknown,\n availableComponents?: Map<string, Set<string>>,\n availableFields?: Set<string>,\n): ValidationResult {\n const allErrors: ValidationError[] = [];\n\n // 1. 结构校验\n const structureResult = validatePageSchema(data);\n allErrors.push(...structureResult.errors);\n\n // 如果结构校验失败,后续校验可能不准确,直接返回\n if (!structureResult.valid) {\n return { valid: false, errors: allErrors };\n }\n\n // 2. 组件引用校验(如果提供了可用组件列表)\n if (availableComponents) {\n const componentResult = validateComponentReferences(data, availableComponents);\n allErrors.push(...componentResult.errors);\n }\n\n // 3. 表达式引用校验(如果提供了可用字段列表)\n if (availableFields) {\n const expressionResult = validateExpressionReferences(data, availableFields);\n allErrors.push(...expressionResult.errors);\n }\n\n // 4. 数据绑定引用校验\n const bindingResult = validateDataBindingReferences(data);\n allErrors.push(...bindingResult.errors);\n\n // 5. 动作引用校验\n const actionResult = validateActionReferences(data);\n allErrors.push(...actionResult.errors);\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n };\n}\n\n// ============================================================\n// 导出版本信息\n// ============================================================\n\nexport const VERSION = '2.0.0';\n\n// 重新导出 Schema\nexport {\n pageSchema,\n componentMetaSchema,\n actionSpecSchema,\n dataQuerySpecSchema,\n} from '@djvlc/contracts-schemas';\n"],"mappings":"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","names":["pageSchema","componentMetaSchema","actionSpecSchema","dataQuerySpecSchema","ajv","lifecycle"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djvlc/contracts-validators",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "DJV Low-code Platform - 预编译的 Ajv 校验器包",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"clean": "rimraf dist"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@djvlc/contracts-types": "1.8.
|
|
27
|
-
"@djvlc/contracts-schemas": "1.5.
|
|
26
|
+
"@djvlc/contracts-types": "1.8.2",
|
|
27
|
+
"@djvlc/contracts-schemas": "1.5.2",
|
|
28
28
|
"ajv": "^8.12.0",
|
|
29
29
|
"ajv-formats": "^3.0.1"
|
|
30
30
|
},
|