Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(context): introduce c.var #1406

Merged
merged 8 commits into from
Sep 9, 2023
Merged

feat(context): introduce c.var #1406

merged 8 commits into from
Sep 9, 2023

Conversation

yusukebe
Copy link
Member

@yusukebe yusukebe commented Sep 4, 2023

This PR introduces two new features: the ability to set variables using Middleware generics and accessing them via c.var.

Currently, you can globally define variable types using generics for Hono.

type Client = 'foo client'

const app = new Hono<{
  Variables: {
    client: Client
  }
}>()

Alternatively, you can specify them for a specific middleware using ContextVariableMap:

// JWT middleare
declare module '../../context' { // Or you can write `declare module 'hono'`
  interface ContextVariableMap {
    jwtPayload: any
  }
}

The challenge here is that using ContextVariableMap makes it globally available. For instance, after importing the JWT middleware, you can access jwtPayload in any handler.

With this PR, you can confine middleware-defined variables to specific handlers where the middleware is applied.

const oneApiMiddleware: MiddlewareHandler<{
  Variables: {
    client: Client
  }
}> = async (c, next) => {
  c.set('client', new Client())
  await next()
}

app.get('/foo', oneApiMiddleware, (c) => {
  const client = c.get('client') // `client` is accessible only in this handler
  // ...
  return c.json({})
})

This offers a scoped approach to variable type availability.

The second feature is c.var. While the conventional method to access the actual value of a variable is c.get():

const client = c.get('client')

With c.var, you can use a more intuitive syntax:

const result = c.var.client.oneMethod()

The combination of these two features will provide a powerful tool for developers:

const app = new Hono()

const echoMiddleware: MiddlewareHandler<{
  Variables: {
    echo: (str: string) => string
  }
}> = async (c, next) => {
  c.set('echo', (str) => str)
  await next()
}

app.get('/echo', echoMiddleware, (c) => {
  return c.text(c.var.echo('Hello!'))
})
Screenshot 2023-09-04 at 22 54 18

This was discussed in issue #414 and is now being realized.

@yusukebe
Copy link
Member Author

yusukebe commented Sep 4, 2023

Hi @usualoma , @ThatOneBro , and others.

What do you think about this feature? I think this is good because it will achieve big things with minimal change of the APIs.

@ThatOneBro
Copy link
Contributor

I think this makes a lot of sense overall. 👍 LGTM

@yusukebe yusukebe changed the base branch from main to next September 5, 2023 07:32
@yusukebe
Copy link
Member Author

yusukebe commented Sep 6, 2023

With this commit, I've set the properties to read-only. This is to prevent confusion, emphasizing that users should exclusively use c.set() to assign values.

Screenshot 2023-09-06 at 11 15 47

@yusukebe yusukebe merged commit 665f456 into next Sep 9, 2023
10 checks passed
@yusukebe yusukebe deleted the feat/c-var branch September 9, 2023 08:11
@Eduard-Hasa
Copy link

const app = new Hono()

const echoMiddleware: MiddlewareHandler<{
  Variables: {
    echo: (str: string) => string
  }
}> = async (c, next) => {
  c.set('echo', (str) => str)
  await next()
}

app.get('/echo', echoMiddleware, (c) => {
  return c.text(c.var.echo('Hello!'))
})

I think there is a large gap in documentation/public knowledge on how to use honojs with cloudflare durable objects in the sense that there is no way shown how to access durable object storage in the route handlers. Would the c.set() and c.text(c.var.echo('Hello!')) solution be good to store and access durable object storage in routes?

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.

None yet

3 participants