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

I want to prevent errors when I forget to put / in the Routing path. #960

Open
kbkn3 opened this issue Feb 6, 2025 · 0 comments
Open

I want to prevent errors when I forget to put / in the Routing path. #960

kbkn3 opened this issue Feb 6, 2025 · 0 comments
Labels
enhancement New feature or request

Comments

@kbkn3
Copy link

kbkn3 commented Feb 6, 2025

Which middleware is the feature for?

@hono/zod-openapi

What is the feature you are proposing?

When defining API Schema in hono/zod-openapi, if a client is created with a mix of path:/hoge and path: hoge, it works, but a type error occurs: If a client is created with a mix of path:/hoge and path:hoge, it works, but a but a type error occurs.

We would like to address this on the library side, as it is difficult to find errors when they occur.

Error Example

// api schema
export const getDrafts = createRoute({
  path: 'draft',
  method: 'get',

export const postDraft = createRoute({
  path: '/draft',
  method: 'post',

// client
const response = await client.api.draft.$get(); <- ts-error
Property '$get' is not present in type '{} & { $url: (arg?: {} | undefined) => URL; } & { “:id”: ClientRequest<{}>; }'. ts(2339)

Solution

I came up with two approaches

Allow no / head and give it on the library side

export const createRoute = <P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
  routeConfig: R
) => {
  const route = {
    ...routeConfig,
    getRoutingPath(): RoutingPath<R['path']> {
      return `/${routeConfig.path}`
        .replaceAll(/\/{(.+?)}/g, '/:$1')
        .replace('//', '/') as RoutingPath<P>
    },
  }
  return Object.defineProperty(route, 'getRoutingPath', { enumerable: false })
}

Run-time Error

const validatePath: (path: string) => asserts path is `/${string}` = (path: string) => {
  if (!path.startsWith('/')) {
    throw new Error(`Invalid path: ${path}. Path must start with a '/'.`)
  }
}

export const createRoute = <P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
  routeConfig: R
) => {

  validatePath(routeConfig.path)
  const route = {
    ...routeConfig,
    getRoutingPath(): RoutingPath<R['path']> {
      return routeConfig.path.replaceAll(/\/{(.+?)}/g, '/:$1') as RoutingPath<P>
    },
  }
  return Object.defineProperty(route, 'getRoutingPath', { enumerable: false })
}

I think it would be ideal if I could narrow it down with a typescript type, but I haven't come up with a good way to do it.
I would like your advice!

@kbkn3 kbkn3 added the enhancement New feature or request label Feb 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant