function validateAgainstSchema(value, schema) {
  const errors = [];
  walk(value, schema, "$", errors);
  return errors;
}
function walk(value, schema, path, errors) {
  if (schema.type) {
    const types = Array.isArray(schema.type) ? schema.type : [schema.type];
    if (!types.some((t) => matchesType(value, t))) {
      errors.push({
        path,
        message: `expected type ${types.join("|")} but got ${actualType(value)}`
      });
      return;
    }
  }
  if (schema.type === "object" && value && typeof value === "object") {
    const obj = value;
    for (const req of schema.required ?? []) {
      if (obj[req] === void 0) {
        errors.push({ path: `${path}.${req}`, message: "required" });
      }
    }
    for (const [k, sub] of Object.entries(schema.properties ?? {})) {
      if (obj[k] !== void 0) {
        walk(obj[k], sub, `${path}.${k}`, errors);
      }
    }
  }
  if (schema.type === "array" && Array.isArray(value) && schema.items) {
    value.forEach(
      (item, i) => walk(item, schema.items, `${path}[${i}]`, errors)
    );
  }
}
function matchesType(value, type) {
  switch (type) {
    case "string":
      return typeof value === "string";
    case "number":
    case "integer":
      return typeof value === "number";
    case "boolean":
      return typeof value === "boolean";
    case "null":
      return value === null;
    case "array":
      return Array.isArray(value);
    case "object":
      return value !== null && typeof value === "object" && !Array.isArray(value);
    default:
      return true;
  }
}
function actualType(value) {
  if (value === null) return "null";
  if (Array.isArray(value)) return "array";
  return typeof value;
}
export {
  validateAgainstSchema
};
//# sourceMappingURL=validate.js.map