Skip to content

feat: extend complex formdata support to StandardSchema #1697

Open
Teyik0 wants to merge 17 commits intoelysiajs:mainfrom
Teyik0:main
Open

feat: extend complex formdata support to StandardSchema #1697
Teyik0 wants to merge 17 commits intoelysiajs:mainfrom
Teyik0:main

Conversation

@Teyik0
Copy link
Contributor

@Teyik0 Teyik0 commented Jan 25, 2026

My precedent works on complex formdata was not complete, this one should end my journey around complex formdata and put Elysia in a good state regarding limited support on this on others frameworks.

This PR has two primary goals:

  1. ✅ Multipart FormData support for Standard Schema (previously TypeBox-only)
  2. ✅ Nested file upload support for both TypeBox and Standard Schema (previously impossible even with TypeBox)

Feature
Clients can now combine JSON stringify with dot notation to optimize bandwidth and support complex nested structures with files:

example ->

// Client - Mixed notation approach
const formData = new FormData()

// Pure dot notation
formData.append('user.name', 'John')
formData.append('user.avatar', fileBlob)
formData.append('user.photos[0]', photo1)
formData.append('user.photos[1]', photo2)

// Mixed: JSON stringify + dot notation for files
formData.append(
  'images.update[0]',
  JSON.stringify({
    id: '123',
    altText: 'an image'
  })
)
// Files merged intelligently into the object
formData.append('images.update[0].img', Bun.file('image.jpg'))

// Server receives unified structure:
// {
//   user: { name: 'John', avatar: File, photos: [File, File] },
//   images: { update: [{ id: '123', altText: 'an image', img: File }] }
// }
// Then validation can happen

No breaking change, fully tested with complex example (maybe too much).
I think that all edge case are handled.
Next-step (if review ok), update Eden to handle nested image as well.

Summary by CodeRabbit

  • New Features

    • Added an example demonstrating nested multipart file uploads using dot-notation keys and multiple endpoints for common nested patterns.
  • Improvements

    • More robust form-data parsing for complex nested structures, including array notation support.
    • Added defenses to prevent prototype-pollution via form keys.
  • Tests

    • Substantially expanded test coverage for nested multipart forms, mixed file/field payloads, coercion, and security scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

claude and others added 16 commits January 22, 2026 08:06
…orms

Adds support for nested file uploads in multipart forms using dot notation.
This enables organizing files and data in nested structures while maintaining
compatibility with standard multipart/form-data encoding.

Changes:
- Add setNestedValue helper to reconstruct nested objects from dot notation
- Update multipart parser in dynamic-handle.ts (3 locations)
- Update code generation in web-standard adapter
- Bun adapter inherits changes automatically via WebStandardAdapter
- Add comprehensive tests for nested file uploads
- Add example demonstrating nested file upload patterns

Key features:
- Works with any validation library (universal support)
- Zero overhead for flat forms (fast path preserved)
- Handles deeply nested structures (e.g., "user.profile.photo")
- Supports mixed flat and nested fields
- Type-safe with TypeBox schemas

Client usage:
  const formData = new FormData()
  formData.append('user.name', 'John')
  formData.append('user.avatar', fileBlob)
  // Server receives: { user: { name: 'John', avatar: File } }

Related to nested object coercing that already handles nested objects
by stringifying them - this extends that pattern to support File objects
which cannot be stringified.
- Add phantom type markers (__elysia_objectstring__, __elysia_arraystring__) to ObjectString and ArrayString types for future Eden auto-detection
- Make ObjectString.Decode() accept both JSON strings and already-decoded objects
- Enables both stringify (compact) and dot notation (universal) strategies to work seamlessly
- Backward compatible: all existing tests pass
- Prepares for Eden smart auto-detection feature
…rt-eF4Rq

feat: add nested file upload support with dot notation in multipart forms
Extended the nested object reconstruction to handle array indices in multipart
form keys (e.g., `images.create[0]`, `items[1].name`).

Changes:
- Updated setNestedValue() to parse and handle array index notation [N]
- Arrays are automatically initialized when indices are detected
- Code generation in web-standard adapter updated for array support
- Added comprehensive test for complex nested arrays with files

This enables schemas like:
  t.Object({
    images: t.Object({
      create: t.Files(),
      update: t.Array(t.Object({
        id: t.String(),
        img: t.File()
      }))
    })
  })

All 49 body validator tests pass.
…rt-eF4Rq

feat: add array index support in nested multipart form parsing
Block dangerous keys (__proto__, constructor, prototype) to prevent
prototype pollution attacks in nested file upload feature.

Changes:
- Add validation in setNestedValue() to block dangerous keys
- Add protection in generated multipart parser code
- Add security tests for prototype pollution scenarios

Security Impact:
- Prevents attackers from injecting properties into Object.prototype
- Blocks pollution via dot notation (e.g., user.__proto__.isAdmin)
- Blocks pollution via array notation (e.g., items[__proto__])

Tests:
- 53 existing tests pass
- 3 new security tests added
- Zero performance impact

Fixes security issues identified by cubic-dev-ai bot in PR #4
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 25, 2026

Walkthrough

Adds nested/dot-notation multipart/form-data parsing and normalization, prototype-pollution guards, adapter/handler integration for nested arrays/objects and files, a new example, and extensive tests for nested form handling and security.

Changes

Cohort / File(s) Summary
Example Usage
example/nested-multipart-files.ts
New example demonstrating nested multipart file uploads via dot-notation (multiple endpoints: /user/profile, /user/portfolio, /post) and client usage comments.
Adapter (web-standard)
src/adapter/web-standard/index.ts
Adds dangerous key guards, parseArrayKey, enhanced formData parsing, JSON/string merging with File(s), and safe nested assignment logic to prevent prototype pollution.
Dynamic Handler
src/dynamic-handle.ts
Introduces ARRAY_INDEX_REGEX, DANGEROUS_KEYS, isDangerousKey, parseArrayKey, parseObjectString, setNestedValue, normalizeFormValue; routes multipart/form-data through normalization and supports nested dot/array notation and async decode unwrapping.
Type System Formatting
src/type-system/index.ts
Formatting/line-break adjustments only; no API or behavioral changes.
Type System Tests
test/type-system/formdata.test.ts
Re-enabled and expanded tests for nested objects/files, numeric coercion, repeated array fields, and updated assertions using response-based matching.
Validator Tests
test/validator/body.test.ts
Large suite of new tests covering nested/dot-notation formdata, arrays-with-files, mixed payloads, and prototype-pollution defenses (__proto__, constructor, array index cases).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Adapter as WebStandardAdapter
  participant Handler as DynamicHandler
  participant Validator
  participant Route as RouteHandler

  Client->>Adapter: POST multipart/form-data (dot-notation keys, files)
  Adapter->>Adapter: parse FormData, detect arrays/JSON, guard dangerous keys
  Adapter->>Handler: pass normalized key/value map
  Handler->>Handler: normalizeFormValue -> setNestedValue (handle arrays/files)
  Handler->>Validator: validate/ decode body (may be async)
  Validator-->>Handler: validated body
  Handler->>Route: invoke route handler with nested body
  Route-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Fix nested formdata #1607: Related work on nested multipart/form-data coercion and schema rewrites to support nested form-data coercion.

Poem

🐰 I stitched the dots into a thread,

Files and fields tucked in my bed,
No proto trick can find its place,
Nested maps now hold their space,
Hooray—uploads hop with grace! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: extend complex formdata support to StandardSchema' clearly describes the main change: extending multipart/form-data support to Standard Schema and enabling nested file uploads, which aligns with the primary objectives and the majority of code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 25, 2026

Open in StackBlitz

npm i https://pkg.pr.new/elysiajs/elysia@1697

commit: 563a873

@Teyik0 Teyik0 marked this pull request as ready for review January 25, 2026 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants