ViraStack
  • Academy
  • About
  • Support
HomeGet StartedExamples

Getting started

  • Introduction
  • Upgrade from v1
  • llms.txt
  • llms-full.txt

Usage

  • useViraMask()
  • Custom mask
  • Validation
  • Server
  • Helpers
  • Types
  • UI libraries

Server

Use the same schema in Server Components and Server Actions with @virastack/mask/server.

Server entry

The root entry (@virastack/mask) ships the hook, so it carries "use client". In Server Components, Server Actions and shared schema files use @virastack/mask/server: it has createMask, definePreset, the validators, toMinorUnits and parseMasked.

// lib/checkout-masks.ts — no "use client"
import type { MaskSchema } from "@virastack/mask/server"
 
export const checkoutMasks = {
  phone: { preset: "phone", country: "TR" },
  card: "card",
  cvv: { preset: "cvv", from: "card" },
  price: { preset: "currency", from: "currency" },
} as const satisfies MaskSchema
import { createMask } from "@virastack/mask/server"
 
const phone = createMask({ preset: "phone", country: "TR" })
 
export default async function Customers() {
  const customers = await getCustomers()
  return customers.map((c) => <p key={c.id}>{phone.format(c.phone)}</p>) // (555) 123 45 67
}

Server Action

parseMasked takes FormData, URLSearchParams or a plain object. It parses masked text (when the form posts without JavaScript) or raw values, validates them and turns names like address.zip into nested objects.

"use server"
import { parseMasked } from "@virastack/mask/server"
import { checkoutMasks } from "@/lib/checkout-masks"
 
export async function checkout(formData: FormData) {
  const result = parseMasked(checkoutMasks, formData)
  if (!result.success) return { errors: result.errors } // { phone: "phone.incomplete" }
 
  // result.data: { phone: "5551234567", card: "4111…", price: "1234.56", currency: "TRY" }
}

Standard Schema

Pass any Standard Schema (Zod, Valibot, ArkType…) as the third argument. The package doesn't depend on them; it only uses the shared interface. With a schema the result is a Promise.

import { z } from "zod"
 
const schema = z.object({
  phone: z.string().length(10),
  price: z.string().transform(Number),
  currency: z.enum(["TRY", "USD"]),
})
 
const result = await parseMasked(checkoutMasks, formData, schema)
// masks are parsed and validated first, then the schema runs
// result.data → z.output<typeof schema>
PreviousValidationNextHelpers

On this page

  • Server entry
  • Server Action
  • Standard Schema
Something wrong? Fix it