npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

frmz

v0.0.111

Published

A schema-aware reactive FormData builder with Zod validation and full Blob/File support

Readme

"Banner Image"

frmz

A schema-aware reactive FormData builder with Zod validation and full Blob/File support. Manage form state, validate data, and generate submission-ready FormData with a reactive proxy.

Features

  • Automatic Schema Inference: Derive Zod schemas from your data structures
  • Manual Schema Validation: Use custom Zod schemas for precise control
  • Reactive Data Proxy: Live updates with deep object reactivity
  • Blob & File Support: Perfect for file uploads and image handling
  • TypeScript First: Full type safety and intelligent inference
  • FormData Generation: Create fetch-ready FormData objects automatically

Installation

Copy the src/index.ts into your project if you don't want to add additional dependencies to your project or

npm install frmz zod

pnpm add frmz zod

Note: Zod is a peer dependency and must be installed separately.

Basic Usage

import { frmz } from "frmz";

// Create a form manager with automatic schema inference
const { data, getFormData } = frmz({
  user: {
    name: "Alice",
    email: "[email protected]",
    age: 30,
  },
  preferences: {
    newsletter: true,
    tags: ["tech", "programming"],
  },
});

// Update values reactively
data.user.name = "Bob"; // Changes are tracked
data.preferences.tags.push("javascript");

// Generate FormData for submission
const formData = getFormData();
// formData contains: user[name]=Bob, user[email][email protected], etc.

File Upload Example

// Handle file inputs with full type safety
document.getElementById("avatar").addEventListener("change", (e) => {
  const file = e.target.files[0];

  const { data, getFormData } = frmz({
    profile: {
      name: "John Doe",
      avatar: file, // File object handled properly
      documents: [file], // Works in arrays too
      metadata: {
        uploadDate: new Date().toISOString(),
      },
    },
  });

  // Submit to server
  fetch("/api/upload", {
    method: "POST",
    body: getFormData(), // Contains the file properly
  });
});

Advanced Schema Validation

import { z } from "zod";
import { frmz } from "frmz";

const userSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
  avatar: z.instanceof(Blob).optional(),
  age: z.number().min(18),
  tags: z.array(z.string()),
});

const { data, getFormData } = frmz(
  {
    name: "Alice",
    email: "[email protected]",
    age: 25,
    tags: ["developer"],
    avatar: someFile, // Optional blob
  },
  userSchema // Custom schema override
);

API Reference

1. frmz(initialData)

Creates a form manager with inferred schema.

Parameters:

  • initialData: Object or array to use as initial state

Returns:

  • data: Reactive proxy of the initial data
  • getFormData(): FormData: Function that returns current state as FormData

2. frmz(initialData, schema)

Creates a form manager with custom Zod schema.

Parameters:

  • initialData: Data matching the provided schema
  • schema: Zod schema for validation

Returns:

  • data: Reactive proxy of validated data
  • getFormData(): FormData: Function that returns current state as FormData

Reactive Data Pattern

The data object is a deep proxy that tracks changes:

const { data, getFormData } = frmz({
  user: { name: "Alice", settings: { darkMode: true } },
});

// All changes are tracked
data.user.name = "Bob"; // Simple property
data.user.settings.darkMode = false; // Nested property
data.user.settings.fontSize = 16; // New properties

// getFormData() captures all current changes
const formData = getFormData(); // Contains latest state

FormData Output Format

The generated FormData uses standard encoding:

Object properties:

user[name]=Alice
user[email][email protected]

Array elements:

tags[0]=tech
tags[1]=programming

File uploads:

tags[0]=tech
tags[1]=programming

## Type Utilities DeepWritable<T> Utility type to make deeply nested readonly types writable:

import type { DeepWritable } from "frmz";

type User = DeepWritable<typeof userSchema>;
// Now all properties are mutable

Error Handling

The library throws Zod validation errors when provided data doesn't match the schema:

try {
  const manager = frmz(
    { email: "invalid-email" },
    z.object({ email: z.string().email() })
  );
} catch (error) {
  console.error("Validation failed:", error.errors);
}

Common Use Cases

  1. Form State Management

    const { data, getFormData } = frmz(initialFormState);
    
    // Bind to input events
    input.addEventListener("change", (e) => {
      data.user.name = e.target.value;
    });
    
    // Submit handler
    form.addEventListener("submit", async (e) => {
      e.preventDefault();
      await fetch("/submit", { body: getFormData() });
    });
  2. File Upload Forms

    const { data, getFormData } = frmz({
      title: "",
      description: "",
      attachments: [], // Will hold files
    });
    
    // Add files to array
    fileInput.addEventListener("change", (e) => {
      data.attachments.push(...e.target.files);
    });
  3. Configuration Objects

    const { data, getFormData } = frmz({
      settings: {
        theme: "dark",
        notifications: true,
        layout: { grid: true, spacing: 2 },
      },
    });

Limitations

  • Root Types: Only objects and arrays are supported as root values

  • FormData Encoding: Uses standard multipart/form-data encoding (not JSON)

  • Circular References: Not supported in the data structure

  • Server Processing: Requires server-side support for bracket notation (e.g.,user[name])

 Browser Support

Works in all modern browsers that support:

  • Proxy API (ES2015)

  • FormData API

  • Blob/File API

 Contributing

Found an issue? Want to add a feature? Please open an issue or PR on our GitHub repository.

 License

MIT License - feel free to use in your projects!