UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

174 lines (173 loc) 6.7 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import { Guard } from "typebox/guard"; import { Check } from "typebox/schema"; //#region packages/normalization-core/src/json-schema.ts const schemaMapKeywords = /* @__PURE__ */ new Set([ "$defs", "definitions", "dependentSchemas", "patternProperties", "properties" ]); const schemaValueKeywords = /* @__PURE__ */ new Set([ "additionalItems", "additionalProperties", "contains", "else", "if", "items", "not", "propertyNames", "then", "unevaluatedItems", "unevaluatedProperties" ]); const schemaArrayKeywords = /* @__PURE__ */ new Set([ "allOf", "anyOf", "oneOf", "prefixItems" ]); const schemaResourceKeywords = /* @__PURE__ */ new Set([ "$anchor", "$defs", "$dynamicAnchor", "$id", "$recursiveAnchor", "$schema", "$vocabulary", "definitions" ]); function normalizeSchemaMap(value) { if (!isRecord(value)) return value; return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, normalizeJsonSchemaNode(entry)])); } function compilesUnicodePattern(pattern) { try { new RegExp(pattern, "u"); return true; } catch { return false; } } function repairJsonSchemaPatternForUnicodeRegExp(pattern) { if (compilesUnicodePattern(pattern)) return pattern; const repaired = pattern.replace(/\\([^\\])/g, (match, ch) => { if (ch === ":" || ch === "/") return ch; return match; }); return compilesUnicodePattern(repaired) ? repaired : pattern; } function normalizeSchemaDependencies(value) { if (!isRecord(value)) return value; return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, isStringArray(entry) ? entry : normalizeJsonSchemaNode(entry)])); } function normalizePatternProperties(value) { const normalized = /* @__PURE__ */ new Map(); for (const [pattern, propertySchema] of Object.entries(value)) { const repairedPattern = repairJsonSchemaPatternForUnicodeRegExp(pattern); const repairedSchema = normalizeJsonSchemaNode(propertySchema); const existingSchema = normalized.get(repairedPattern); normalized.set(repairedPattern, existingSchema === void 0 ? repairedSchema : { allOf: [existingSchema, repairedSchema] }); } return Object.fromEntries(normalized); } function expandJsonSchemaTypeArray(schema) { const { nullable, type, ...rest } = schema; const types = Array.isArray(type) ? [...type] : typeof type === "string" ? [type] : null; if (!types) return schema; if (nullable === true && !types.includes("null")) types.push("null"); if (types.length === 1 && !Array.isArray(type)) return schema; const entries = Object.entries(rest); const resourceEntries = entries.filter(([key]) => schemaResourceKeywords.has(key)); const branch = Object.fromEntries(entries.filter(([key]) => !schemaResourceKeywords.has(key))); return { ...Object.fromEntries(resourceEntries), anyOf: types.map((entry) => Object.assign({}, branch, { type: entry })) }; } function normalizeAdditionalPropertiesSchema(schema) { if (!isRecord(schema.additionalProperties) || isRecord(schema.properties) || isRecord(schema.patternProperties)) return schema; const { additionalProperties, ...rest } = schema; return { ...rest, patternProperties: { ".*": additionalProperties }, additionalProperties: false }; } function normalizeJsonSchemaNode(schema) { if (Array.isArray(schema)) return schema.map((entry) => normalizeJsonSchemaNode(entry)); if (!isRecord(schema)) return schema; const normalizedSchema = normalizeAdditionalPropertiesSchema(expandJsonSchemaTypeArray(schema.nullable === true && schema.enumIncludesNull === true && Array.isArray(schema.enum) && !schema.enum.some((entry) => entry === null) ? { ...schema, enum: [...schema.enum, null] } : schema)); return Object.fromEntries(Object.entries(normalizedSchema).map(([key, value]) => { if (key === "$dynamicRef" && normalizedSchema.$ref === void 0) return ["$ref", value]; if (key === "pattern" && typeof value === "string") return [key, repairJsonSchemaPatternForUnicodeRegExp(value)]; if (key === "patternProperties" && isRecord(value)) return [key, normalizePatternProperties(value)]; if (schemaMapKeywords.has(key)) return [key, normalizeSchemaMap(value)]; if (key === "dependencies") return [key, normalizeSchemaDependencies(value)]; if (schemaValueKeywords.has(key) || schemaArrayKeywords.has(key)) return [key, normalizeJsonSchemaNode(value)]; return [key, value]; })); } function isStringArray(value) { return Array.isArray(value) && value.every((entry) => typeof entry === "string"); } function isJsonValue(value, active = /* @__PURE__ */ new WeakSet(), complete = /* @__PURE__ */ new WeakSet()) { if (value === null || typeof value === "string" || typeof value === "boolean") return true; if (typeof value === "number") return Number.isFinite(value); if (typeof value !== "object") return false; let entries; try { if (Array.isArray(value)) { const ownKeys = Reflect.ownKeys(value); if (ownKeys.length !== value.length + 1 || ownKeys.some((key) => { if (key === "length") return false; if (typeof key !== "string") return true; const index = Number(key); return !Number.isSafeInteger(index) || index < 0 || index >= value.length || String(index) !== key; })) return false; entries = value; } else { const prototype = Object.getPrototypeOf(value); if (prototype !== Object.prototype && prototype !== null) return false; if (Reflect.ownKeys(value).some((key) => typeof key !== "string" || !Object.prototype.propertyIsEnumerable.call(value, key))) return false; entries = Object.values(value); } } catch { return false; } if (complete.has(value)) return true; if (active.has(value)) return false; active.add(value); const valid = entries.every((entry) => isJsonValue(entry, active, complete)); active.delete(value); if (valid) complete.add(value); return valid; } /** Normalize JSON Schema constructs into the TypeBox runtime subset used by validators. */ function normalizeJsonSchemaForTypeBox(schema) { return normalizeJsonSchemaNode(schema); } /** Compare acyclic JSON values using the same equality semantics as TypeBox. */ function jsonSchemaValuesEqual(left, right) { if (!isJsonValue(left) || !isJsonValue(right)) return false; try { return Guard.IsDeepEqual(left, right); } catch { return false; } } /** Validate an acyclic JSON value against the canonical normalized schema. */ function isJsonSchemaValueValid(schema, value) { if (!isJsonValue(value)) return false; try { return Check(normalizeJsonSchemaForTypeBox(schema), value); } catch { return false; } } //#endregion export { jsonSchemaValuesEqual as n, normalizeJsonSchemaForTypeBox as r, isJsonSchemaValueValid as t };