fermyon / spin-js-sdk

https://developer.fermyon.com/spin/javascript-components
Apache License 2.0
52 stars 18 forks source link

Improving routing? #87

Closed radu-matei closed 1 year ago

radu-matei commented 1 year ago

Scenario: I am trying to build a single component that can handle multiple paths. How should one handle routing inside a component?

Here is what I currently have:

export const handleRequest: HandleRequest = async function(
  request: HttpRequest
): Promise<HttpResponse> {
  switch (request.headers["spin-path-info"]) {
    case "/list": {
      return await list(...);
    }
    case "/remove": {
      return await remove(...);
    }
    case "/add": {
      return await add(...);
    }

    default: {
      return { status: 500, headers: {} };
    }
  }

Do we want to consider a lightweight router? How would it look like?

karthik2804 commented 1 year ago

We could possibly use https://www.npmjs.com/package/itty-router

It does not currently work with the SDK as we are missing the entries method on URLSearchParams object but implementing it is straightforward. Once we have that, itty-router should just work.

I do have it working locally. Will PR it soon.

karthik2804 commented 1 year ago

@radu-matei once #91 is merged, itty-router should work.

radu-matei commented 1 year ago

Is the plan to add an example? Do we need to tweak it in any way?

Thanks!

karthik2804 commented 1 year ago

We need to tweak it very slightly. I'll add an example for it.

karthik2804 commented 1 year ago

A newer commit to itty-router (https://github.com/kwhitley/itty-router/commit/e81b146c0a4ebe1ab5f6a70550a8ff48d1b1d5d3) renders it currently broken with SDK. This breakage is due to URLSearchParams not being iterable in the SDK. I will look into adding the @@iterator method.

karthik2804 commented 1 year ago

92 fixes the bug mentioned above. I am inlining an example for itty-router as it will not currently work with v0.2.0 of the SDK.

import { HandleRequest, HttpRequest, HttpResponse } from "@fermyon/spin-sdk"
import { Router } from 'itty-router'

const router = Router()
const encoder = new TextEncoder()

export const handleRequest: HandleRequest = async function (request: HttpRequest): Promise<HttpResponse> {
   router.get('/todos/:id', ({params}) => console.log(`Todos ` + params.id))
   router.get('/done', ({query}) => console.log(`Todos done ` + query.test))

   await router.handle({
       method: request.method,
       url: request.headers["spin-full-url"]
   })

   return {
       status: 200,
       headers: {"foo": "bar"},
       body: encoder.encode("Hello from JS-SDK").buffer
   }
}

@radu-matei thoughts on adding the example to the repository when it will not work with the current release?

radu-matei commented 1 year ago

Once we have a working example for using the router, adding it to the repo examples makes sense to me! I am wondering though if we can get rid of the last return statement somehow and of the last router.handle.

Thanks for looking into this!

karthik2804 commented 1 year ago

closed with #99