Yup โ
Schema-based form validation, built on Yup. You don't call Yup's .validate() yourself โ you build a schema, keep an error object, and run it through the validation helpers from useMonoUtility (validateAllSchema, validateSchema, validateAllSchemaCheck, clearSchemaValidation). Yup is an optional dependency: skip it if an app has no forms to validate.
The pattern โ
Three pieces: a reactive input, a Yup schema, and an error object that mirrors the form โ each field holding { valid, message }. The helpers fill the error object for you.
ts
import * as yup from 'yup'
import { useMonoUtility } from 'mono-utils/runtime'
const { validateAllSchema, validateSchema, clearSchemaValidation } = useMonoUtility()
const input = ref({ username: '', password: '' })
const schema = yup.object().shape({
username: yup.string().required('Username is required'),
password: yup.string().min(6, 'Min 6 characters').required('Password is required'),
})
// one { valid, message } slot per field
const error = ref({
username: { valid: true, message: '' },
password: { valid: true, message: '' },
})Validate the whole form (the callback runs only when everything passes):
ts
await validateAllSchema(
{ schema, input: input.value, error: error.value },
async () => { await submit() }, // valid โ proceed
)Validate a single field (e.g. on blur) โ updates just that field's error slot:
ts
await validateSchema({ field: 'username', schema, input: input.value, error: error.value })Reset all messages/flags with clearSchemaValidation({ error }), and check current validity with validateAllSchemaCheck(error) (true if any field is invalid). See Useful Utils for the full signatures.
Typed schema + error
mono-utils/runtime also exports helper types โ SchemaObject<T> (a typed .shape<โฆ>()) and ValidateError<T> / MonoValidateError (the { valid, message } map) โ for full type-safety on nested forms. Import them when you want the compiler to check your schema against your input type.
Where it plugs in โ
The validation state (error[field].valid / .message) drives the form controls โ bind it to the validation-state / validation-message props on <mono-input>, <mono-select>, etc., so a failed field shows its message inline.
Optional dependency โ
yup is an optional peer of mono-utils โ install it only in apps that validate forms. The app owns the schemas (you write yup.object().shape(...)), so Yup lives in the app the same way notivue does. Without it, the validation helpers simply aren't used; everything else in mono-utils works unchanged.
Vite interop (tiny-case) โ handled for you
yup imports the CommonJS tiny-case, which has no named ESM exports, so a Vite dev server would normally throw doesn't provide an export named 'snakeCase' when it hits mono-utils's validation helpers. mono-utils bundles its own copy of yup (and tiny-case) into its dist at build time, so that chain never reaches your app โ no optimizeDeps / ssr.noExternal wiring is needed in either a Nuxt or a plain-Vite host.
The yup you install in your app (for authoring schemas) is a separate, normal dependency that Vite pre-bundles automatically the first time it's imported. Same version as mono-utils's bundled copy, so schemas built with your yup validate correctly through the helpers.