Skip to content

Commit 44668ee

Browse files
committed
fix: params serialization issue
1 parent 23651ce commit 44668ee

File tree

8 files changed

+1010
-75
lines changed

8 files changed

+1010
-75
lines changed

example/components/client-comp.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React from "react";
3+
import React, { useEffect } from "react";
44
import { clientTrpc } from "~/trpc/client";
55

66
export const ClientComp: React.FC = () => {
@@ -15,6 +15,28 @@ export const ClientComp: React.FC = () => {
1515
});
1616
console.log({ clientOrganization: organization });
1717

18+
useEffect(() => {
19+
const asyncFn = async () => {
20+
await clientTrpc.analyticsFetcher.fetch({
21+
contentTypes: ["booking"],
22+
organizationId: "qlmskjdqslmdf",
23+
endDate: "03-10-2025",
24+
where: {
25+
lksdf: true,
26+
what: [
27+
"do",
28+
"you",
29+
{
30+
sdf: "string",
31+
test: 5,
32+
},
33+
],
34+
},
35+
});
36+
};
37+
asyncFn();
38+
}, []);
39+
1840
if (user.isLoading) {
1941
return <>Loading...</>;
2042
}

example/trpc/router.ts

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,51 @@ export const createContext = async () => {
1111
const ctx = new CtxRouter<Awaited<ReturnType<typeof createContext>>>();
1212

1313
interface MockUser {
14-
id:string,
15-
name:string,
16-
email:string,
17-
avatar:string
14+
id: string;
15+
name: string;
16+
email: string;
17+
avatar: string;
1818
}
1919

2020
interface MockOrganization {
21-
id: string,
22-
name: string,
23-
slug: string,
24-
description: string,
25-
memberCount: number,
26-
createdAt: string
21+
id: string;
22+
name: string;
23+
slug: string;
24+
description: string;
25+
memberCount: number;
26+
createdAt: string;
2727
}
28+
29+
const tableSchemaMap = {
30+
order: true,
31+
booking: false,
32+
};
33+
34+
const analyticsFetcherSchema = z.object({
35+
contentTypes: z.array(
36+
z.enum(
37+
Object.keys(tableSchemaMap) as unknown as readonly [
38+
keyof typeof tableSchemaMap,
39+
...(keyof typeof tableSchemaMap)[]
40+
]
41+
)
42+
),
43+
startDate: z.string().optional(),
44+
endDate: z.string().optional(),
45+
// Optional where object passed from client; server interprets it if provided
46+
where: z.record(z.any()).optional(),
47+
organizationId: z.string().optional(),
48+
});
49+
2850
export const appRouter = ctx.router({
2951
getUser: ctx.endpoint.action(async ({ hello, howAreYou, request }) => {
30-
console.log({
31-
myCustomContext: {
32-
hello,
33-
howAreYou,
34-
},
35-
nextjsRequest: request,
36-
});
52+
// console.log({
53+
// myCustomContext: {
54+
// hello,
55+
// howAreYou,
56+
// },
57+
// nextjsRequest: request,
58+
// });
3759

3860
return new Promise<MockUser>((resolve) => {
3961
setTimeout(() => {
@@ -47,58 +69,64 @@ export const appRouter = ctx.router({
4769
});
4870
}),
4971
greeting: ctx.endpoint
50-
.input(
72+
.input(
5173
z.object({
52-
name: z.string(),
53-
age: z.coerce.number(),
54-
})
74+
name: z.string(),
75+
age: z.coerce.number(),
76+
})
5577
)
5678
.action(({ name, age }, { howAreYou }) => {
57-
console.log({ howAreYou });
58-
return `Hi my name is ${name}, and I am ${age} years old.`;
79+
console.log({ howAreYou });
80+
return `Hi my name is ${name}, and I am ${age} years old.`;
81+
}),
82+
test: ctx.endpoint.action(async ({ hello, howAreYou, request }) => {
83+
return new Promise((resolve) => {
84+
setTimeout(() => {
85+
resolve({
86+
id: "1",
87+
name: "John Doe",
88+
email: "john@example.com",
89+
avatar: "https://avatar.example.com/john.jpg",
90+
});
91+
}, 1000);
92+
});
93+
}),
94+
analyticsFetcher: ctx.endpoint
95+
.input(analyticsFetcherSchema)
96+
.action(async (inputs) => {
97+
console.log("analyticsFetcher");
98+
console.log({ inputs });
99+
return { test: true };
59100
}),
60-
test: ctx.endpoint.action(async ({ hello, howAreYou, request }) => {
61-
62-
return new Promise((resolve) => {
101+
getOrganization: ctx.endpoint
102+
.input(
103+
z.object({
104+
orgSlug: z.string(),
105+
})
106+
)
107+
.action(async ({ orgSlug }, { hello, howAreYou, request }) => {
108+
// console.log({
109+
// myCustomContext: {
110+
// hello,
111+
// howAreYou,
112+
// },
113+
// nextjsRequest: request,
114+
// orgSlug,
115+
// });
116+
117+
return new Promise<MockOrganization>((resolve) => {
63118
setTimeout(() => {
64119
resolve({
65-
id: "1",
66-
name: "John Doe",
67-
email: "john@example.com",
68-
avatar: "https://avatar.example.com/john.jpg",
120+
id: "org-123",
121+
name: `Organization ${orgSlug}`,
122+
slug: orgSlug,
123+
description: `This is a mock organization for ${orgSlug}`,
124+
memberCount: 25,
125+
createdAt: "2023-01-01T00:00:00.000Z",
69126
});
70127
}, 1000);
71128
});
72129
}),
73-
getOrganization: ctx.endpoint
74-
.input(
75-
z.object({
76-
orgSlug: z.string(),
77-
})
78-
)
79-
.action(async ({ orgSlug }, { hello, howAreYou, request }) => {
80-
console.log({
81-
myCustomContext: {
82-
hello,
83-
howAreYou,
84-
},
85-
nextjsRequest: request,
86-
orgSlug,
87-
});
88-
89-
return new Promise<MockOrganization>((resolve) => {
90-
setTimeout(() => {
91-
resolve({
92-
id: "org-123",
93-
name: `Organization ${orgSlug}`,
94-
slug: orgSlug,
95-
description: `This is a mock organization for ${orgSlug}`,
96-
memberCount: 25,
97-
createdAt: "2023-01-01T00:00:00.000Z",
98-
});
99-
}, 1000);
100-
});
101-
}),
102130
});
103131

104132
export type AppRouter = typeof appRouter;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@creatorem/next-trpc",
3-
"version": "1.0.11",
3+
"version": "1.0.12",
44
"repository": {
55
"type": "git",
66
"url": "git+https://github.com/creatorem/next-trpc"

src/__tests__/create-trpc-client.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ describe('create-trpc-client', () => {
206206
await fetchFn(complexInput);
207207

208208
expect(mockFetch).toHaveBeenCalledWith(
209-
'http://localhost:3000/api/trpc/create-user?name=John+Doe&age=30&active=true&metadata=%5Bobject+Object%5D',
209+
'http://localhost:3000/api/trpc/create-user?name=John+Doe&age=30&active=true&metadata=%7B%22key%22%3A%22value%22%7D',
210210
expect.any(Object)
211211
);
212212
});

src/__tests__/create-trpc-query-client.test.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ describe('create-trpc-query-client', () => {
2525
describe('createTrpcQueryClient', () => {
2626
it('creates client with proxy that returns fetch and useQuery functions', () => {
2727
const client = createTrpcQueryClient({
28-
url: 'http://localhost:3000/api/trpc'
28+
url: 'http://localhost:3000/api/trpc',
29+
useQuery: mockUseQuery
2930
});
3031

3132
expect(typeof (client as any).getUser.fetch).toBe('function');
@@ -36,7 +37,8 @@ describe('create-trpc-query-client', () => {
3637

3738
it('proxy returns undefined for non-string properties', () => {
3839
const client = createTrpcQueryClient({
39-
url: 'http://localhost:3000/api/trpc'
40+
url: 'http://localhost:3000/api/trpc',
41+
useQuery: mockUseQuery
4042
});
4143

4244
expect((client as any)[Symbol.iterator]).toBeUndefined();
@@ -53,7 +55,8 @@ describe('create-trpc-query-client', () => {
5355
mockFetch.mockResolvedValue(mockResponse as any);
5456

5557
const client = createTrpcQueryClient({
56-
url: 'http://localhost:3000/api/trpc'
58+
url: 'http://localhost:3000/api/trpc',
59+
useQuery: mockUseQuery
5760
});
5861

5962
const result = await (client as any).getUser.fetch({ id: '123' });
@@ -72,7 +75,8 @@ describe('create-trpc-query-client', () => {
7275

7376
it('useQuery function calls useQuery with correct parameters', () => {
7477
const client = createTrpcQueryClient({
75-
url: 'http://localhost:3000/api/trpc'
78+
url: 'http://localhost:3000/api/trpc',
79+
useQuery: mockUseQuery
7680
});
7781

7882
const mockQueryResult = {
@@ -100,7 +104,8 @@ describe('create-trpc-query-client', () => {
100104

101105
it('useQuery converts camelCase to kebab-case for queryKey', () => {
102106
const client = createTrpcQueryClient({
103-
url: 'http://localhost:3000/api/trpc'
107+
url: 'http://localhost:3000/api/trpc',
108+
useQuery: mockUseQuery
104109
});
105110

106111
mockUseQuery.mockReturnValue({});
@@ -115,7 +120,8 @@ describe('create-trpc-query-client', () => {
115120

116121
it('useQuery handles endpoint names with consecutive uppercase letters', () => {
117122
const client = createTrpcQueryClient({
118-
url: 'http://localhost:3000/api/trpc'
123+
url: 'http://localhost:3000/api/trpc',
124+
useQuery: mockUseQuery
119125
});
120126

121127
mockUseQuery.mockReturnValue({});
@@ -130,7 +136,8 @@ describe('create-trpc-query-client', () => {
130136

131137
it('useQuery works without additional options', () => {
132138
const client = createTrpcQueryClient({
133-
url: 'http://localhost:3000/api/trpc'
139+
url: 'http://localhost:3000/api/trpc',
140+
useQuery: mockUseQuery
134141
});
135142

136143
mockUseQuery.mockReturnValue({});
@@ -152,6 +159,7 @@ describe('create-trpc-query-client', () => {
152159

153160
const client = createTrpcQueryClient({
154161
url: 'http://localhost:3000/api/trpc',
162+
useQuery: mockUseQuery,
155163
headers: {
156164
'Authorization': 'Bearer token123'
157165
}
@@ -184,6 +192,7 @@ describe('create-trpc-query-client', () => {
184192

185193
const client = createTrpcQueryClient({
186194
url: 'http://localhost:3000/api/trpc',
195+
useQuery: mockUseQuery,
187196
headers: headersFn
188197
});
189198

@@ -212,7 +221,8 @@ describe('create-trpc-query-client', () => {
212221
});
213222

214223
const client = createTrpcQueryClient<typeof testRouter>({
215-
url: 'http://localhost:3000/api/trpc'
224+
url: 'http://localhost:3000/api/trpc',
225+
useQuery: mockUseQuery
216226
});
217227

218228
expect((client as any).getUser.fetch).toBeDefined();
@@ -233,7 +243,8 @@ describe('create-trpc-query-client', () => {
233243
mockFetch.mockResolvedValue(mockResponse as any);
234244

235245
const client = createTrpcQueryClient({
236-
url: 'http://localhost:3000/api/trpc'
246+
url: 'http://localhost:3000/api/trpc',
247+
useQuery: mockUseQuery
237248
});
238249

239250
let capturedQueryFn: any;
@@ -259,7 +270,8 @@ describe('create-trpc-query-client', () => {
259270

260271
it('preserves all useQuery options while adding queryKey and queryFn', () => {
261272
const client = createTrpcQueryClient({
262-
url: 'http://localhost:3000/api/trpc'
273+
url: 'http://localhost:3000/api/trpc',
274+
useQuery: mockUseQuery
263275
});
264276

265277
mockUseQuery.mockReturnValue({});
@@ -291,7 +303,8 @@ describe('create-trpc-query-client', () => {
291303
mockFetch.mockResolvedValue(mockResponse as any);
292304

293305
const client = createTrpcQueryClient({
294-
url: 'http://localhost:3000/api/trpc'
306+
url: 'http://localhost:3000/api/trpc',
307+
useQuery: mockUseQuery
295308
});
296309

297310
let capturedQueryFn: any;

0 commit comments

Comments
 (0)