Skip to content

Commit

Permalink
Merge pull request #962 from macabeus/fix-issue-950
Browse files Browse the repository at this point in the history
🔧 fix schema default value when AOT is off
  • Loading branch information
SaltyAom authored Dec 24, 2024
2 parents 5dfebc8 + e66eb0b commit e83daaf
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 9 deletions.
35 changes: 27 additions & 8 deletions src/dynamic-handle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { parseCookie } from './cookies'

import type { Handler, LifeCycleStore, SchemaValidator } from './types'
import { TransformDecodeError } from '@sinclair/typebox/value'
import { TypeCheck } from './type-system'

// JIT Handler
export type DynamicHandler = {
Expand All @@ -25,6 +26,14 @@ export type DynamicHandler = {
validator?: SchemaValidator
}

const injectDefaultValues = (typeChecker: TypeCheck<any>, obj: Record<string, any>) => {
// @ts-expect-error private
for (const [key, keySchema] of Object.entries(typeChecker.schema.properties)) {
// @ts-expect-error private
obj[key] ??= keySchema.default
}
}

export const createDynamicHandler = (app: AnyElysia) => {
const { mapResponse, mapEarlyResponse } = app['~adapter'].handler

Expand Down Expand Up @@ -220,6 +229,18 @@ export const createDynamicHandler = (app: AnyElysia) => {
: undefined
)) as any

const headerValidator = validator?.createHeaders?.()
if (headerValidator)
injectDefaultValues(headerValidator, context.headers)

const paramsValidator = validator?.createParams?.()
if (paramsValidator)
injectDefaultValues(paramsValidator, context.params)

const queryValidator = validator?.createQuery?.()
if (queryValidator)
injectDefaultValues(queryValidator, context.query)

for (let i = 0; i < hooks.transform.length; i++) {
const hook = hooks.transform[i]
const operation = hook.fn(context)
Expand All @@ -232,10 +253,10 @@ export const createDynamicHandler = (app: AnyElysia) => {
}

if (validator) {
if (validator.createHeaders?.()) {
const _header: Record<string, string> = {}
for (const key in request.headers)
_header[key] = request.headers.get(key)!
if (headerValidator) {
const _header = structuredClone(context.headers)
for (const [key, value] of request.headers)
_header[key] = value

if (validator.headers!.Check(_header) === false)
throw new ValidationError(
Expand All @@ -247,9 +268,7 @@ export const createDynamicHandler = (app: AnyElysia) => {
// @ts-ignore
context.headers = validator.headers.Decode(context.headers)

if (
validator.createParams?.()?.Check(context.params) === false
) {
if (paramsValidator?.Check(context.params) === false) {
throw new ValidationError(
'params',
validator.params!,
Expand All @@ -259,7 +278,7 @@ export const createDynamicHandler = (app: AnyElysia) => {
// @ts-ignore
context.params = validator.params.Decode(context.params)

if (validator.createQuery?.()?.Check(context.query) === false)
if (queryValidator?.Check(context.query) === false)
throw new ValidationError(
'query',
validator.query!,
Expand Down
28 changes: 28 additions & 0 deletions test/core/dynamic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,34 @@ describe('Dynamic Mode', () => {
expect(res).toBe('me - v1,v2')
})

it('default value', async () => {
const app = new Elysia({ aot: false }).get(
"/:propParams?",
({ params: { propParams }, headers: { propHeader }, query: { propQuery } }) => `${propParams} ${propHeader} ${propQuery}`,
{
params: t.Object({
propParams: t.String({
default: "params-default",
}),
}),
headers: t.Object({
propHeader: t.String({
default: "header-default",
}),
}),
query: t.Object({
propQuery: t.String({
default: "query-default",
}),
}),
}
);

const response = await app.handle(new Request('http://localhost')).then((x) => x.text());

expect(response).toBe('params-default header-default query-default');
});

it('handle non query fallback', async () => {
const app = new Elysia({ aot: false }).get('/', () => 'hi', {
query: t.Object({
Expand Down
35 changes: 34 additions & 1 deletion test/core/elysia.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Elysia } from '../../src'
import { Elysia, t } from '../../src'

import { describe, expect, it } from 'bun:test'
import { req } from '../utils'
Expand Down Expand Up @@ -173,4 +173,37 @@ describe('Edge Case', () => {
// @ts-expect-error private property
expect(main.getGlobalRoutes().length).toBe(2)
})

describe('value returned from transform has priority over the default value from schema', () => {
const route = new Elysia().get(
"/:propParams?",
({ params: { propParams } }) => propParams,
{
params: t.Object({
propParams: t.String({
default: "params-default",
}),
}),
transform({ params }) {
params.propParams = "params-transform"
}
}
)

it('aot is on', async () => {
const app = new Elysia().use(route);

const response = await app.handle(new Request('http://localhost')).then((x) => x.text());

expect(response).toBe('params-transform');
})

it('aot is off', async () => {
const app = new Elysia({ aot: false }).use(route);

const response = await app.handle(new Request('http://localhost')).then((x) => x.text());

expect(response).toBe('params-transform');
})
})
})

0 comments on commit e83daaf

Please sign in to comment.