Summary

This PR adds support for generating Datastar fetch expressions directly from ZIO HTTP Endpoint definitions. Instead of manually writing Datastar request strings, developers can now automatically generate them from their endpoint definitions.

Motivation

When using Datastar with ZIO HTTP endpoints, developers had to manually construct Datastar fetch expressions like @get('/api/users'). This was error-prone and didn’t leverage the type-safe endpoint definitions we already have. This PR bridges that gap.

Changes

Core Implementation

  • EndpointRequest - New trait representing a Datastar request action with method, URL, headers, and options
  • EndpointRequestBuilder - Builder class for constructing requests from endpoints with fluent API
  • Extension method - Added toDatastarRequest to Endpoint for easy conversion
  • Helper methods - Added dataFetch shortcuts in Attributes trait for quick request creation

Features

  • ✅ Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE)
  • ✅ Handles path parameters (both actual values and signal placeholders)
  • ✅ Custom headers and request options
  • ✅ Builder pattern for flexible configuration
  • ✅ Integration with existing Datastar attributes

Testing

  • Added 30 comprehensive unit tests covering:
    • Basic request creation for all methods
    • Path parameter handling (values and signals)
    • Headers and request options
    • Integration with data-on attributes
    • HTML rendering and escaping

Documentation

  • Added example application demonstrating usage patterns
  • Inline documentation with clear examples

Usage Example

import zio.http._
import zio.http.endpoint._
// Define an endpoint
val endpoint = Endpoint(RoutePattern.GET / "api" / "users")
// Generate Datastar request - simple!
val request = endpoint.toDatastarRequest.build()
// Result: @get('/api/users')
// With path parameters
val userEndpoint = Endpoint(RoutePattern.GET / "api" / "users" / PathCodec.int("id"))
val userRequest = userEndpoint.toDatastarRequest.build(42)
// Result: @get('/api/users/42')
// With signals for dynamic values
val deleteRequest = userEndpoint.toDatastarRequest.buildWithSignals()
// Result: @get('/api/users/${id}')
// Using the shorthand helper
val fetchRequest = dataFetch.get("/api/users")

Checklist

  • Implementation complete
  • Unit tests added and passing
  • Example code provided
  • No breaking changes to existing code
  • Code follows project style guidelines

Related Issues

Closes #3697

/claim https://github.com/zio/zio-http/issues/3697

Claim

Total prize pool $250
Total paid $0
Status Pending
Submitted October 16, 2025
Last updated October 16, 2025

Contributors

AL

Ali Raza

@aliraza556

100%

Sponsors

ZI

ZIO

@ZIO

$250