Files
overleaf-cep/libraries/validation-tools/validateSchema.js
Andrew Rumble 632299d7b5 Merge pull request #31723 from overleaf/ar-do-not-queue-invalid-analytics-messages
[analytics] do not queue invalid analytics messages

GitOrigin-RevId: 9182fe41974ab618e7a51330bfba6703894295f4
2026-03-23 09:05:29 +00:00

70 lines
1.7 KiB
JavaScript

// @ts-check
const { isZodErrorLike } = require('zod-validation-error')
/**
* @typedef {import('zod').ZodType} ZodType
*/
/**
* @template T
* @typedef {import('zod').output<T>} output<T>
*/
/**
* A helper function to safely get a nested value from an object
* using a path array (e.g., ["query", "resource_type"])
* @param {any} data
* @param {Array<PropertyKey>} path
*/
function getPathValue(data, path) {
let current = data
for (const key of path) {
if (current === null || typeof current !== 'object') {
return undefined
}
current = current[key]
}
return current
}
/**
* @param {any} issue
* @param {any} value
*/
const isRequiredError = (issue, value) =>
value === undefined &&
(issue.code === 'invalid_type' || issue.code === 'invalid_union')
/**
* Validates data against a Zod schema and throws a user-friendly error.
*
* @template {ZodType} T
* @param {T} schema - The Zod schema
* @param {unknown} data - The data to validate
* @returns {output<T>} The validated (and transformed) data
*/
function validateSchema(schema, data) {
try {
return schema.parse(data)
} catch (err) {
if (isZodErrorLike(err)) {
const errorMessages = err.issues.map(issue => {
const value = getPathValue(data, issue.path)
if (issue.path.length === 0) {
return issue.message
}
const fieldName = String(issue.path[issue.path.length - 1])
if (isRequiredError(issue, value)) {
return `"${fieldName}" is required`
}
return `"${fieldName}" - ` + issue.message
})
throw new Error(errorMessages.join('; '))
}
throw err
}
}
module.exports = { validateSchema }