Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/app/api-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"zod": ">=3.25.56"
},
"devDependencies": {
"@biomejs/biome": "^2.3.7",
"@biomejs/biome": "^2.4.7",
"@lokalise/biome-config": "^3.1.0",
"@lokalise/tsconfig": "^3.1.0",
"@vitest/coverage-v8": "^4.0.18",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { describe, expectTypeOf, it } from 'vitest'
import { z } from 'zod/v4'
import type { GetRouteDefinition } from './apiContracts.ts'
import { buildContract } from './contractBuilder.ts'
import type { DualModeContractDefinition } from './sse/dualModeContracts.ts'
import type { SSEContractDefinition } from './sse/sseContracts.ts'

describe('buildContract type inference', () => {
// ============================================================================
Expand Down Expand Up @@ -397,7 +395,6 @@ describe('buildContract type inference', () => {
},
})

expectTypeOf(contract).toMatchTypeOf<SSEContractDefinition<'get'>>()
expectTypeOf(contract.method).toEqualTypeOf<'get'>()
expectTypeOf(contract.isSSE).toEqualTypeOf<true>()
})
Expand Down Expand Up @@ -641,7 +638,6 @@ describe('buildContract type inference', () => {
},
})

expectTypeOf(contract).toMatchTypeOf<DualModeContractDefinition<'get'>>()
expectTypeOf(contract.method).toEqualTypeOf<'get'>()
expectTypeOf(contract.isDualMode).toEqualTypeOf<true>()
})
Expand Down
8 changes: 4 additions & 4 deletions packages/app/api-contracts/src/sse/dualModeContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import type { SSEEventSchemas } from './sseTypes.ts'
*/
export type DualModeContractDefinition<
Method extends SSEMethod = SSEMethod,
Params extends z.ZodTypeAny = z.ZodTypeAny,
Query extends z.ZodTypeAny = z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny = z.ZodTypeAny,
Params extends z.ZodTypeAny | undefined = undefined,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was inconsistent with simple REST contracts for no good reason, which made using them harder

Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Body extends z.ZodTypeAny | undefined = undefined,
SyncResponse extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
Expand All @@ -32,7 +32,7 @@ export type DualModeContractDefinition<
| undefined = undefined,
> = {
method: Method
pathResolver: RoutePathResolver<z.infer<Params>>
pathResolver: Params extends z.ZodTypeAny ? RoutePathResolver<z.infer<Params>> : () => string
requestPathParamsSchema?: Params
requestQuerySchema?: Query
requestHeaderSchema?: RequestHeaders
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('contractBuilders', () => {
const route = buildSseContract(baseConfig)

expect(route.method).toBe('post')
expect(route.pathResolver({})).toBe('/api/test')
expect(route.pathResolver()).toBe('/api/test')
expect(route.isSSE).toBe(true)
})

Expand Down
88 changes: 44 additions & 44 deletions packages/app/api-contracts/src/sse/sseContractBuilders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import type { SSEEventSchemas } from './sseTypes.ts'
* Forbids requestBodySchema for GET variants.
*/
export type SSEGetContractConfig<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
> = {
method: 'get'
pathResolver: RoutePathResolver<z.infer<Params>>
pathResolver: Params extends z.ZodTypeAny ? RoutePathResolver<z.infer<Params>> : () => string
requestPathParamsSchema?: Params
requestQuerySchema?: Query
requestHeaderSchema?: RequestHeaders
Expand Down Expand Up @@ -51,17 +51,17 @@ export type SSEGetContractConfig<
* Requires requestBodySchema for payload variants.
*/
export type SSEPayloadContractConfig<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Body extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Body extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
> = {
method: 'post' | 'put' | 'patch'
pathResolver: RoutePathResolver<z.infer<Params>>
pathResolver: Params extends z.ZodTypeAny ? RoutePathResolver<z.infer<Params>> : () => string
requestPathParamsSchema?: Params
requestQuerySchema?: Query
requestHeaderSchema?: RequestHeaders
Expand Down Expand Up @@ -93,18 +93,18 @@ export type SSEPayloadContractConfig<
* Requires successResponseBodySchema, forbids requestBodySchema.
*/
export type DualModeGetContractConfig<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
JsonResponse extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseHeaders extends z.ZodTypeAny | undefined = undefined,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
> = {
method: 'get'
pathResolver: RoutePathResolver<z.infer<Params>>
pathResolver: Params extends z.ZodTypeAny ? RoutePathResolver<z.infer<Params>> : () => string
requestPathParamsSchema?: Params
requestQuerySchema?: Query
requestHeaderSchema?: RequestHeaders
Expand Down Expand Up @@ -149,19 +149,19 @@ export type DualModeGetContractConfig<
* Requires both requestBodySchema and successResponseBodySchema.
*/
export type DualModePayloadContractConfig<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Body extends z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Body extends z.ZodTypeAny = z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseHeaders extends z.ZodTypeAny | undefined = undefined,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
> = {
method: 'post' | 'put' | 'patch'
pathResolver: RoutePathResolver<z.infer<Params>>
pathResolver: Params extends z.ZodTypeAny ? RoutePathResolver<z.infer<Params>> : () => string
requestPathParamsSchema?: Params
requestQuerySchema?: Query
requestHeaderSchema?: RequestHeaders
Expand Down Expand Up @@ -280,11 +280,11 @@ function determineMethod(config: { method: string }) {

// Overload 1: Dual-mode GET (has successResponseBodySchema, no requestBodySchema)
export function buildSseContract<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
JsonResponse extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseHeaders extends z.ZodTypeAny | undefined = undefined,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
Expand Down Expand Up @@ -313,10 +313,10 @@ export function buildSseContract<

// Overload 2: SSE GET (no requestBodySchema, no successResponseBodySchema)
export function buildSseContract<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
Expand All @@ -334,12 +334,12 @@ export function buildSseContract<

// Overload 3: Dual-mode with body (has successResponseBodySchema + requestBodySchema)
export function buildSseContract<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Body extends z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Body extends z.ZodTypeAny = z.ZodTypeAny,
JsonResponse extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseHeaders extends z.ZodTypeAny | undefined = undefined,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
Expand Down Expand Up @@ -369,11 +369,11 @@ export function buildSseContract<

// Overload 4: SSE with body (has requestBodySchema, no successResponseBodySchema)
export function buildSseContract<
Params extends z.ZodTypeAny,
Query extends z.ZodTypeAny,
RequestHeaders extends z.ZodTypeAny,
Body extends z.ZodTypeAny,
Events extends SSEEventSchemas,
Params extends z.ZodTypeAny | undefined = undefined,
Query extends z.ZodTypeAny | undefined = undefined,
RequestHeaders extends z.ZodTypeAny | undefined = undefined,
Body extends z.ZodTypeAny = z.ZodTypeAny,
Events extends SSEEventSchemas = SSEEventSchemas,
ResponseSchemasByStatusCode extends
| Partial<Record<HttpStatusCode, z.ZodTypeAny>>
| undefined = undefined,
Expand Down
Loading
Loading