{"id":46612990,"url":"https://github.com/draftswithea/frmz","last_synced_at":"2026-03-07T19:01:00.006Z","repository":{"id":317932896,"uuid":"1048730990","full_name":"draftswithea/frmz","owner":"draftswithea","description":"A lightweight, schema-aware reactive FormData builder with Zod validation and full Blob/File support","archived":false,"fork":false,"pushed_at":"2025-09-02T00:05:24.000Z","size":1539,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-05T20:36:23.761Z","etag":null,"topics":["blob","file","file-upload","form","form-validation","proxy","react","schema","solid","svelte","typescript","vue","zod"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/frmz","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/draftswithea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-02T00:01:40.000Z","updated_at":"2025-09-02T00:05:27.000Z","dependencies_parsed_at":"2025-10-09T15:00:34.251Z","dependency_job_id":null,"html_url":"https://github.com/draftswithea/frmz","commit_stats":null,"previous_names":["techwithmanuel/frmz","draftswithea/frmz"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/draftswithea/frmz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftswithea%2Ffrmz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftswithea%2Ffrmz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftswithea%2Ffrmz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftswithea%2Ffrmz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/draftswithea","download_url":"https://codeload.github.com/draftswithea/frmz/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/draftswithea%2Ffrmz/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30226749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T18:12:09.766Z","status":"ssl_error","status_checked_at":"2026-03-07T18:11:58.786Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blob","file","file-upload","form","form-validation","proxy","react","schema","solid","svelte","typescript","vue","zod"],"created_at":"2026-03-07T19:00:41.675Z","updated_at":"2026-03-07T19:00:59.991Z","avatar_url":"https://github.com/draftswithea.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![\"Banner Image\"](/public/banner.png)\n\n# frmz\n\nA 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.\n\n## Features\n\n- ✅ **Automatic Schema Inference**: Derive Zod schemas from your data structures\n- ✅ **Manual Schema Validation**: Use custom Zod schemas for precise control\n- ✅ **Reactive Data Proxy**: Live updates with deep object reactivity\n- ✅ **Blob \u0026 File Support**: Perfect for file uploads and image handling\n- ✅ **TypeScript First**: Full type safety and intelligent inference\n- ✅ **FormData Generation**: Create fetch-ready FormData objects automatically\n\n## Installation\n\nCopy the `src/index.ts` into your project if you don't want to add additional dependencies to your project or\n\n```bash\nnpm install frmz zod\n\npnpm add frmz zod\n```\n\nNote: Zod is a peer dependency and must be installed separately.\n\n## Basic Usage\n\n```ts\nimport { frmz } from \"frmz\";\n\n// Create a form manager with automatic schema inference\nconst { data, getFormData } = frmz({\n  user: {\n    name: \"Alice\",\n    email: \"alice@example.com\",\n    age: 30,\n  },\n  preferences: {\n    newsletter: true,\n    tags: [\"tech\", \"programming\"],\n  },\n});\n\n// Update values reactively\ndata.user.name = \"Bob\"; // Changes are tracked\ndata.preferences.tags.push(\"javascript\");\n\n// Generate FormData for submission\nconst formData = getFormData();\n// formData contains: user[name]=Bob, user[email]=alice@example.com, etc.\n```\n\n## File Upload Example\n\n```ts\n// Handle file inputs with full type safety\ndocument.getElementById(\"avatar\").addEventListener(\"change\", (e) =\u003e {\n  const file = e.target.files[0];\n\n  const { data, getFormData } = frmz({\n    profile: {\n      name: \"John Doe\",\n      avatar: file, // File object handled properly\n      documents: [file], // Works in arrays too\n      metadata: {\n        uploadDate: new Date().toISOString(),\n      },\n    },\n  });\n\n  // Submit to server\n  fetch(\"/api/upload\", {\n    method: \"POST\",\n    body: getFormData(), // Contains the file properly\n  });\n});\n```\n\n## Advanced Schema Validation\n\n```ts\nimport { z } from \"zod\";\nimport { frmz } from \"frmz\";\n\nconst userSchema = z.object({\n  name: z.string().min(2),\n  email: z.string().email(),\n  avatar: z.instanceof(Blob).optional(),\n  age: z.number().min(18),\n  tags: z.array(z.string()),\n});\n\nconst { data, getFormData } = frmz(\n  {\n    name: \"Alice\",\n    email: \"alice@example.com\",\n    age: 25,\n    tags: [\"developer\"],\n    avatar: someFile, // Optional blob\n  },\n  userSchema // Custom schema override\n);\n```\n\n## API Reference\n\n### 1. `frmz(initialData)`\n\nCreates a form manager with inferred schema.\n\n**Parameters:**\n\n- `initialData`: Object or array to use as initial state\n\n**Returns:**\n\n- `data`: Reactive proxy of the initial data\n- `getFormData()`: FormData: Function that returns current state as FormData\n\n### 2. `frmz(initialData, schema)`\n\nCreates a form manager with custom Zod schema.\n\n**Parameters:**\n\n- `initialData`: Data matching the provided schema\n- `schema`: Zod schema for validation\n\n**Returns:**\n\n- `data`: Reactive proxy of validated data\n- `getFormData()`: FormData: Function that returns current state as FormData\n\n## Reactive Data Pattern\n\nThe `data` object is a deep proxy that tracks changes:\n\n```ts\nconst { data, getFormData } = frmz({\n  user: { name: \"Alice\", settings: { darkMode: true } },\n});\n\n// All changes are tracked\ndata.user.name = \"Bob\"; // Simple property\ndata.user.settings.darkMode = false; // Nested property\ndata.user.settings.fontSize = 16; // New properties\n\n// getFormData() captures all current changes\nconst formData = getFormData(); // Contains latest state\n```\n\n### FormData Output Format\n\nThe generated FormData uses standard encoding:\n\n**Object properties:**\n\n```text\nuser[name]=Alice\nuser[email]=alice@example.com\n```\n\n**Array elements:**\n\n```text\ntags[0]=tech\ntags[1]=programming\n```\n\n**File uploads:**\n\n```text\ntags[0]=tech\ntags[1]=programming\n```\n\n## Type Utilities\n`DeepWritable\u003cT\u003e`\nUtility type to make deeply nested readonly types writable:\n\n```typescript\nimport type { DeepWritable } from \"frmz\";\n\ntype User = DeepWritable\u003ctypeof userSchema\u003e;\n// Now all properties are mutable\n```\n\n## Error Handling\n\nThe library throws Zod validation errors when provided data doesn't match the schema:\n\n```typescript\ntry {\n  const manager = frmz(\n    { email: \"invalid-email\" },\n    z.object({ email: z.string().email() })\n  );\n} catch (error) {\n  console.error(\"Validation failed:\", error.errors);\n}\n```\n\n## Common Use Cases\n\n1. Form State Management\n\n   ```ts\n   const { data, getFormData } = frmz(initialFormState);\n\n   // Bind to input events\n   input.addEventListener(\"change\", (e) =\u003e {\n     data.user.name = e.target.value;\n   });\n\n   // Submit handler\n   form.addEventListener(\"submit\", async (e) =\u003e {\n     e.preventDefault();\n     await fetch(\"/submit\", { body: getFormData() });\n   });\n   ```\n\n2. File Upload Forms\n\n   ```ts\n   const { data, getFormData } = frmz({\n     title: \"\",\n     description: \"\",\n     attachments: [], // Will hold files\n   });\n\n   // Add files to array\n   fileInput.addEventListener(\"change\", (e) =\u003e {\n     data.attachments.push(...e.target.files);\n   });\n   ```\n\n3. Configuration Objects\n   ```ts\n   const { data, getFormData } = frmz({\n     settings: {\n       theme: \"dark\",\n       notifications: true,\n       layout: { grid: true, spacing: 2 },\n     },\n   });\n   ```\n\n## Limitations\n\n- Root Types: Only objects and arrays are supported as root values\n\n- FormData Encoding: Uses standard multipart/form-data encoding (not JSON)\n\n- Circular References: Not supported in the data structure\n\n- Server Processing: Requires server-side support for bracket notation (e.g.,`user[name]`)\n\n##  Browser Support\n\nWorks in all modern browsers that support:\n\n- Proxy API (ES2015)\n\n- FormData API\n\n- Blob/File API\n\n##  Contributing\n\nFound an issue? Want to add a feature? Please open an issue or PR on our GitHub repository.\n\n##  License\n\nMIT License - feel free to use in your projects!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdraftswithea%2Ffrmz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdraftswithea%2Ffrmz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdraftswithea%2Ffrmz/lists"}