Skip to content

Commit

Permalink
feat: allow query params in $url method
Browse files Browse the repository at this point in the history
Close #25
  • Loading branch information
Julien-R44 committed Dec 8, 2024
1 parent 308e3c9 commit 18aacee
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-pugs-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tuyau/client': patch
---

Query params are now allowed when building an URL with `$url`. See https://github.com/Julien-R44/tuyau/issues/25
7 changes: 7 additions & 0 deletions docs/content/docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,13 @@ const url = tuyau.users({ id: 1 }).posts({ postId: 2 }).$url()
console.log(url) // http://localhost:3333/users/1/posts/2
```

You can also pass a query object to the `$url` method but note that the query object will NOT be type-safe here, since we have no way to determine which route you're calling and what query parameters are available. `tuyau.users.$url()` could refer to POST `/users` or GET `/users` for example.

```ts
const url = tuyau.users.$url({ query: { page: 1, limit: 10 } })
console.log(url) // http://localhost:3333/users?page=1&limit=10
```

### Generating URL from route name

To generate a
Expand Down
5 changes: 4 additions & 1 deletion packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { KyInstance } from 'ky'

import { RouteHelper } from './route.js'
import { TuyauRequest } from './request.js'
import { buildSearchParams } from './utils.js'
import type {
TuyauOptions,
GeneratedRoutes,
Expand Down Expand Up @@ -40,7 +41,9 @@ function createProxy(options: {
}

if (lastPath === '$url') {
return new URL(paths.join('/').replace('/$url', ''), baseUrl).toString()
const searchParams = buildSearchParams(body?.query)
const url = new URL(paths.join('/').replace('/$url', ''), baseUrl)
return url.toString() + searchParams
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export type TuyauRpcClient<in out Route extends Record<string, any>> = {
? (body?: Request | null, options?: TuyauQueryOptions) => ResponseOrUnwrap<Res>
: (body: CleanRequest<Request>, options?: TuyauQueryOptions) => ResponseOrUnwrap<Res>
: K extends '$url'
? () => string
? (options?: { query?: QueryParameters }) => string
: CreateParams<Route[K]>
}

Expand Down
30 changes: 30 additions & 0 deletions packages/client/tests/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,36 @@ test.group('Client | Runtime', () => {
assert.deepEqual(tuyau.users({ id: '1' }).$url(), 'http://localhost:3333/users/1')
})

test('generate url with query parameters', async ({ assert }) => {
const tuyau = createTuyau<{
routes: []
definition: {
users: {
'$url': {}
'$get': {
request: { email: string }
response: { 200: Simplify<Serialize<{ token: string }>> }
}
':id': {
$url: {}
$get: {
request: { email: string }
response: { 200: Simplify<Serialize<{ token: string }>> }
}
}
}
}
}>({ baseUrl: 'http://localhost:3333' })

const result = tuyau.users.$url({ query: { email: '[email protected]', bar: ['baz', 'qux'] } })
assert.deepEqual(result, 'http://localhost:3333/users?email=foo%40ok.com&bar[]=baz&bar[]=qux')
assert.deepEqual(tuyau.users({ id: '1' }).$url(), 'http://localhost:3333/users/1')
assert.deepEqual(
tuyau.users({ id: '1' }).$url({ query: { foo: 'ok' } }),
'http://localhost:3333/users/1?foo=ok',
)
})

test('upload file pass the right content type', async () => {
const tuyau = createTuyau<{
routes: []
Expand Down

0 comments on commit 18aacee

Please sign in to comment.