diff --git a/.changeset/large-pugs-draw.md b/.changeset/large-pugs-draw.md new file mode 100644 index 0000000..3ee5d4a --- /dev/null +++ b/.changeset/large-pugs-draw.md @@ -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 diff --git a/docs/content/docs/client.md b/docs/content/docs/client.md index e80e4ad..b774d67 100644 --- a/docs/content/docs/client.md +++ b/docs/content/docs/client.md @@ -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 diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index 82791e0..8d79ca3 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -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, @@ -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 } /** diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index fb445f3..c9dbb4c 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -69,7 +69,7 @@ export type TuyauRpcClient> = { ? (body?: Request | null, options?: TuyauQueryOptions) => ResponseOrUnwrap : (body: CleanRequest, options?: TuyauQueryOptions) => ResponseOrUnwrap : K extends '$url' - ? () => string + ? (options?: { query?: QueryParameters }) => string : CreateParams } diff --git a/packages/client/tests/client.spec.ts b/packages/client/tests/client.spec.ts index 85ab14d..ed20eb6 100644 --- a/packages/client/tests/client.spec.ts +++ b/packages/client/tests/client.spec.ts @@ -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> } + } + ':id': { + $url: {} + $get: { + request: { email: string } + response: { 200: Simplify> } + } + } + } + } + }>({ baseUrl: 'http://localhost:3333' }) + + const result = tuyau.users.$url({ query: { email: 'foo@ok.com', 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: []