neandertech / smithy4s-fetch

Smithy4s client directly using Fetch APIs, without bringing http4s/cats, to dramatically reduce bundle size
10 stars 1 forks source link
fetch scala scalajs smithy smithy4s

smithy4s-fetch

An experimental Smithy4s client backend for Scala.js, utilising Fetch directly, without introducing a http4s/cats dependency.

The purpose of this library is to provide users of Smithy4s backend services a more lightweight client for the frontend – if your Scala.js frontend is not using Cats/Cats-Effect based libraries, you can communicate with your Smithy4s backend directly using Fetch, reducing bundle size by as much as 50% in some instances.

The library is currently only available for Scala 3, but we will welcome contributions cross-compiling it to 2.13 – it should be very easy. API surface is very minimal and designed for binary compatible evolution, so after initial round of testing and gathering community feedback, we plan to release 1.0.0 and start checking binary/Tasty compatibility for each release.

Installation

Latest version: smithy4s-fetch Scala version support

Getting started

For example's sake, let's say we have a smithy4s service that models one of the endpoints from https://httpbin.org, defined using smithy4s-deriving (note we're using Scala CLI for this demo):

//> using dep "tech.neander::smithy4s-deriving::0.0.2"
//> using platform scala-js
//> using scala 3.4.2
//> using option -Wunused:all

import smithy4s.*

import scala.annotation.experimental
import scala.scalajs.js.Promise

import deriving.{given, *}
import aliases.*

case class Response(headers: Map[String, String], origin: String, url: String)
    derives Schema

@experimental
trait HttpbinService derives API:
  @readonly
  @httpGet("/get")
  def get(): Promise[Response]

Note that we only need to use @experimental annotation because we are using smithy4s-deriving. If you're creating clients for services generated by standard Smithy4s codegen, just remove all @experimental annotations you see.

To create a Fetch client for this service all we need to do is this:

import smithy4s_fetch.*

@main @experimental
def helloWorld = 
  val service: HttpbinService = 
    SimpleRestJsonFetchClient(
      API.service[HttpbinService],
      "https://httpbin.org"
     ).make.unliftService

  service.get().`then`(v => println(v))

If your locally installed Node.js version is higher than 18 (version where fetch was added into Node.js), then you can run this example for youreself by running make run-example

Contributing

If you see something that can be improved in this library – please contribute!

This is a relatively standard Scala CLI project, even though the tests run a Scala version newer than the library itself (library is published for 3.3, tests are in 3.4, to make use of smithy4s-deriving).

Here are some useful commands: