From d3367c6f195127da9d194205694ff50246e444a0 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:02:08 +0000 Subject: [PATCH 01/14] fix(server): rpc serialization --- packages/server/src/api/common/utils.ts | 18 ++++---- packages/server/src/api/rpc/index.ts | 57 ++++++++++++++++--------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/packages/server/src/api/common/utils.ts b/packages/server/src/api/common/utils.ts index c2a0cf3fd..21b8a964a 100644 --- a/packages/server/src/api/common/utils.ts +++ b/packages/server/src/api/common/utils.ts @@ -4,18 +4,19 @@ import SuperJSON from 'superjson'; * Supports the SuperJSON request payload format used by api handlers * `{ meta: { serialization }, ...json }`. */ -export async function processSuperJsonRequestPayload( - payload: unknown, -): Promise<{ result: unknown; error: string | undefined }> { - if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !('meta' in (payload as any))) { +export async function processSuperJsonRequestPayload(payload: { + data?: any; + meta?: any; +}): Promise<{ result: unknown; error: string | undefined }> { + if (!payload || typeof payload !== 'object' || Array.isArray(payload)) { return { result: payload, error: undefined }; } - const { meta, ...rest } = payload as any; + const { meta, data } = payload; if (meta?.serialization) { try { return { - result: SuperJSON.deserialize({ json: rest, meta: meta.serialization }), + result: SuperJSON.deserialize({ json: data, meta: meta.serialization }), error: undefined, }; } catch (err) { @@ -26,8 +27,7 @@ export async function processSuperJsonRequestPayload( } } - // drop meta when no serialization info is present - return { result: rest, error: undefined }; + return { result: data, error: undefined }; } /** @@ -38,7 +38,7 @@ export function unmarshalQ(value: string, meta: string | undefined) { try { parsedValue = JSON.parse(value); } catch { - throw new Error('invalid "q" query parameter'); + throw new Error('invalid "data" query parameter'); } if (meta) { diff --git a/packages/server/src/api/rpc/index.ts b/packages/server/src/api/rpc/index.ts index 024685a98..5ec85ade7 100644 --- a/packages/server/src/api/rpc/index.ts +++ b/packages/server/src/api/rpc/index.ts @@ -91,6 +91,7 @@ export class RPCApiHandler implements ApiH model = lowerCaseFirst(model); method = method.toUpperCase(); let args: unknown; + let meta: unknown; let resCode = 200; switch (op) { @@ -105,7 +106,8 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse('missing request body'); } - args = requestBody; + args = (requestBody as any)?.data; + meta = (requestBody as any)?.meta; resCode = 201; break; @@ -120,9 +122,11 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse('invalid request method, only GET is supported'); } try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + args = query?.['data'] + ? unmarshalQ(query['data'] as string, query['meta'] as string | undefined) + : {}; } catch { - return this.makeBadInputErrorResponse('invalid "q" query parameter'); + return this.makeBadInputErrorResponse('invalid "data" query parameter'); } break; @@ -136,7 +140,8 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse('missing request body'); } - args = requestBody; + args = (requestBody as any)?.data; + meta = (requestBody as any)?.meta; break; case 'delete': @@ -145,10 +150,12 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse('invalid request method, only DELETE is supported'); } try { - args = query?.['q'] ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) : {}; + args = query?.['data'] + ? unmarshalQ(query['data'] as string, query['meta'] as string | undefined) + : {}; } catch (err) { return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', + err instanceof Error ? err.message : 'invalid "data" query parameter', ); } break; @@ -157,7 +164,7 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse('invalid operation: ' + op); } - const { result: processedArgs, error } = await this.processRequestPayload(args); + const { result: processedArgs, error } = await this.processRequestPayload({ data: args, meta }); if (error) { return this.makeBadInputErrorResponse(error); } @@ -221,18 +228,20 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse(`unsupported transaction type: ${type}`); } - if (!requestBody || !Array.isArray(requestBody) || requestBody.length === 0) { - return this.makeBadInputErrorResponse('request body must be a non-empty array of operations'); + const operations = (requestBody as any)?.data; + + if (!operations || !Array.isArray(operations) || operations.length === 0) { + return this.makeBadInputErrorResponse('request data must be a non-empty array of operations'); } const processedOps: Array<{ model: string; op: string; args: unknown }> = []; - for (let i = 0; i < requestBody.length; i++) { - const item = requestBody[i]; + for (let i = 0; i < operations.length; i++) { + const item = operations[i]; if (!item || typeof item !== 'object') { return this.makeBadInputErrorResponse(`operation at index ${i} must be an object`); } - const { model: itemModel, op: itemOp, args: itemArgs } = item as any; + const { model: itemModel, op: itemOp, args: itemArgs, meta } = item as any; if (!itemModel || typeof itemModel !== 'string') { return this.makeBadInputErrorResponse(`operation at index ${i} is missing a valid "model" field`); } @@ -253,7 +262,10 @@ export class RPCApiHandler implements ApiH return this.makeBadInputErrorResponse(`operation at index ${i} has invalid "args" field`); } - const { result: processedArgs, error: argsError } = await this.processRequestPayload(itemArgs ?? {}); + const { result: processedArgs, error: argsError } = await this.processRequestPayload({ + data: itemArgs ?? {}, + meta, + }); if (argsError) { return this.makeBadInputErrorResponse(`operation at index ${i}: ${argsError}`); } @@ -325,20 +337,23 @@ export class RPCApiHandler implements ApiH } } - let argsPayload = method === 'POST' ? requestBody : undefined; + let argsPayload = method === 'POST' ? (requestBody as any)?.data : undefined; if (method === 'GET') { try { - argsPayload = query?.['q'] - ? unmarshalQ(query['q'] as string, query['meta'] as string | undefined) + argsPayload = query?.['data'] + ? unmarshalQ(query['data'] as string, query['meta'] as string | undefined) : undefined; } catch (err) { return this.makeBadInputErrorResponse( - err instanceof Error ? err.message : 'invalid "q" query parameter', + err instanceof Error ? err.message : 'invalid "data" query parameter', ); } } - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload({ + data: argsPayload, + meta: (requestBody as any)?.meta, + }); if (error) { return this.makeBadInputErrorResponse(error); } @@ -441,17 +456,17 @@ export class RPCApiHandler implements ApiH } private async processRequestPayload(args: any) { - const { meta, ...rest } = args ?? {}; + const { meta, data } = args ?? {}; if (meta?.serialization) { try { // superjson deserialization - args = SuperJSON.deserialize({ json: rest, meta: meta.serialization }); + args = SuperJSON.deserialize({ json: data, meta: meta.serialization }); } catch (err) { return { result: undefined, error: `failed to deserialize request payload: ${(err as Error).message}` }; } } else { // drop meta when no serialization info is present - args = rest; + args = data; } return { result: args, error: undefined }; } From 8ddadcec76fa17ccb02d1061d6a49cb361f745bb Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:07:05 +0000 Subject: [PATCH 02/14] fix(client-helpers): serialization --- packages/clients/client-helpers/src/fetch.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/clients/client-helpers/src/fetch.ts b/packages/clients/client-helpers/src/fetch.ts index de3700d6c..e0b6b0639 100644 --- a/packages/clients/client-helpers/src/fetch.ts +++ b/packages/clients/client-helpers/src/fetch.ts @@ -30,7 +30,7 @@ export async function fetcher(url: string, options?: RequestInit, customFetch const textResult = await res.text(); try { - return unmarshal(textResult).data as R; + return unmarshal(textResult) as R; } catch (err) { console.error(`Unable to deserialize data:`, textResult); throw err; @@ -47,7 +47,7 @@ export function makeUrl(endpoint: string, model: string, operation: string, args } const { data, meta } = serialize(args); - let result = `${baseUrl}?q=${encodeURIComponent(JSON.stringify(data))}`; + let result = `${baseUrl}?data=${encodeURIComponent(JSON.stringify(data))}`; if (meta) { result += `&meta=${encodeURIComponent(JSON.stringify({ serialization: meta }))}`; } @@ -113,11 +113,10 @@ export function deserialize(value: unknown, meta: any): unknown { */ export function marshal(value: unknown) { const { data, meta } = serialize(value); - if (meta) { - return JSON.stringify({ ...(data as any), meta: { serialization: meta } }); - } else { - return JSON.stringify(data); + if (!meta) { + return JSON.stringify({ data }); } + return JSON.stringify({ data, meta: { serialization: meta } }); } /** @@ -126,10 +125,8 @@ export function marshal(value: unknown) { */ export function unmarshal(value: string) { const parsed = JSON.parse(value); - if (typeof parsed === 'object' && parsed?.data && parsed?.meta?.serialization) { - const deserializedData = deserialize(parsed.data, parsed.meta.serialization); - return { ...parsed, data: deserializedData }; - } else { - return parsed; + if (!parsed.meta?.serialization) { + return parsed.data; } + return deserialize(parsed.data, parsed.meta.serialization); } From 02a1969fb9a7180ff12f7e8350bdd44766b0c8ab Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:07:31 +0000 Subject: [PATCH 03/14] fix(fetch-client): transaction serialization --- packages/clients/fetch-client/src/index.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/clients/fetch-client/src/index.ts b/packages/clients/fetch-client/src/index.ts index 92a327099..2c22dc18b 100644 --- a/packages/clients/fetch-client/src/index.ts +++ b/packages/clients/fetch-client/src/index.ts @@ -301,7 +301,20 @@ export function createClient { + const { data: serializedOp, meta } = serialize(op); + if (!meta) { + return serializedOp; + } + return { + ...(serializedOp as any), + meta: { + serialization: meta, + }, + }; + }), + }), }, customFetch, ); From 2501652f589ddb8d53a3479dfaa942c986186f9e Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:09:16 +0000 Subject: [PATCH 04/14] chore(fetch-client): adjust tests --- .../fetch-client/test/fetch-client.test.ts | 46 ++++++++++--------- .../fetch-client/test/typing.test-d.ts | 3 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/packages/clients/fetch-client/test/fetch-client.test.ts b/packages/clients/fetch-client/test/fetch-client.test.ts index 14e86a805..38248301e 100644 --- a/packages/clients/fetch-client/test/fetch-client.test.ts +++ b/packages/clients/fetch-client/test/fetch-client.test.ts @@ -40,7 +40,7 @@ describe('createClient', () => { expect(mockFetch).toHaveBeenCalledOnce(); const [url, init] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/findUnique?q=`); + expect(url).toContain(`${ENDPOINT}/user/findUnique?data=`); expect(init).toBeUndefined(); expect(result).toEqual(data); }); @@ -53,7 +53,7 @@ describe('createClient', () => { await client.user.findFirst({ where: { name: 'Bob' } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/findFirst?q=`); + expect(url).toContain(`${ENDPOINT}/user/findFirst?data=`); }); it('findFirst - can be called with no args', async () => { @@ -88,7 +88,7 @@ describe('createClient', () => { const result = await client.user.exists({ where: { id: '1' } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/exists?q=`); + expect(url).toContain(`${ENDPOINT}/user/exists?data=`); expect(result).toBe(true); }); @@ -111,7 +111,7 @@ describe('createClient', () => { const result = await client.user.aggregate({ _count: { id: true } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/aggregate?q=`); + expect(url).toContain(`${ENDPOINT}/user/aggregate?data=`); expect(result).toEqual(aggResult); }); @@ -123,7 +123,7 @@ describe('createClient', () => { const result = await client.user.groupBy({ by: ['name'], _count: { id: true } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/groupBy?q=`); + expect(url).toContain(`${ENDPOINT}/user/groupBy?data=`); expect(result).toEqual(groupResult); }); }); @@ -137,7 +137,7 @@ describe('createClient', () => { const result = await client.user.findUniqueOrThrow({ where: { id: '1' } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/findUnique?q=`); + expect(url).toContain(`${ENDPOINT}/user/findUnique?data=`); expect(result).toEqual(data); }); @@ -184,7 +184,7 @@ describe('createClient', () => { expect(url).toBe(`${ENDPOINT}/user/create`); expect(init.method).toBe('POST'); expect(init.headers['content-type']).toBe('application/json'); - expect(JSON.parse(init.body)).toMatchObject({ data: { email: 'new@example.com' } }); + expect(JSON.parse(init.body)).toMatchObject({ data: { data: { email: 'new@example.com' } } }); expect(result).toEqual(created); }); @@ -269,7 +269,7 @@ describe('createClient', () => { await client.user.delete({ where: { id: '1' } }); const [url, init] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/delete?q=`); + expect(url).toContain(`${ENDPOINT}/user/delete?data=`); expect(init.method).toBe('DELETE'); expect(init.body).toBeUndefined(); }); @@ -281,7 +281,7 @@ describe('createClient', () => { await client.user.deleteMany({ where: { name: null } }); const [url, init] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain(`${ENDPOINT}/user/deleteMany?q=`); + expect(url).toContain(`${ENDPOINT}/user/deleteMany?data=`); expect(init.method).toBe('DELETE'); }); @@ -365,7 +365,7 @@ describe('createClient', () => { mockFetch.mockResolvedValue({ ok: false, status: 404, - text: async () => JSON.stringify({ error: errorInfo }), + text: async () => makeResponseText({ error: errorInfo }), }); const client = createClient(schema, { endpoint: ENDPOINT }); @@ -394,7 +394,7 @@ describe('createClient', () => { ok: false, status: 403, text: async () => - JSON.stringify({ error: { rejectedByPolicy: true, rejectReason: 'cannot-read-back' } }), + makeResponseText({ error: { rejectedByPolicy: true, rejectReason: 'cannot-read-back' } }), }); const client = createClient(schema, { endpoint: ENDPOINT }); @@ -406,7 +406,7 @@ describe('createClient', () => { mockFetch.mockResolvedValue({ ok: false, status: 500, - text: async () => JSON.stringify({ error: { message: 'Internal server error' } }), + text: async () => makeResponseText({ error: { message: 'Internal server error' } }), }); const client = createClient(schema, { endpoint: ENDPOINT }); @@ -450,7 +450,7 @@ describe('createClient', () => { await client.user.findMany({ where: { id: '1' } }); const [url] = mockFetch.mock.calls[0] ?? []; - expect(url).toContain('?q='); + expect(url).toContain('?data='); }); it('marshals args with Decimal into POST body', async () => { @@ -461,7 +461,7 @@ describe('createClient', () => { const [, init] = mockFetch.mock.calls[0] ?? []; const body = JSON.parse(init.body); - expect(body).toMatchObject({ data: [{ email: 'x@test.com' }] }); + expect(body).toMatchObject({ data: { data: [{ email: 'x@test.com' }] } }); }); }); @@ -521,10 +521,12 @@ describe('createClient', () => { expect(init.headers['content-type']).toBe('application/json'); const body = JSON.parse(init.body); - expect(body).toEqual([ - { model: 'User', op: 'create', args: { data: { email: 'alice@example.com' } } }, - { model: 'Post', op: 'create', args: { data: { title: 'Hello' } } }, - ]); + expect(body).toEqual({ + data: [ + { model: 'User', op: 'create', args: { data: { email: 'alice@example.com' } } }, + { model: 'Post', op: 'create', args: { data: { title: 'Hello' } } }, + ], + }); expect(user).toEqual(results[0]); expect(post).toEqual(results[1]); @@ -555,8 +557,8 @@ describe('createClient', () => { ]); const body = JSON.parse((mockFetch.mock.calls[0] ?? [])[1].body); - expect(body[0]).toMatchObject({ model: 'User', op: 'updateMany' }); - expect(body[1]).toMatchObject({ model: 'Post', op: 'delete' }); + expect(body.data[0]).toMatchObject({ model: 'User', op: 'updateMany' }); + expect(body.data[1]).toMatchObject({ model: 'Post', op: 'delete' }); }); it('marshals args with SuperJSON when special types are present', async () => { @@ -567,7 +569,7 @@ describe('createClient', () => { // Plain args – no meta expected const body = JSON.parse((mockFetch.mock.calls[0] ?? [])[1].body); - expect(body[0].args).toEqual({ where: { id: '1' } }); + expect(body.data[0].args).toEqual({ where: { id: '1' } }); }); it('uses custom fetch in transaction', async () => { @@ -587,7 +589,7 @@ describe('createClient', () => { mockFetch.mockResolvedValue({ ok: false, status: 400, - text: async () => JSON.stringify({ error: { message: 'Bad request' } }), + text: async () => makeResponseText({ error: { message: 'Bad request' } }), }); const client = createClient(schema, { endpoint: ENDPOINT }); diff --git a/packages/clients/fetch-client/test/typing.test-d.ts b/packages/clients/fetch-client/test/typing.test-d.ts index 1df90827f..50f64964d 100644 --- a/packages/clients/fetch-client/test/typing.test-d.ts +++ b/packages/clients/fetch-client/test/typing.test-d.ts @@ -10,7 +10,7 @@ describe('Result narrowing through AllModelOperations', () => { it('full row shape with no select', () => { const client = createClient(schema, { endpoint: ENDPOINT }); expectTypeOf(client.user.findMany()).resolves.toEqualTypeOf< - Array<{ id: string; email: string; name: string | null }> + Array<{ id: string; email: string; name: string | null; createdAt: Date }> >(); }); @@ -26,6 +26,7 @@ describe('Result narrowing through AllModelOperations', () => { id: string; email: string; name: string | null; + createdAt: Date; }>(); }); }); From 751f1db845045cb1741f21c59b4a4f32e057fdf4 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:09:55 +0000 Subject: [PATCH 05/14] chore(fetch-client): add `$transaction` superjson test --- .../fetch-client/test/fetch-client.test.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/clients/fetch-client/test/fetch-client.test.ts b/packages/clients/fetch-client/test/fetch-client.test.ts index 38248301e..af8650a04 100644 --- a/packages/clients/fetch-client/test/fetch-client.test.ts +++ b/packages/clients/fetch-client/test/fetch-client.test.ts @@ -597,6 +597,44 @@ describe('createClient', () => { client.$transaction([{ model: 'User', op: 'create', args: { data: { email: 'x@test.com' } } }]), ).rejects.toMatchObject({ status: 400 }); }); + + it('works with superjson serialization', async () => { + const createdAt = new Date(); + const results = [{ id: '1', email: 'alice@example.com', createdAt: createdAt.toISOString() }]; + mockFetch.mockResolvedValue({ ok: true, text: async () => makeResponseText(results) }); + + const client = createClient(schema, { endpoint: ENDPOINT }); + const [user] = await client.$transaction([ + { model: 'User', op: 'create', args: { data: { email: 'alice@example.com', createdAt } } }, + ]); + + const [url, init] = mockFetch.mock.calls[0] ?? []; + expect(url).toBe(`${ENDPOINT}/$transaction/sequential`); + expect(init.method).toBe('POST'); + expect(init.headers['content-type']).toBe('application/json'); + + const body = JSON.parse(init.body); + expect(body).toMatchObject({ + data: [ + { + model: 'User', + op: 'create', + args: { + data: { email: 'alice@example.com', createdAt: createdAt.toISOString() }, + }, + meta: { + serialization: { + values: { + 'args.data.createdAt': ['Date'], + }, + }, + }, + }, + ], + }); + + expect(user).toEqual(results[0]); + }); }); describe('$procs absent when schema has no procedures', () => { From dbe80dbdc4fbe5c8aa0570acd961425fc678af6c Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:10:11 +0000 Subject: [PATCH 06/14] chore(fetch-client): regenerate schema --- .../fetch-client/test/schemas/basic/schema-lite.ts | 6 ++++++ .../fetch-client/test/schemas/basic/schema.zmodel | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/clients/fetch-client/test/schemas/basic/schema-lite.ts b/packages/clients/fetch-client/test/schemas/basic/schema-lite.ts index 492879376..17feb8708 100644 --- a/packages/clients/fetch-client/test/schemas/basic/schema-lite.ts +++ b/packages/clients/fetch-client/test/schemas/basic/schema-lite.ts @@ -36,6 +36,12 @@ export class SchemaType implements SchemaDef { type: "Post", array: true, relation: { opposite: "author" } + }, + createdAt: { + name: "createdAt", + type: "DateTime", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }] as readonly AttributeApplication[], + default: ExpressionUtils.call("now") as FieldDefault } }, idFields: ["id"], diff --git a/packages/clients/fetch-client/test/schemas/basic/schema.zmodel b/packages/clients/fetch-client/test/schemas/basic/schema.zmodel index 001c6795e..da60146af 100644 --- a/packages/clients/fetch-client/test/schemas/basic/schema.zmodel +++ b/packages/clients/fetch-client/test/schemas/basic/schema.zmodel @@ -3,10 +3,11 @@ datasource db { } model User { - id String @id @default(cuid()) - email String @unique - name String? - posts Post[] + id String @id @default(cuid()) + email String @unique + name String? + posts Post[] + createdAt DateTime @default(now()) } model Post { From 12f8fa3a7e373ca6aa5f8f63c2786e070791014e Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:11:47 +0000 Subject: [PATCH 07/14] chore(tanstack-query): adjust tests --- .../clients/tanstack-query/test/react/helpers.tsx | 2 +- .../test/react/json-null-serialization.test.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/clients/tanstack-query/test/react/helpers.tsx b/packages/clients/tanstack-query/test/react/helpers.tsx index 045f2d6f4..8c1be02fc 100644 --- a/packages/clients/tanstack-query/test/react/helpers.tsx +++ b/packages/clients/tanstack-query/test/react/helpers.tsx @@ -22,7 +22,7 @@ export function createWrapper() { export function makeUrl(model: string, operation: string, args?: unknown) { let r = `${BASE_URL}/api/model/${model}/${operation}`; if (args) { - r += `?q=${encodeURIComponent(JSON.stringify(args))}`; + r += `?data=${encodeURIComponent(JSON.stringify(args))}`; } return r; } diff --git a/packages/clients/tanstack-query/test/react/json-null-serialization.test.tsx b/packages/clients/tanstack-query/test/react/json-null-serialization.test.tsx index 32f066658..13a42df1f 100644 --- a/packages/clients/tanstack-query/test/react/json-null-serialization.test.tsx +++ b/packages/clients/tanstack-query/test/react/json-null-serialization.test.tsx @@ -34,9 +34,9 @@ describe('JSON null value serialization', () => { const url = new URL(capturedUri, BASE_URL); expect(url.searchParams.has('meta')).toBe(true); - const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!)); + const data = JSON.parse(decodeURIComponent(url.searchParams.get('data')!)); const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!)); - const reconstructed = deserialize(q, meta.serialization) as any; + const reconstructed = deserialize(data, meta.serialization) as any; expect(reconstructed.where.name.__brand).toBe('DbNull'); }); @@ -61,9 +61,9 @@ describe('JSON null value serialization', () => { const url = new URL(capturedUri, BASE_URL); expect(url.searchParams.has('meta')).toBe(true); - const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!)); + const data = JSON.parse(decodeURIComponent(url.searchParams.get('data')!)); const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!)); - const reconstructed = deserialize(q, meta.serialization) as any; + const reconstructed = deserialize(data, meta.serialization) as any; expect(reconstructed.where.name.__brand).toBe('JsonNull'); }); @@ -88,9 +88,9 @@ describe('JSON null value serialization', () => { const url = new URL(capturedUri, BASE_URL); expect(url.searchParams.has('meta')).toBe(true); - const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!)); + const data = JSON.parse(decodeURIComponent(url.searchParams.get('data')!)); const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!)); - const reconstructed = deserialize(q, meta.serialization) as any; + const reconstructed = deserialize(data, meta.serialization) as any; expect(reconstructed.where.name.__brand).toBe('AnyNull'); }); From e86ca4f31c199961955d8795ee80d78ba6f6d4a2 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:12:19 +0000 Subject: [PATCH 08/14] chore(client-helpers): adjust tests --- .../clients/client-helpers/test/fetch.test.ts | 47 ++++++------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/packages/clients/client-helpers/test/fetch.test.ts b/packages/clients/client-helpers/test/fetch.test.ts index cc69d0b67..838e21126 100644 --- a/packages/clients/client-helpers/test/fetch.test.ts +++ b/packages/clients/client-helpers/test/fetch.test.ts @@ -75,28 +75,18 @@ describe('Fetcher and serialization tests', () => { expect(result).toEqual(input); }); - it('marshals objects without metadata when not needed', () => { - const input = { name: 'John', age: 30 }; - const marshaled = marshal(input); - const parsed = JSON.parse(marshaled); - expect(parsed.meta).toBeUndefined(); - }); - it('marshals and unmarshals objects with Decimal values', () => { const input = { price: new Decimal('123.45') }; const marshaled = marshal(input); const parsed = JSON.parse(marshaled); // marshal spreads the data into the root object with meta - expect(parsed.price).toBeDefined(); + expect(parsed.data.price).toBeDefined(); expect(parsed.meta).toBeDefined(); expect(parsed.meta.serialization).toBeDefined(); - // unmarshal doesn't automatically deserialize this format - // It only deserializes objects with explicit 'data' and 'meta.serialization' fields const result = unmarshal(marshaled); expect(result).toHaveProperty('price'); - expect(result).toHaveProperty('meta'); }); it('includes metadata when serialization is needed', () => { @@ -120,17 +110,10 @@ describe('Fetcher and serialization tests', () => { const marshaled = JSON.stringify(responseFormat); const result = unmarshal(marshaled); - expect(result.data).toBeDefined(); - expect((result.data as any).value).toBeInstanceOf(Decimal); + expect(result).toBeDefined(); + expect((result as any).value).toBeInstanceOf(Decimal); // Decimal normalizes '100.00' to '100' - expect((result.data as any).value.toString()).toBe('100'); - }); - - it('unmarshals plain values without data wrapper', () => { - const plainValue = { name: 'test' }; - const marshaled = JSON.stringify(plainValue); - const result = unmarshal(marshaled); - expect(result).toEqual(plainValue); + expect((result as any).value.toString()).toBe('100'); }); }); @@ -143,7 +126,7 @@ describe('Fetcher and serialization tests', () => { it('creates URL with simple args', () => { const args = { where: { id: '1' } }; const url = makeUrl('/api', 'User', 'findUnique', args); - expect(url).toContain('/api/user/findUnique?q='); + expect(url).toContain('/api/user/findUnique?data='); expect(url).toContain(encodeURIComponent(JSON.stringify(args))); }); @@ -161,12 +144,12 @@ describe('Fetcher and serialization tests', () => { }; const url = makeUrl('/api', 'Product', 'findFirst', args); - expect(url).toContain('/api/product/findFirst?q='); + expect(url).toContain('/api/product/findFirst?data='); expect(url).toContain('&meta='); // Verify we can reconstruct the args from the URL const urlObj = new URL(url, 'http://localhost'); - const qParam = urlObj.searchParams.get('q'); + const qParam = urlObj.searchParams.get('data'); const metaParam = urlObj.searchParams.get('meta'); expect(qParam).toBeDefined(); @@ -179,7 +162,7 @@ describe('Fetcher and serialization tests', () => { it('handles empty args object', () => { const url = makeUrl('/api', 'User', 'findMany', {}); - expect(url).toContain('/api/user/findMany?q='); + expect(url).toContain('/api/user/findMany?data='); }); it('handles complex nested args', () => { @@ -188,7 +171,7 @@ describe('Fetcher and serialization tests', () => { where: { AND: [{ active: true }, { verified: true }] }, }; const url = makeUrl('/api', 'User', 'findMany', args); - expect(url).toContain('/api/user/findMany?q='); + expect(url).toContain('/api/user/findMany?data='); expect(url).toContain(encodeURIComponent(JSON.stringify(args))); }); }); @@ -211,7 +194,7 @@ describe('Fetcher and serialization tests', () => { const responseData = { id: '1', name: 'Alice' }; mockFetch.mockResolvedValue({ ok: true, - text: async () => marshal({ data: responseData }), + text: async () => marshal(responseData), }); const result = await fetcher('/api/user/findUnique', {}); @@ -251,7 +234,7 @@ describe('Fetcher and serialization tests', () => { mockFetch.mockResolvedValue({ ok: false, status: 404, - text: async () => JSON.stringify({ error: errorInfo }), + text: async () => marshal({ error: errorInfo }), }); await expect(fetcher('/api/user/findUnique', {})).rejects.toThrow( @@ -275,7 +258,7 @@ describe('Fetcher and serialization tests', () => { mockFetch.mockResolvedValue({ ok: false, status: 403, - text: async () => JSON.stringify({ error: errorInfo }), + text: async () => marshal({ error: errorInfo }), }); const result = await fetcher('/api/user/create', {}); @@ -300,7 +283,7 @@ describe('Fetcher and serialization tests', () => { it('use custom fetch if provided', async () => { const customFetch = vi.fn().mockResolvedValue({ ok: true, - text: async () => marshal({ data: { id: '1', name: 'Custom' } }), + text: async () => marshal({ id: '1', name: 'Custom' }), }); const result = await fetcher('/api/user/findUnique', {}, customFetch); @@ -333,7 +316,7 @@ describe('Fetcher and serialization tests', () => { it('handles empty response body', async () => { mockFetch.mockResolvedValue({ ok: true, - text: async () => marshal({ data: null }), + text: async () => marshal(null), }); const result = await fetcher('/api/user/delete', {}); @@ -347,7 +330,7 @@ describe('Fetcher and serialization tests', () => { ]; mockFetch.mockResolvedValue({ ok: true, - text: async () => marshal({ data: responseData }), + text: async () => marshal(responseData), }); const result = await fetcher('/api/user/findMany', {}); From 6a09e42c617c2f3edc493d688a52746c726cf8a6 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:15:09 +0000 Subject: [PATCH 09/14] chore(server): adjust rest and rpc query params --- packages/server/src/api/rest/index.ts | 5 ++++- packages/server/src/api/rest/openapi.ts | 2 +- packages/server/src/api/rpc/openapi.ts | 12 ++++++------ packages/server/test/utils.ts | 6 ++++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index 24b2541b5..d8712f104 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -718,7 +718,10 @@ export class RestApiHandler implements Api const argsPayload = method === 'POST' ? requestBody : query; // support SuperJSON request payload format - const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload(argsPayload); + const { result: processedArgsPayload, error } = await processSuperJsonRequestPayload({ + data: argsPayload, + meta: (requestBody as any)?.meta, + }); if (error) { return this.makeProcBadInputErrorResponse(error); } diff --git a/packages/server/src/api/rest/openapi.ts b/packages/server/src/api/rest/openapi.ts index c16d2801d..68090ce7a 100644 --- a/packages/server/src/api/rest/openapi.ts +++ b/packages/server/src/api/rest/openapi.ts @@ -616,7 +616,7 @@ export class RestApiSpecGenerator { if (method === 'get') { op['parameters'] = [ { - name: 'q', + name: 'data', in: 'query', description: 'Procedure arguments as JSON', schema: { type: 'string' }, diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts index 35ff95649..03784ccfd 100644 --- a/packages/server/src/api/rpc/openapi.ts +++ b/packages/server/src/api/rpc/openapi.ts @@ -19,7 +19,7 @@ import type { OpenApiSpecOptions } from '../common/types'; type SchemaObject = OpenAPIV3_1.SchemaObject; type ReferenceObject = OpenAPIV3_1.ReferenceObject; -// Operations that use GET with args in ?q= query parameter +// Operations that use GET with args in ?data= query parameter const GET_OPERATIONS = new Set([ 'findFirst', 'findUnique', @@ -33,7 +33,7 @@ const GET_OPERATIONS = new Set([ const POST_OPERATIONS = new Set(['create', 'createMany', 'createManyAndReturn', 'upsert']); // Operations that use PUT with request body const PUT_OPERATIONS = new Set(['update', 'updateMany', 'updateManyAndReturn']); -// Operations that use DELETE with args in ?q= query parameter +// Operations that use DELETE with args in ?data= query parameter const DELETE_OPERATIONS = new Set(['delete', 'deleteMany']); const JSON_CT = 'application/json'; @@ -364,7 +364,7 @@ export class RPCApiSpecGenerator { const qRequired = Array.isArray(inputSchema?.required) && inputSchema.required.length > 0; operation['parameters'] = [ { - name: 'q', + name: 'data', in: 'query', ...(qRequired && { required: true }), description: `JSON-encoded arguments for ${modelName}.${op}`, @@ -375,7 +375,7 @@ export class RPCApiSpecGenerator { { name: 'meta', in: 'query', - description: 'JSON-encoded SuperJSON serialization metadata for the "q" parameter', + description: 'JSON-encoded SuperJSON serialization metadata for the "data" parameter', schema: { type: 'string' }, }, ]; @@ -450,7 +450,7 @@ export class RPCApiSpecGenerator { if (hasParams) { op['parameters'] = [ { - name: 'q', + name: 'data', in: 'query', ...(hasRequiredParams && { required: true }), description: `JSON-encoded arguments for procedure ${procName}`, @@ -461,7 +461,7 @@ export class RPCApiSpecGenerator { { name: 'meta', in: 'query', - description: 'JSON-encoded SuperJSON serialization metadata for the "q" parameter', + description: 'JSON-encoded SuperJSON serialization metadata for the "data" parameter', schema: { type: 'string' }, }, ]; diff --git a/packages/server/test/utils.ts b/packages/server/test/utils.ts index 674a35c70..e8b515902 100644 --- a/packages/server/test/utils.ts +++ b/packages/server/test/utils.ts @@ -28,6 +28,8 @@ model Post { } `; -export function makeUrl(path: string, q?: object, useSuperJson = false) { - return q ? `${path}?q=${encodeURIComponent(useSuperJson ? superjson.stringify(q) : JSON.stringify(q))}` : path; +export function makeUrl(path: string, data?: object, useSuperJson = false) { + return data + ? `${path}?data=${encodeURIComponent(useSuperJson ? superjson.stringify(data) : JSON.stringify(data))}` + : path; } From 58fb5d1950471e20572e237ffe90983b6b23e1f2 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:16:08 +0000 Subject: [PATCH 10/14] chore(server): adjust adapter tests --- packages/server/test/adapter/elysia.test.ts | 22 ++++++++++------- packages/server/test/adapter/express.test.ts | 20 +++++++++------- packages/server/test/adapter/fastify.test.ts | 22 +++++++++-------- packages/server/test/adapter/hono.test.ts | 22 ++++++++++------- packages/server/test/adapter/next.test.ts | 24 +++++++++---------- .../server/test/adapter/sveltekit.test.ts | 22 ++++++++++------- .../test/adapter/tanstack-start.test.ts | 22 ++++++++--------- 7 files changed, 85 insertions(+), 69 deletions(-) diff --git a/packages/server/test/adapter/elysia.test.ts b/packages/server/test/adapter/elysia.test.ts index 9d02e35cd..187d74364 100644 --- a/packages/server/test/adapter/elysia.test.ts +++ b/packages/server/test/adapter/elysia.test.ts @@ -24,15 +24,17 @@ describe('Elysia adapter tests - rpc handler', () => { r = await handler( makeRequest('POST', '/api/user/create', { - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }), @@ -55,7 +57,9 @@ describe('Elysia adapter tests - rpc handler', () => { expect((await unmarshal(r)).data).toHaveLength(1); r = await handler( - makeRequest('PUT', '/api/user/update', { where: { id: 'user1' }, data: { email: 'user1@def.com' } }), + makeRequest('PUT', '/api/user/update', { + data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + }), ); expect(r.status).toBe(200); expect((await unmarshal(r)).data.email).toBe('user1@def.com'); diff --git a/packages/server/test/adapter/express.test.ts b/packages/server/test/adapter/express.test.ts index 77c36d8ee..0dea6c0f9 100644 --- a/packages/server/test/adapter/express.test.ts +++ b/packages/server/test/adapter/express.test.ts @@ -30,15 +30,17 @@ describe('Express adapter tests - rpc handler', () => { r = await request(app) .post('/api/user/create') .send({ - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }); @@ -65,7 +67,7 @@ describe('Express adapter tests - rpc handler', () => { r = await request(app) .put('/api/user/update') - .send({ where: { id: 'user1' }, data: { email: 'user1@def.com' } }); + .send({ data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } } }); expect(r.status).toBe(200); expect(r.body.data.email).toBe('user1@def.com'); diff --git a/packages/server/test/adapter/fastify.test.ts b/packages/server/test/adapter/fastify.test.ts index d5d2be6b9..d509c1024 100644 --- a/packages/server/test/adapter/fastify.test.ts +++ b/packages/server/test/adapter/fastify.test.ts @@ -27,15 +27,17 @@ describe('Fastify adapter tests - rpc handler', () => { method: 'POST', url: '/api/user/create', payload: { - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }, @@ -69,7 +71,7 @@ describe('Fastify adapter tests - rpc handler', () => { r = await app.inject({ method: 'PUT', url: '/api/user/update', - payload: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + payload: { data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } } }, }); expect(r.statusCode).toBe(200); expect(r.json().data.email).toBe('user1@def.com'); @@ -132,7 +134,7 @@ describe('Fastify adapter tests - rpc handler', () => { r = await app.inject({ method: 'GET', - url: '/api/post/findMany?q=abc', + url: '/api/post/findMany?data=abc', }); expect(r.statusCode).toBe(400); }); diff --git a/packages/server/test/adapter/hono.test.ts b/packages/server/test/adapter/hono.test.ts index 3b406f9bd..d81f1b40e 100644 --- a/packages/server/test/adapter/hono.test.ts +++ b/packages/server/test/adapter/hono.test.ts @@ -20,15 +20,17 @@ describe('Hono adapter tests - rpc handler', () => { r = await handler( makeRequest('POST', '/api/user/create', { - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }), @@ -51,7 +53,9 @@ describe('Hono adapter tests - rpc handler', () => { expect((await unmarshal(r)).data).toHaveLength(1); r = await handler( - makeRequest('PUT', '/api/user/update', { where: { id: 'user1' }, data: { email: 'user1@def.com' } }), + makeRequest('PUT', '/api/user/update', { + data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + }), ); expect(r.status).toBe(200); expect((await unmarshal(r)).data.email).toBe('user1@def.com'); diff --git a/packages/server/test/adapter/next.test.ts b/packages/server/test/adapter/next.test.ts index ee3350387..b23123cf2 100644 --- a/packages/server/test/adapter/next.test.ts +++ b/packages/server/test/adapter/next.test.ts @@ -10,14 +10,14 @@ import { RestApiHandler, RPCApiHandler } from '../../src/api'; function makeTestClient( apiPath: string, options: PageRouteRequestHandlerOptions, - qArg?: unknown, + dataArg?: unknown, otherArgs?: any, ) { const pathParts = apiPath.split('/').filter((p) => p); const query = { path: pathParts, - ...(qArg ? { q: JSON.stringify(qArg) } : {}), + ...(dataArg ? { data: JSON.stringify(dataArg) } : {}), ...otherArgs, }; @@ -62,7 +62,7 @@ model M { await makeTestClient('/m/create', makeClientOptions) .post('/') - .send({ data: { id: '1', value: 1 } }) + .send({ data: { data: { id: '1', value: 1 } } }) .expect(201) .expect((resp) => { expect(resp.body.data.value).toBe(1); @@ -91,7 +91,7 @@ model M { await makeTestClient('/m/update', makeClientOptions) .put('/') - .send({ where: { id: '1' }, data: { value: 2 } }) + .send({ data: { where: { id: '1' }, data: { value: 2 } } }) .expect(200) .expect((resp) => { expect(resp.body.data.value).toBe(2); @@ -99,7 +99,7 @@ model M { await makeTestClient('/m/updateMany', makeClientOptions) .put('/') - .send({ data: { value: 4 } }) + .send({ data: { data: { value: 4 } } }) .expect(200) .expect((resp) => { expect(resp.body.data.count).toBe(1); @@ -107,7 +107,7 @@ model M { await makeTestClient('/m/upsert', makeClientOptions) .post('/') - .send({ where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } }) + .send({ data: { where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } } }) .expect(201) .expect((resp) => { expect(resp.body.data.value).toBe(2); @@ -115,7 +115,7 @@ model M { await makeTestClient('/m/upsert', makeClientOptions) .post('/') - .send({ where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } }) + .send({ data: { where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } } }) .expect(201) .expect((resp) => { expect(resp.body.data.value).toBe(3); @@ -189,7 +189,7 @@ model M { await makeTestClient('/m/create', makeClientOptions) .post('/') - .send({ data: { value: 0 } }) + .send({ data: { data: { value: 0 } } }) .expect(403) .expect((resp) => { expect(resp.body.error.rejectReason).toBe('cannot-read-back'); @@ -197,7 +197,7 @@ model M { await makeTestClient('/m/create', makeClientOptions) .post('/') - .send({ data: { id: '1', value: 1 } }) + .send({ data: { data: { id: '1', value: 1 } } }) .expect(201); await makeTestClient('/m/findMany', makeClientOptions) @@ -209,12 +209,12 @@ model M { await makeTestClient('/m/update', makeClientOptions) .put('/') - .send({ where: { id: '1' }, data: { value: 0 } }) + .send({ data: { where: { id: '1' }, data: { value: 0 } } }) .expect(403); await makeTestClient('/m/update', makeClientOptions) .put('/') - .send({ where: { id: '1' }, data: { value: 2 } }) + .send({ data: { where: { id: '1' }, data: { value: 2 } } }) .expect(200); await makeTestClient('/m/delete', makeClientOptions, { where: { id: '1' } }) @@ -223,7 +223,7 @@ model M { await makeTestClient('/m/update', makeClientOptions) .put('/') - .send({ where: { id: '1' }, data: { value: 3 } }) + .send({ data: { where: { id: '1' }, data: { value: 3 } } }) .expect(200); await makeTestClient('/m/delete', makeClientOptions, { where: { id: '1' } }) diff --git a/packages/server/test/adapter/sveltekit.test.ts b/packages/server/test/adapter/sveltekit.test.ts index 16f2f3741..db1f289a1 100644 --- a/packages/server/test/adapter/sveltekit.test.ts +++ b/packages/server/test/adapter/sveltekit.test.ts @@ -21,15 +21,17 @@ describe('SvelteKit adapter tests - rpc handler', () => { r = await handler( makeRequest('POST', '/api/user/create', { - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }), @@ -52,7 +54,9 @@ describe('SvelteKit adapter tests - rpc handler', () => { expect((await unmarshal(r)).data).toHaveLength(1); r = await handler( - makeRequest('PUT', '/api/user/update', { where: { id: 'user1' }, data: { email: 'user1@def.com' } }), + makeRequest('PUT', '/api/user/update', { + data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + }), ); expect(r.status).toBe(200); expect((await unmarshal(r)).data.email).toBe('user1@def.com'); diff --git a/packages/server/test/adapter/tanstack-start.test.ts b/packages/server/test/adapter/tanstack-start.test.ts index 4d4031ef6..4b3489955 100644 --- a/packages/server/test/adapter/tanstack-start.test.ts +++ b/packages/server/test/adapter/tanstack-start.test.ts @@ -42,7 +42,7 @@ function makeTestClient( if (method === 'GET' || method === 'DELETE') { const url = new URL(baseUrl); if (qArg) { - url.searchParams.set('q', JSON.stringify(qArg)); + url.searchParams.set('data', JSON.stringify(qArg)); } if (otherArgs) { Object.entries(otherArgs).forEach(([key, value]) => { @@ -94,7 +94,7 @@ model M { const client = await makeTestClient('/m/create', options) .post() - .send({ data: { id: '1', value: 1 } }); + .send({ data: { data: { id: '1', value: 1 } } }); expect(client.status).toBe(201); expect(client.body.data.value).toBe(1); @@ -112,25 +112,25 @@ model M { const update = await makeTestClient('/m/update', options) .put() - .send({ where: { id: '1' }, data: { value: 2 } }); + .send({ data: { where: { id: '1' }, data: { value: 2 } } }); expect(update.status).toBe(200); expect(update.body.data.value).toBe(2); const updateMany = await makeTestClient('/m/updateMany', options) .put() - .send({ data: { value: 4 } }); + .send({ data: { data: { value: 4 } } }); expect(updateMany.status).toBe(200); expect(updateMany.body.data.count).toBe(1); const upsert1 = await makeTestClient('/m/upsert', options) .post() - .send({ where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } }); + .send({ data: { where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } } }); expect(upsert1.status).toBe(201); expect(upsert1.body.data.value).toBe(2); const upsert2 = await makeTestClient('/m/upsert', options) .post() - .send({ where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } }); + .send({ data: { where: { id: '2' }, create: { id: '2', value: 2 }, update: { value: 3 } } }); expect(upsert2.status).toBe(201); expect(upsert2.body.data.value).toBe(3); @@ -184,13 +184,13 @@ model M { const createForbidden = await makeTestClient('/m/create', options) .post() - .send({ data: { value: 0 } }); + .send({ data: { data: { value: 0 } } }); expect(createForbidden.status).toBe(403); expect(createForbidden.body.error.rejectReason).toBe('cannot-read-back'); const create = await makeTestClient('/m/create', options) .post() - .send({ data: { id: '1', value: 1 } }); + .send({ data: { data: { id: '1', value: 1 } } }); expect(create.status).toBe(201); const findMany = await makeTestClient('/m/findMany', options).get(); @@ -199,12 +199,12 @@ model M { const updateForbidden1 = await makeTestClient('/m/update', options) .put() - .send({ where: { id: '1' }, data: { value: 0 } }); + .send({ data: { where: { id: '1' }, data: { value: 0 } } }); expect(updateForbidden1.status).toBe(403); const update1 = await makeTestClient('/m/update', options) .put() - .send({ where: { id: '1' }, data: { value: 2 } }); + .send({ data: { where: { id: '1' }, data: { value: 2 } } }); expect(update1.status).toBe(200); const deleteForbidden = await makeTestClient('/m/delete', options, { where: { id: '1' } }).del(); @@ -212,7 +212,7 @@ model M { const update2 = await makeTestClient('/m/update', options) .put() - .send({ where: { id: '1' }, data: { value: 3 } }); + .send({ data: { where: { id: '1' }, data: { value: 3 } } }); expect(update2.status).toBe(200); const deleteOne = await makeTestClient('/m/delete', options, { where: { id: '1' } }).del(); From 17e8fa6c0e32f865ff3d522d7ade7b27094b4453 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:16:52 +0000 Subject: [PATCH 11/14] chore(server): adjust rpc open api tests --- packages/server/test/api/rpc.test.ts | 256 ++++++++++-------- .../test/openapi/baseline/rpc.baseline.yaml | 188 ++++++------- .../server/test/openapi/rpc-openapi.test.ts | 36 +-- 3 files changed, 260 insertions(+), 220 deletions(-) diff --git a/packages/server/test/api/rpc.test.ts b/packages/server/test/api/rpc.test.ts index d98fecaa0..32f8645ad 100644 --- a/packages/server/test/api/rpc.test.ts +++ b/packages/server/test/api/rpc.test.ts @@ -30,7 +30,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/user/exists', - query: { q: JSON.stringify({ where: { id: 'user1' } }) }, + query: { data: JSON.stringify({ where: { id: 'user1' } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -41,15 +41,17 @@ describe('RPC API Handler Tests', () => { path: '/user/create', query: {}, requestBody: { - include: { posts: true }, data: { - id: 'user1', - email: 'user1@abc.com', - posts: { - create: [ - { title: 'post1', published: true, viewCount: 1 }, - { title: 'post2', published: false, viewCount: 2 }, - ], + include: { posts: true }, + data: { + id: 'user1', + email: 'user1@abc.com', + posts: { + create: [ + { title: 'post1', published: true, viewCount: 1 }, + { title: 'post2', published: false, viewCount: 2 }, + ], + }, }, }, }, @@ -69,7 +71,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/user/exists', - query: { q: JSON.stringify({ where: { id: 'user1' } }) }, + query: { data: JSON.stringify({ where: { id: 'user1' } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -86,7 +88,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ where: { viewCount: { gt: 1 } } }) }, + query: { data: JSON.stringify({ where: { viewCount: { gt: 1 } } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -95,7 +97,9 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'put', path: '/user/update', - requestBody: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + requestBody: { + data: { where: { id: 'user1' }, data: { email: 'user1@def.com' } }, + }, client: rawClient, }); expect(r.status).toBe(200); @@ -104,7 +108,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/post/count', - query: { q: JSON.stringify({ where: { viewCount: { gt: 1 } } }) }, + query: { data: JSON.stringify({ where: { viewCount: { gt: 1 } } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -113,7 +117,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/post/aggregate', - query: { q: JSON.stringify({ _sum: { viewCount: true } }) }, + query: { data: JSON.stringify({ _sum: { viewCount: true } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -122,7 +126,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'get', path: '/post/groupBy', - query: { q: JSON.stringify({ by: ['published'], _sum: { viewCount: true } }) }, + query: { data: JSON.stringify({ by: ['published'], _sum: { viewCount: true } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -136,7 +140,7 @@ describe('RPC API Handler Tests', () => { r = await handleRequest({ method: 'delete', path: '/user/deleteMany', - query: { q: JSON.stringify({ where: { id: 'user1' } }) }, + query: { data: JSON.stringify({ where: { id: 'user1' } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -189,7 +193,7 @@ procedure getUndefined(): Undefined let r = await handleProcRequest({ method: 'get', path: '/$procs/echo', - query: { q: JSON.stringify({ args: { input: 'hello' } }) }, + query: { data: JSON.stringify({ args: { input: 'hello' } }) }, }); expect(r.status).toBe(200); expect(r.data).toBe('hello'); @@ -197,7 +201,9 @@ procedure getUndefined(): Undefined r = await handleProcRequest({ method: 'post', path: '/$procs/echo', - requestBody: { args: { input: 'hello' } }, + requestBody: { + data: { args: { input: 'hello' } }, + }, }); expect(r.status).toBe(400); expect(r.error?.message).toMatch(/only GET is supported/i); @@ -206,7 +212,9 @@ procedure getUndefined(): Undefined r = await handleProcRequest({ method: 'post', path: '/$procs/createUser', - requestBody: { args: { email: 'user1@abc.com' } }, + requestBody: { + data: { args: { email: 'user1@abc.com' } }, + }, }); expect(r.status).toBe(200); expect(r.data).toEqual(expect.objectContaining({ email: 'user1@abc.com' })); @@ -214,7 +222,7 @@ procedure getUndefined(): Undefined r = await handleProcRequest({ method: 'get', path: '/$procs/createUser', - query: { q: JSON.stringify({ args: { email: 'user2@abc.com' } }) }, + query: { data: JSON.stringify({ args: { email: 'user2@abc.com' } }) }, }); expect(r.status).toBe(400); expect(r.error?.message).toMatch(/only POST is supported/i); @@ -289,7 +297,7 @@ procedure echoOverview(o: Overview): Overview let r = await handleProcRequest({ method: 'get', path: '/$procs/sum3', - query: { q: JSON.stringify({ args: { a: 1, b: 2, c: 3 } }) }, + query: { data: JSON.stringify({ args: { a: 1, b: 2, c: 3 } }) }, }); expect(r.status).toBe(200); expect(r.data).toBe(6); @@ -299,11 +307,11 @@ procedure echoOverview(o: Overview): Overview expect(r.status).toBe(200); expect(r.data).toBe(0); - // array-typed single param via q JSON array + // array-typed single param via data JSON array r = await handleProcRequest({ method: 'get', path: '/$procs/sumIds', - query: { q: JSON.stringify({ args: { ids: [1, 2, 3] } }) }, + query: { data: JSON.stringify({ args: { ids: [1, 2, 3] } }) }, }); expect(r.status).toBe(200); expect(r.data).toBe(6); @@ -312,7 +320,7 @@ procedure echoOverview(o: Overview): Overview r = await handleProcRequest({ method: 'get', path: '/$procs/echoRole', - query: { q: JSON.stringify({ args: { r: 'ADMIN' } }) }, + query: { data: JSON.stringify({ args: { r: 'ADMIN' } }) }, }); expect(r.status).toBe(200); expect(r.data).toBe('ADMIN'); @@ -321,7 +329,7 @@ procedure echoOverview(o: Overview): Overview r = await handleProcRequest({ method: 'get', path: '/$procs/echoOverview', - query: { q: JSON.stringify({ args: { o: { total: 123 } } }) }, + query: { data: JSON.stringify({ args: { o: { total: 123 } } }) }, }); expect(r.status).toBe(200); expect(r.data).toMatchObject({ total: 123 }); @@ -330,7 +338,7 @@ procedure echoOverview(o: Overview): Overview r = await handleProcRequest({ method: 'get', path: '/$procs/echoInt', - query: { q: JSON.stringify({ args: { x: 'x' } }) }, + query: { data: JSON.stringify({ args: { x: 'x' } }) }, }); expect(r.status).toBe(422); expect(r.error?.message).toMatch(/invalid input/i); @@ -339,7 +347,7 @@ procedure echoOverview(o: Overview): Overview r = await handleProcRequest({ method: 'get', path: '/$procs/sum3', - query: { q: JSON.stringify({ args: [1, 2, 3, 4] }) }, + query: { data: JSON.stringify({ args: [1, 2, 3, 4] }) }, }); expect(r.status).toBe(400); expect(r.error?.message).toMatch(/args/i); @@ -348,7 +356,7 @@ procedure echoOverview(o: Overview): Overview r = await handleProcRequest({ method: 'get', path: '/$procs/sum3', - query: { q: JSON.stringify({ args: { a: 1, b: 2, c: 3, d: 4 } }) }, + query: { data: JSON.stringify({ args: { a: 1, b: 2, c: 3, d: 4 } }) }, }); expect(r.status).toBe(400); expect(r.error?.message).toMatch(/unknown procedure argument/i); @@ -382,7 +390,7 @@ procedure echoOverview(o: Overview): Overview let r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: { title: 'asc' } }) }, + query: { data: JSON.stringify({ orderBy: { title: 'asc' } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -394,7 +402,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: { viewCount: 'desc' } }) }, + query: { data: JSON.stringify({ orderBy: { viewCount: 'desc' } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -405,7 +413,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: [{ published: 'desc' }, { title: 'asc' }] }) }, + query: { data: JSON.stringify({ orderBy: [{ published: 'desc' }, { title: 'asc' }] }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -415,7 +423,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ take: 3 }) }, + query: { data: JSON.stringify({ take: 3 }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -425,7 +433,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ skip: 2, take: 2 }) }, + query: { data: JSON.stringify({ skip: 2, take: 2 }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -435,7 +443,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: { title: 'asc' }, skip: 1, take: 3 }) }, + query: { data: JSON.stringify({ orderBy: { title: 'asc' }, skip: 1, take: 3 }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -447,7 +455,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: { id: 'asc' }, take: 2 }) }, + query: { data: JSON.stringify({ orderBy: { id: 'asc' }, take: 2 }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -458,7 +466,7 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findMany', - query: { q: JSON.stringify({ orderBy: { id: 'asc' }, take: 2, skip: 1, cursor: { id: lastId } }) }, + query: { data: JSON.stringify({ orderBy: { id: 'asc' }, take: 2, skip: 1, cursor: { id: lastId } }) }, client: rawClient, }); expect(r.status).toBe(200); @@ -490,7 +498,9 @@ procedure echoOverview(o: Overview): Overview method: 'post', path: '/post/create', requestBody: { - data: { id: '2', title: 'post2', authorId: '1', published: false }, + data: { + data: { id: '2', title: 'post2', authorId: '1', published: false }, + }, }, client, }); @@ -503,8 +513,10 @@ procedure echoOverview(o: Overview): Overview method: 'put', path: '/post/update', requestBody: { - where: { id: '1' }, - data: { title: 'post2' }, + data: { + where: { id: '1' }, + data: { title: 'post2' }, + }, }, client, }); @@ -527,7 +539,9 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/post/create', - requestBody: { data: {} }, + requestBody: { + data: { data: {} }, + }, client: rawClient, }); expect(r.status).toBe(422); @@ -537,7 +551,9 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/user/create', - requestBody: { data: { email: 'hello' } }, + requestBody: { + data: { data: { email: 'hello' } }, + }, client: rawClient, }); expect(r.status).toBe(422); @@ -566,20 +582,20 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'get', path: '/post/findUnique', - query: { q: 'abc' }, + query: { data: 'abc' }, client: rawClient, }); expect(r.status).toBe(400); - expect(r.error.message).toContain('invalid "q" query parameter'); + expect(r.error.message).toContain('invalid "data" query parameter'); r = await handleRequest({ method: 'delete', path: '/post/deleteMany', - query: { q: 'abc' }, + query: { data: 'abc' }, client: rawClient, }); expect(r.status).toBe(400); - expect(r.error.message).toContain('invalid "q" query parameter'); + expect(r.error.message).toContain('invalid "data" query parameter'); }); it('field types', async () => { @@ -644,7 +660,7 @@ procedure echoOverview(o: Overview): Overview query: {}, client, requestBody: { - ...(serialized.json as any), + data: serialized.json, meta: { serialization: serialized.meta }, }, }); @@ -671,7 +687,7 @@ procedure echoOverview(o: Overview): Overview method: 'get', path: '/foo/findFirst', query: { - q: JSON.stringify(serializedQ.json), + data: JSON.stringify(serializedQ.json), meta: JSON.stringify({ serialization: serializedQ.meta }), }, client, @@ -689,7 +705,7 @@ procedure echoOverview(o: Overview): Overview method: 'get', path: '/foo/findFirst', query: { - q: JSON.stringify(serializedQ1.json), + data: JSON.stringify(serializedQ1.json), meta: JSON.stringify({ serialization: serializedQ1.meta }), }, client, @@ -711,7 +727,7 @@ procedure echoOverview(o: Overview): Overview method: 'get', path: '/foo/findFirst', query: { - q: JSON.stringify(serializedQ2.json), + data: JSON.stringify(serializedQ2.json), meta: JSON.stringify({ serialization: serializedQ2.meta }), }, client, @@ -733,7 +749,7 @@ procedure echoOverview(o: Overview): Overview method: 'get', path: '/foo/findFirst', query: { - q: JSON.stringify(serializedQ3.json), + data: JSON.stringify(serializedQ3.json), meta: JSON.stringify({ serialization: serializedQ3.meta }), }, client, @@ -754,7 +770,7 @@ procedure echoOverview(o: Overview): Overview query: {}, client, requestBody: { - ...(serializedUpdate.json as any), + data: serializedUpdate.json, meta: { serialization: serializedUpdate.meta }, }, }); @@ -774,23 +790,25 @@ procedure echoOverview(o: Overview): Overview const r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [ - { - model: 'User', - op: 'create', - args: { data: { id: 'txuser1', email: 'txuser1@abc.com' } }, - }, - { - model: 'Post', - op: 'create', - args: { data: { id: 'txpost1', title: 'Tx Post', authorId: 'txuser1' } }, - }, - { - model: 'Post', - op: 'findMany', - args: { where: { authorId: 'txuser1' } }, - }, - ], + requestBody: { + data: [ + { + model: 'User', + op: 'create', + args: { data: { id: 'txuser1', email: 'txuser1@abc.com' } }, + }, + { + model: 'Post', + op: 'create', + args: { data: { id: 'txpost1', title: 'Tx Post', authorId: 'txuser1' } }, + }, + { + model: 'Post', + op: 'findMany', + args: { where: { authorId: 'txuser1' } }, + }, + ], + }, client: rawClient, }); @@ -833,7 +851,9 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [], + requestBody: { + data: [], + }, client: rawClient, }); expect(r.status).toBe(400); @@ -842,7 +862,9 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: { model: 'User', op: 'findMany', args: {} }, + requestBody: { + data: { model: 'User', op: 'findMany', args: {} }, + }, client: rawClient, }); expect(r.status).toBe(400); @@ -855,7 +877,9 @@ procedure echoOverview(o: Overview): Overview const r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [{ model: 'Ghost', op: 'create', args: { data: {} } }], + requestBody: { + data: [{ model: 'Ghost', op: 'create', args: { data: {} } }], + }, client: rawClient, }); expect(r.status).toBe(400); @@ -868,7 +892,9 @@ procedure echoOverview(o: Overview): Overview const r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [{ model: 'User', op: 'dropTable', args: {} }], + requestBody: { + data: [{ model: 'User', op: 'dropTable', args: {} }], + }, client: rawClient, }); expect(r.status).toBe(400); @@ -881,7 +907,9 @@ procedure echoOverview(o: Overview): Overview let r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [{ op: 'create', args: { data: {} } }], + requestBody: { + data: [{ op: 'create', args: { data: {} } }], + }, client: rawClient, }); expect(r.status).toBe(400); @@ -890,7 +918,9 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [{ model: 'User', args: { data: {} } }], + requestBody: { + data: [{ model: 'User', args: { data: {} } }], + }, client: rawClient, }); expect(r.status).toBe(400); @@ -904,13 +934,15 @@ procedure echoOverview(o: Overview): Overview let r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [ - { - model: 'User', - op: 'findMany', - args: { where: { nonExistentField: 'value' } }, - }, - ], + requestBody: { + data: [ + { + model: 'User', + op: 'findMany', + args: { where: { nonExistentField: 'value' } }, + }, + ], + }, client: rawClient, }); expect(r.status).toBe(422); @@ -920,13 +952,15 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [ - { - model: 'Post', - op: 'findUnique', - args: {}, - }, - ], + requestBody: { + data: [ + { + model: 'Post', + op: 'findUnique', + args: {}, + }, + ], + }, client: rawClient, }); expect(r.status).toBe(422); @@ -936,14 +970,16 @@ procedure echoOverview(o: Overview): Overview r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [ - { - model: 'Post', - op: 'create', - // title is required but omitted - args: { data: {} }, - }, - ], + requestBody: { + data: [ + { + model: 'Post', + op: 'create', + // title is required but omitted + args: { data: {} }, + }, + ], + }, client: rawClient, }); expect(r.status).toBe(422); @@ -969,18 +1005,22 @@ procedure echoOverview(o: Overview): Overview const r = await handleRequest({ method: 'post', path: '/$transaction/sequential', - requestBody: [ - { - model: 'User', - op: 'create', - args: { ...(serialized.json as any), meta: { serialization: serialized.meta } }, - }, - { - model: 'Post', - op: 'create', - args: { ...(serializedPost.json as any), meta: { serialization: serializedPost.meta } }, - }, - ], + requestBody: { + data: [ + { + model: 'User', + op: 'create', + args: serialized.json, + meta: { serialization: serialized.meta }, + }, + { + model: 'Post', + op: 'create', + args: serializedPost.json, + meta: { serialization: serialized.meta }, + }, + ], + }, client: rawClient, }); diff --git a/packages/server/test/openapi/baseline/rpc.baseline.yaml b/packages/server/test/openapi/baseline/rpc.baseline.yaml index b268f9c9b..a62dbac8f 100644 --- a/packages/server/test/openapi/baseline/rpc.baseline.yaml +++ b/packages/server/test/openapi/baseline/rpc.baseline.yaml @@ -55,7 +55,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.findMany content: @@ -64,7 +64,7 @@ paths: $ref: "#/components/schemas/UserFindManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/findUnique: @@ -108,7 +108,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for User.findUnique @@ -118,7 +118,7 @@ paths: $ref: "#/components/schemas/UserFindUniqueArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/findFirst: @@ -162,7 +162,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.findFirst content: @@ -171,7 +171,7 @@ paths: $ref: "#/components/schemas/UserFindFirstArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/create: @@ -547,7 +547,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for User.delete @@ -557,7 +557,7 @@ paths: $ref: "#/components/schemas/UserDeleteArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/deleteMany: @@ -604,7 +604,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.deleteMany content: @@ -613,7 +613,7 @@ paths: $ref: "#/components/schemas/UserDeleteManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/count: @@ -654,7 +654,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.count content: @@ -663,7 +663,7 @@ paths: $ref: "#/components/schemas/UserCountArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/aggregate: @@ -704,7 +704,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.aggregate content: @@ -713,7 +713,7 @@ paths: $ref: "#/components/schemas/UserAggregateArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/groupBy: @@ -754,7 +754,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for User.groupBy @@ -764,7 +764,7 @@ paths: $ref: "#/components/schemas/UserGroupByArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /user/exists: @@ -806,7 +806,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for User.exists content: @@ -815,7 +815,7 @@ paths: $ref: "#/components/schemas/UserExistsArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/findMany: @@ -859,7 +859,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.findMany content: @@ -868,7 +868,7 @@ paths: $ref: "#/components/schemas/ProfileFindManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/findUnique: @@ -912,7 +912,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Profile.findUnique @@ -922,7 +922,7 @@ paths: $ref: "#/components/schemas/ProfileFindUniqueArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/findFirst: @@ -966,7 +966,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.findFirst content: @@ -975,7 +975,7 @@ paths: $ref: "#/components/schemas/ProfileFindFirstArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/create: @@ -1351,7 +1351,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Profile.delete @@ -1361,7 +1361,7 @@ paths: $ref: "#/components/schemas/ProfileDeleteArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/deleteMany: @@ -1408,7 +1408,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.deleteMany content: @@ -1417,7 +1417,7 @@ paths: $ref: "#/components/schemas/ProfileDeleteManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/count: @@ -1458,7 +1458,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.count content: @@ -1467,7 +1467,7 @@ paths: $ref: "#/components/schemas/ProfileCountArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/aggregate: @@ -1508,7 +1508,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.aggregate content: @@ -1517,7 +1517,7 @@ paths: $ref: "#/components/schemas/ProfileAggregateArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/groupBy: @@ -1558,7 +1558,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Profile.groupBy @@ -1568,7 +1568,7 @@ paths: $ref: "#/components/schemas/ProfileGroupByArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /profile/exists: @@ -1610,7 +1610,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Profile.exists content: @@ -1619,7 +1619,7 @@ paths: $ref: "#/components/schemas/ProfileExistsArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/findMany: @@ -1663,7 +1663,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.findMany content: @@ -1672,7 +1672,7 @@ paths: $ref: "#/components/schemas/PostFindManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/findUnique: @@ -1716,7 +1716,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Post.findUnique @@ -1726,7 +1726,7 @@ paths: $ref: "#/components/schemas/PostFindUniqueArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/findFirst: @@ -1770,7 +1770,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.findFirst content: @@ -1779,7 +1779,7 @@ paths: $ref: "#/components/schemas/PostFindFirstArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/create: @@ -2155,7 +2155,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Post.delete @@ -2165,7 +2165,7 @@ paths: $ref: "#/components/schemas/PostDeleteArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/deleteMany: @@ -2212,7 +2212,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.deleteMany content: @@ -2221,7 +2221,7 @@ paths: $ref: "#/components/schemas/PostDeleteManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/count: @@ -2262,7 +2262,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.count content: @@ -2271,7 +2271,7 @@ paths: $ref: "#/components/schemas/PostCountArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/aggregate: @@ -2312,7 +2312,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.aggregate content: @@ -2321,7 +2321,7 @@ paths: $ref: "#/components/schemas/PostAggregateArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/groupBy: @@ -2362,7 +2362,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Post.groupBy @@ -2372,7 +2372,7 @@ paths: $ref: "#/components/schemas/PostGroupByArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /post/exists: @@ -2414,7 +2414,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Post.exists content: @@ -2423,7 +2423,7 @@ paths: $ref: "#/components/schemas/PostExistsArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/findMany: @@ -2467,7 +2467,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.findMany content: @@ -2476,7 +2476,7 @@ paths: $ref: "#/components/schemas/CommentFindManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/findUnique: @@ -2520,7 +2520,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Comment.findUnique @@ -2530,7 +2530,7 @@ paths: $ref: "#/components/schemas/CommentFindUniqueArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/findFirst: @@ -2574,7 +2574,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.findFirst content: @@ -2583,7 +2583,7 @@ paths: $ref: "#/components/schemas/CommentFindFirstArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/create: @@ -2959,7 +2959,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Comment.delete @@ -2969,7 +2969,7 @@ paths: $ref: "#/components/schemas/CommentDeleteArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/deleteMany: @@ -3016,7 +3016,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.deleteMany content: @@ -3025,7 +3025,7 @@ paths: $ref: "#/components/schemas/CommentDeleteManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/count: @@ -3066,7 +3066,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.count content: @@ -3075,7 +3075,7 @@ paths: $ref: "#/components/schemas/CommentCountArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/aggregate: @@ -3116,7 +3116,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.aggregate content: @@ -3125,7 +3125,7 @@ paths: $ref: "#/components/schemas/CommentAggregateArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/groupBy: @@ -3166,7 +3166,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Comment.groupBy @@ -3176,7 +3176,7 @@ paths: $ref: "#/components/schemas/CommentGroupByArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /comment/exists: @@ -3218,7 +3218,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Comment.exists content: @@ -3227,7 +3227,7 @@ paths: $ref: "#/components/schemas/CommentExistsArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/findMany: @@ -3271,7 +3271,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.findMany content: @@ -3280,7 +3280,7 @@ paths: $ref: "#/components/schemas/SettingFindManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/findUnique: @@ -3324,7 +3324,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Setting.findUnique @@ -3334,7 +3334,7 @@ paths: $ref: "#/components/schemas/SettingFindUniqueArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/findFirst: @@ -3378,7 +3378,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.findFirst content: @@ -3387,7 +3387,7 @@ paths: $ref: "#/components/schemas/SettingFindFirstArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/create: @@ -3763,7 +3763,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Setting.delete @@ -3773,7 +3773,7 @@ paths: $ref: "#/components/schemas/SettingDeleteArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/deleteMany: @@ -3820,7 +3820,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.deleteMany content: @@ -3829,7 +3829,7 @@ paths: $ref: "#/components/schemas/SettingDeleteManyArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/count: @@ -3870,7 +3870,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.count content: @@ -3879,7 +3879,7 @@ paths: $ref: "#/components/schemas/SettingCountArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/aggregate: @@ -3920,7 +3920,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.aggregate content: @@ -3929,7 +3929,7 @@ paths: $ref: "#/components/schemas/SettingAggregateArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/groupBy: @@ -3970,7 +3970,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for Setting.groupBy @@ -3980,7 +3980,7 @@ paths: $ref: "#/components/schemas/SettingGroupByArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /setting/exists: @@ -4022,7 +4022,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query description: JSON-encoded arguments for Setting.exists content: @@ -4031,7 +4031,7 @@ paths: $ref: "#/components/schemas/SettingExistsArgs" - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /$procs/findPostsByUser: @@ -4087,7 +4087,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for procedure findPostsByUser @@ -4102,7 +4102,7 @@ paths: - args - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /$procs/getPostCount: @@ -4156,7 +4156,7 @@ paths: schema: $ref: "#/components/schemas/_rpcErrorResponse" parameters: - - name: q + - name: data in: query required: true description: JSON-encoded arguments for procedure getPostCount @@ -4171,7 +4171,7 @@ paths: - args - name: meta in: query - description: JSON-encoded SuperJSON serialization metadata for the "q" parameter + description: JSON-encoded SuperJSON serialization metadata for the "data" parameter schema: type: string /$procs/publishPost: diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts index 6e25cb270..b5532ec00 100644 --- a/packages/server/test/openapi/rpc-openapi.test.ts +++ b/packages/server/test/openapi/rpc-openapi.test.ts @@ -201,23 +201,23 @@ describe('RPC OpenAPI spec generation - input schemas', () => { spec = await generateSpec(handler); }); - it('GET operations have q query parameter', () => { + it('GET operations have data query parameter', () => { for (const op of ['findMany', 'findFirst', 'findUnique', 'count', 'aggregate', 'groupBy', 'exists']) { const operation = spec.paths[`/user/${op}`].get; - const qParam = operation.parameters?.find((p: any) => p.name === 'q'); - expect(qParam, `q param on /user/${op}`).toBeDefined(); - expect(qParam.in).toBe('query'); + const dataParam = operation.parameters?.find((p: any) => p.name === 'data'); + expect(dataParam, `data param on /user/${op}`).toBeDefined(); + expect(dataParam.in).toBe('query'); // OAPI 3.1 content-typed parameter for complex JSON - expect(qParam.content?.['application/json']?.schema).toBeDefined(); + expect(dataParam.content?.['application/json']?.schema).toBeDefined(); } }); - it('DELETE operations have q query parameter', () => { + it('DELETE operations have data query parameter', () => { for (const op of ['delete', 'deleteMany']) { const operation = spec.paths[`/user/${op}`].delete; - const qParam = operation.parameters?.find((p: any) => p.name === 'q'); - expect(qParam, `q param on /user/${op}`).toBeDefined(); - expect(qParam.content?.['application/json']?.schema).toBeDefined(); + const dataParam = operation.parameters?.find((p: any) => p.name === 'data'); + expect(dataParam, `data param on /user/${op}`).toBeDefined(); + expect(dataParam.content?.['application/json']?.schema).toBeDefined(); } }); @@ -238,9 +238,9 @@ describe('RPC OpenAPI spec generation - input schemas', () => { } }); - it('findUnique q schema contains where field', () => { + it('findUnique data schema contains where field', () => { const operation = spec.paths['/user/findUnique'].get; - const qSchema = operation.parameters.find((p: any) => p.name === 'q').content['application/json'].schema; + const qSchema = operation.parameters.find((p: any) => p.name === 'data').content['application/json'].schema; // The schema describes FindUniqueArgs which has a required where field expect(qSchema).toBeDefined(); expect(qSchema.type === 'object' || qSchema.properties || qSchema.$defs || qSchema.$ref).toBeTruthy(); @@ -774,17 +774,17 @@ procedure optionalSearch(query: String?): User[] expect(spec.paths?.['/$procs/createUser']?.get).toBeUndefined(); }); - it('query procedure has q parameter with args envelope schema', async () => { + it('query procedure has data parameter with args envelope schema', async () => { const client = await createTestClient(procSchema); const handler = new RPCApiHandler({ schema: client.$schema }); const spec = await generateSpec(handler); const operation = spec.paths?.['/$procs/getUser']?.get; - const qParam: any = operation?.parameters?.find((p: any) => p.name === 'q'); - expect(qParam).toBeDefined(); - expect(qParam?.content?.['application/json']?.schema).toBeDefined(); + const dataParam: any = operation?.parameters?.find((p: any) => p.name === 'data'); + expect(dataParam).toBeDefined(); + expect(dataParam?.content?.['application/json']?.schema).toBeDefined(); // args is a $ref to the registered ProcArgs component schema - const envelopeSchema = qParam?.content['application/json'].schema; + const envelopeSchema = dataParam?.content['application/json'].schema; const argsRef = envelopeSchema.properties?.args?.$ref; expect(argsRef).toBeDefined(); const argsSchemaName = argsRef.replace('#/components/schemas/', ''); @@ -834,9 +834,9 @@ mutation procedure softDelete(id: Int?): User const spec = await generateSpec(handler); const operation = spec?.paths?.['/$procs/optionalSearch']?.get; - const qParam = operation?.parameters?.find((p: any) => p.name === 'q'); + const dataParam = operation?.parameters?.find((p: any) => p.name === 'data'); // args is a $ref to the registered ProcArgs component schema - const argsRef = (qParam as any)?.content?.['application/json']?.schema?.properties?.args?.$ref; + const argsRef = (dataParam as any)?.content?.['application/json']?.schema?.properties?.args?.$ref; expect(argsRef).toBeDefined(); const argsSchemaName = argsRef.replace('#/components/schemas/', ''); const argsSchema = spec.components?.schemas?.[argsSchemaName] as any; From 8083594138eaf9f5345c0dd394ac6b4814021edf Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:17:03 +0000 Subject: [PATCH 12/14] chore(cli): adjust tests --- packages/cli/test/proxy.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/test/proxy.test.ts b/packages/cli/test/proxy.test.ts index 2e523b69a..f04e4a1b0 100644 --- a/packages/cli/test/proxy.test.ts +++ b/packages/cli/test/proxy.test.ts @@ -29,7 +29,7 @@ const TEST_PUBLIC_KEY_DER = 'MCowBQYDK2VwAyEAFSJV7wjdFuDz2CqYX7hGnITQvcmJYy7OJQq function buildSignatureHeader(options: { privateKey: string; method: string; - /** Path + optional query string, e.g. `/api/model/user/findMany?q=%7B%7D` */ + /** Path + optional query string, e.g. `/api/model/user/findMany?data=%7B%7D` */ pathWithQuery: string; body?: unknown; authorizationToken?: string; @@ -259,7 +259,7 @@ describe('CLI proxy tests', () => { // Confirm persisted outside transaction too. const userRes = await fetch( - `${baseUrl}/api/model/user/findUnique?q=${encodeURIComponent(JSON.stringify({ where: { id: 'u1' } }))}`, + `${baseUrl}/api/model/user/findUnique?data=${encodeURIComponent(JSON.stringify({ where: { id: 'u1' } }))}`, ); expect(userRes.status).toBe(200); const user = await userRes.json(); @@ -317,8 +317,8 @@ describe('CLI proxy tests', () => { // Pre-seed a record directly via client await client.user.create({ data: { id: 'u1', email: 'alice@example.com' } }); - const q = encodeURIComponent(JSON.stringify({ where: { id: 'u1' } })); - const pathWithQuery = `/api/model/user/findUnique?q=${q}`; + const data = encodeURIComponent(JSON.stringify({ where: { id: 'u1' } })); + const pathWithQuery = `/api/model/user/findUnique?data=${data}`; const sig = buildSignatureHeader({ privateKey: TEST_PRIVATE_KEY, method: 'GET', From 2881fb54773b3958a3188143d4822d1a8a782330 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:17:54 +0000 Subject: [PATCH 13/14] chore: regenerate schemas --- packages/zod/test/schema/schema-lite.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/zod/test/schema/schema-lite.ts b/packages/zod/test/schema/schema-lite.ts index c1f44d019..6baa6ca49 100644 --- a/packages/zod/test/schema/schema-lite.ts +++ b/packages/zod/test/schema/schema-lite.ts @@ -18,6 +18,7 @@ export class SchemaType implements SchemaDef { name: "id", type: "String", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("cuid") as FieldDefault }, email: { @@ -129,6 +130,7 @@ export class SchemaType implements SchemaDef { name: "id", type: "String", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("cuid") as FieldDefault }, title: { @@ -171,6 +173,7 @@ export class SchemaType implements SchemaDef { name: "id", type: "String", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("cuid") as FieldDefault }, name: { @@ -184,6 +187,7 @@ export class SchemaType implements SchemaDef { discount: { name: "discount", type: "Float", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.literal(0) }] }] as readonly AttributeApplication[], default: 0 as FieldDefault }, finalPrice: { @@ -211,11 +215,13 @@ export class SchemaType implements SchemaDef { name: "id", type: "Int", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("autoincrement") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("autoincrement") as FieldDefault }, createdAt: { name: "createdAt", type: "DateTime", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("now") as FieldDefault }, assetType: { @@ -239,12 +245,14 @@ export class SchemaType implements SchemaDef { name: "id", type: "Int", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("autoincrement") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("autoincrement") as FieldDefault }, createdAt: { name: "createdAt", type: "DateTime", originModel: "Asset", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("now") as FieldDefault }, assetType: { @@ -275,12 +283,14 @@ export class SchemaType implements SchemaDef { name: "id", type: "Int", id: true, + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("autoincrement") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("autoincrement") as FieldDefault }, createdAt: { name: "createdAt", type: "DateTime", originModel: "Asset", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }] as readonly AttributeApplication[], default: ExpressionUtils.call("now") as FieldDefault }, assetType: { From fe9ce9e99b712ea56dd1c3664f587510c67e2dd4 Mon Sep 17 00:00:00 2001 From: sanny-io Date: Tue, 1 Sep 2026 07:30:09 +0000 Subject: [PATCH 14/14] chore(fetch-client): fix test --- packages/clients/fetch-client/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clients/fetch-client/src/index.ts b/packages/clients/fetch-client/src/index.ts index 2c22dc18b..de44f0892 100644 --- a/packages/clients/fetch-client/src/index.ts +++ b/packages/clients/fetch-client/src/index.ts @@ -8,7 +8,7 @@ import { type TransactionOperation, type TransactionResults, } from '@zenstackhq/client-helpers'; -import { fetcher, makeUrl, marshal, type FetchFn } from '@zenstackhq/client-helpers/fetch'; +import { fetcher, makeUrl, marshal, type FetchFn, serialize } from '@zenstackhq/client-helpers/fetch'; import { lowerCaseFirst } from '@zenstackhq/common-helpers'; import type { AllModelOperations,