Skip to content

Commit

Permalink
Update reply type resolver (#4360)
Browse files Browse the repository at this point in the history
  • Loading branch information
rain714 committed Oct 20, 2022
1 parent 6891451 commit f034113
Show file tree
Hide file tree
Showing 2 changed files with 316 additions and 3 deletions.
311 changes: 311 additions & 0 deletions test/types/type-provider.test-d.ts
Expand Up @@ -231,6 +231,40 @@ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
}
))

// -------------------------------------------------------------------
// TypeBox Reply Type (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: Type.String()
},
'application/json': {
schema: Type.Object({
msg: Type.String()
})
}
}
},
500: Type.Object({
error: Type.String()
})
}
}
},
async (_, res) => {
res.send('hello')
res.send({ msg: 'hello' })
res.send({ error: 'error' })
}
))

// -------------------------------------------------------------------
// TypeBox Reply Type: Non Assignable
// -------------------------------------------------------------------
Expand All @@ -253,6 +287,38 @@ expectError(server.withTypeProvider<TypeBoxProvider>().get(
}
))

// -------------------------------------------------------------------
// TypeBox Reply Type: Non Assignable (Different Content-types)
// -------------------------------------------------------------------

expectError(server.withTypeProvider<TypeBoxProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: Type.String()
},
'application/json': {
schema: Type.Object({
msg: Type.String()
})
}
}
},
500: Type.Object({
error: Type.String()
})
}
}
},
async (_, res) => {
res.send(false)
}
))

// -------------------------------------------------------------------
// TypeBox Reply Return Type
// -------------------------------------------------------------------
Expand Down Expand Up @@ -280,6 +346,43 @@ expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
}
))

// -------------------------------------------------------------------
// TypeBox Reply Return Type (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<TypeBoxProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: Type.String()
},
'application/json': {
schema: Type.Object({
msg: Type.String()
})
}
}
},
500: Type.Object({
error: Type.String()
})
}
}
},
async (_, res) => {
const option = 1 as 1 | 2 | 3
switch (option) {
case 1: return 'hello'
case 2: return { msg: 'hello' }
case 3: return { error: 'error' }
}
}
))

// -------------------------------------------------------------------
// TypeBox Reply Return Type: Non Assignable
// -------------------------------------------------------------------
Expand All @@ -302,6 +405,38 @@ expectError(server.withTypeProvider<TypeBoxProvider>().get(
}
))

// -------------------------------------------------------------------
// TypeBox Reply Return Type: Non Assignable (Different Content-types)
// -------------------------------------------------------------------

expectError(server.withTypeProvider<TypeBoxProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: Type.String()
},
'application/json': {
schema: Type.Object({
msg: Type.String()
})
}
}
},
500: Type.Object({
error: Type.String()
})
}
}
},
async (_, res) => {
return false
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type
// -------------------------------------------------------------------
Expand All @@ -324,6 +459,36 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
(_, res) => {
res.send('hello')
res.send({ msg: 'hello' })
res.send({ error: 'error' })
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type: Non Assignable
// -------------------------------------------------------------------
Expand All @@ -344,6 +509,34 @@ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type: Non Assignable (Different Content-types)
// -------------------------------------------------------------------

expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
async (_, res) => {
res.send(false)
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type Return
// -------------------------------------------------------------------
Expand All @@ -368,6 +561,40 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
}
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type Return (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
async (_, res) => {
const option = 1 as 1 | 2 | 3
switch (option) {
case 1: return 'hello'
case 2: return { msg: 'hello' }
case 3: return { error: 'error' }
}
}
))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type Return: Non Assignable
// -------------------------------------------------------------------
Expand Down Expand Up @@ -399,6 +626,34 @@ expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get('/', {
return { foo: 555 }
}))

// -------------------------------------------------------------------
// JsonSchemaToTs Reply Type Return: Non Assignable (Different Content-types)
// -------------------------------------------------------------------

expectError(server.withTypeProvider<JsonSchemaToTsProvider>().get(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
async (_, res) => {
return false
}
))

// -------------------------------------------------------------------
// Reply Type Override
// -------------------------------------------------------------------
Expand All @@ -419,6 +674,34 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: b
}
))

// -------------------------------------------------------------------
// Reply Type Override (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: boolean}>(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
async (_, res) => {
res.send(true)
}
))

// -------------------------------------------------------------------
// Reply Type Return Override
// -------------------------------------------------------------------
Expand All @@ -439,6 +722,34 @@ expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: b
}
))

// -------------------------------------------------------------------
// Reply Type Return Override (Different Content-types)
// -------------------------------------------------------------------

expectAssignable(server.withTypeProvider<JsonSchemaToTsProvider>().get<{Reply: boolean}>(
'/',
{
schema: {
response: {
200: {
content: {
'text/string': {
schema: { type: 'string' }
},
'application/json': {
schema: { type: 'object', properties: { msg: { type: 'string' } } }
}
}
},
500: { type: 'object', properties: { error: { type: 'string' } } }
} as const
}
},
async (_, res) => {
return true
}
))

// -------------------------------------------------------------------
// FastifyPlugin: Auxiliary
// -------------------------------------------------------------------
Expand Down
8 changes: 5 additions & 3 deletions types/type-provider.d.ts
Expand Up @@ -60,10 +60,12 @@ export interface ResolveFastifyRequestType<TypeProvider extends FastifyTypeProvi
// FastifyReplyType
// -----------------------------------------------------------------------------------------------

// Resolves the Reply type by taking a union of response status codes
// Resolves the Reply type by taking a union of response status codes and content-types
type ResolveReplyFromSchemaCompiler<TypeProvider extends FastifyTypeProvider, SchemaCompiler extends FastifySchema> = {
[K in keyof SchemaCompiler['response']]: CallTypeProvider<TypeProvider, SchemaCompiler['response'][K]>
} extends infer Result ? Result[keyof Result] : unknown
[K1 in keyof SchemaCompiler['response']]: SchemaCompiler['response'][K1] extends { content: { [keyof: string]: { schema: unknown } } } ? ({
[K2 in keyof SchemaCompiler['response'][K1]['content']]: CallTypeProvider<TypeProvider, SchemaCompiler['response'][K1]['content'][K2]['schema']>
} extends infer Result ? Result[keyof Result] : unknown) : CallTypeProvider<TypeProvider, SchemaCompiler['response'][K1]>
} extends infer Result ? Result[keyof Result] : unknown;

// The target reply type. This type is inferenced on fastify 'replies' via generic argument assignment
export type FastifyReplyType<Reply = unknown> = Reply
Expand Down

0 comments on commit f034113

Please sign in to comment.