Skip to content

Commit

Permalink
🎉 feat: test case
Browse files Browse the repository at this point in the history
  • Loading branch information
SaltyAom committed Dec 10, 2023
1 parent 62c7ed9 commit e941e21
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 268 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# 0.8.0
Feature:
- `header` initialization function
- `headers` initialization function
- inline static resources
- support default properties
- extension API
- error function
- add stack trace to plugin checksum
- new life-cycle
- `resolve`: derive after validation
- `mapResponse`: custom response mapping
- add stack trace to plugin checksum

Improvement:
- lazy query reference
Expand Down
16 changes: 9 additions & 7 deletions example/a.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { Elysia, t } from '../src'
import { req } from '../test/utils'

const app = new Elysia().get('/', () => 'NOOP', {
mapResponse() {
return new Response('A')
}
})
const app = new Elysia()
.get('/', Bun.file('test/kyuukurarin.mp4'))
.compile()

console.log(app.routes[0].composed?.toString())
// console.log(app.fetch.toString())

// console.log(app)

// console.log(app.routes[0].composed?.toString())

app.handle(req('/'))
.then((x) => x.text())
.then((x) => x.headers)
.then(console.log)
35 changes: 18 additions & 17 deletions src/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,8 @@ export const composeHandler = ({
const hasHeaders =
hasUnknownContext ||
validator.headers ||
lifeCycleLiteral.some((fn) => isFnUse('headers', fn))
lifeCycleLiteral.some((fn) => isFnUse('headers', fn)) ||
(setHeader && Object.keys(setHeader).length)

const hasCookie =
hasUnknownContext ||
Expand All @@ -613,8 +614,8 @@ export const composeHandler = ({
const secret = !cookieMeta.secrets
? undefined
: typeof cookieMeta.secrets === 'string'
? cookieMeta.secrets
: cookieMeta.secrets[0]
? cookieMeta.secrets
: cookieMeta.secrets[0]

encodeCookie += `const _setCookie = c.set.cookie
if(_setCookie) {`
Expand Down Expand Up @@ -680,10 +681,10 @@ export const composeHandler = ({
cookieMeta.sign === true
? true
: cookieMeta.sign !== undefined
? '[' +
cookieMeta.sign.reduce((a, b) => a + `'${b}',`, '') +
']'
: 'undefined'
? '[' +
cookieMeta.sign.reduce((a, b) => a + `'${b}',`, '') +
']'
: 'undefined'
},
${get('domain')}
${get('expires')}
Expand Down Expand Up @@ -1185,7 +1186,6 @@ export const composeHandler = ({
fnLiteral += isAsync(hooks.beforeHandle[i])
? `await beforeHandle[${i}](c);\n`
: `beforeHandle[${i}](c);\n`


endUnit()
} else {
Expand Down Expand Up @@ -1337,8 +1337,7 @@ export const composeHandler = ({

endHandle()

if(validator.response)
fnLiteral += composeResponseValidation()
if (validator.response) fnLiteral += composeResponseValidation()

report('afterHandle')()

Expand Down Expand Up @@ -1583,11 +1582,11 @@ export const composeGeneralHandler = (
app.event.error.length
? `app.handleError(ctx, notFound)`
: app.event.request.length
? `new Response(error404Message, {
? `new Response(error404Message, {
status: ctx.set.status === 200 ? 404 : ctx.set.status,
headers: ctx.set.headers
})`
: `error404.clone()`
: `error404.clone()`
}
ctx.params = route.params
Expand Down Expand Up @@ -1656,8 +1655,8 @@ export const composeGeneralHandler = (
set: {
headers: ${
// @ts-ignore
Object.keys(app.setHeader ?? {}).length
? 'Object.assign(app.setHeader)'
Object.keys(app.setHeaders ?? {}).length
? 'Object.assign(app.setHeaders)'
: '{}'
},
status: 200
Expand Down Expand Up @@ -1728,8 +1727,8 @@ export const composeGeneralHandler = (
set: {
headers: ${
// @ts-ignore
Object.keys(app.setHeader ?? {}).length
? 'Object.assign(app.setHeader)'
Object.keys(app.setHeaders ?? {}).length
? 'Object.assign(app.setHeaders)'
: '{}'
},
status: 200
Expand Down Expand Up @@ -1837,7 +1836,9 @@ export const composeErrorHandler = (
for (let i = 0; i < app.event.error.length; i++) {
const handler = app.event.error[i]

const response = `${isAsync(handler) ? 'await ' : ''}onError[${i}](context)`
const response = `${
isAsync(handler) ? 'await ' : ''
}onError[${i}](context)`

if (hasReturn(handler.toString()))
fnLiteral += `const r${i} = ${response}; if(r${i} !== undefined) {
Expand Down
108 changes: 63 additions & 45 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import type { Context } from './context'
import { ElysiaWS, websocket } from './ws'
import type { WS } from './ws/types'

import { isNotEmpty, mapCompactResponse, mapResponse } from './handler'
import { isNotEmpty, mapEarlyResponse } from './handler'
import {
composeHandler,
composeGeneralHandler,
composeErrorHandler,
isFnUse
composeErrorHandler
} from './compose'
import {
mergeHook,
Expand Down Expand Up @@ -203,7 +202,7 @@ export default class Elysia<
private add(
method: HTTPMethod,
paths: string | Readonly<string[]>,
handler: Handler<any, any, any> | unknown,
handle: Handler<any, any, any> | any,
localHook?: LocalHook<any, any, any, any, any>,
{ allowMeta = false, skipPrefix = false } = {
allowMeta: false as boolean | undefined,
Expand Down Expand Up @@ -445,36 +444,7 @@ export default class Elysia<

const hooks = mergeHook(globalHook, localHook)

const isFn = typeof handler === 'function'
let handle: Handler<any, any> = isFn ? handler : ((() => '') as any)
if (!isFn) {
const response = mapCompactResponse(handler)

handle = () => response.clone()
// @ts-ignore
handle.response = response

const lifeCycleLiteral =
validator || (method !== 'GET' && method !== 'HEAD')
? [
handler,
...hooks.onResponse,
...hooks.transform,
...hooks.beforeHandle,
...hooks.afterHandle
].map((x) =>
typeof x === 'function' ? x.toString() : `${x}`
)
: []

if (!lifeCycleLiteral.some((fn) => isFnUse('set', fn)))
handler = this.setHeader
? mapResponse(handler, {
status: 200,
headers: this.setHeader as any
})
: mapCompactResponse(handler)
}
const isFn = typeof handle === 'function'

if (this.config.aot === false) {
this.dynamicRouter.add(method, path, {
Expand Down Expand Up @@ -509,20 +479,68 @@ export default class Elysia<
method,
hooks,
validator,
handler,
handler: handle,
handleError: this.handleError,
onRequest: this.event.request,
config: this.config,
definitions: allowMeta ? this.definitions.type : undefined,
schema: allowMeta ? this.schema : undefined,
getReporter: () => this.reporter,
setHeader: this.setHeader
setHeader: this.setHeaders
})

// @ts-ignore
if (handle.response)
if (!isFn) {
const context = Object.assign(
{
headers: {},
query: {},
params: {} as never,
body: undefined,
request: new Request(`http://localhost${path}`),
store: this.store,
path: path,
set: {
headers: this.setHeaders ?? {},
status: 200
}
},
this.decorators as any
)

let response

for (const onRequest of Object.values(hooks.request)) {
try {
const inner = mapEarlyResponse(
onRequest(context),
context.set
)
if (inner !== undefined) {
response = inner
break
}
} catch (error) {
response = this.handleError(context, error as Error)
break
}
}

// @ts-ignore
mainHandler.response = handle.response
if (response) mainHandler.response = response
else {
try {
// @ts-ignore
mainHandler.response = mainHandler(context)
} catch (error) {
// @ts-ignore
mainHandler.response = this.handleError(
context,
error as Error
)
}
}
}

const existingRouteIndex = this.routes.findIndex(
(route) => route.path === path && route.method === method
Expand Down Expand Up @@ -553,7 +571,7 @@ export default class Elysia<
this.staticRouter.handlers.push(mainHandler)

// @ts-ignore
if (handle.response instanceof Response)
if (mainHandler.response instanceof Response)
this.staticRouter.variables += `const st${index} = staticRouter.handlers[${index}].response\n`
else
this.staticRouter.variables += `const st${index} = staticRouter.handlers[${index}]\n`
Expand Down Expand Up @@ -589,7 +607,7 @@ export default class Elysia<
].all = `default: return st${index}(ctx)\n`
else {
// @ts-ignore
if (handle.response instanceof Response)
if (mainHandler.response instanceof Response)
this.staticRouter.map[
path
].code = `case '${method}': return st${index}.clone()\n${this.staticRouter.map[path].code}`
Expand Down Expand Up @@ -635,13 +653,13 @@ export default class Elysia<
}
}

private setHeader?: Context['set']['headers']
header(header: Context['set']['headers'] | undefined) {
private setHeaders?: Context['set']['headers']
headers(header: Context['set']['headers'] | undefined) {
if (!header) return this

if (!this.setHeader) this.setHeader = {}
if (!this.setHeaders) this.setHeaders = {}

this.setHeader = mergeDeep(this.setHeader, header)
this.setHeaders = mergeDeep(this.setHeaders, header)

return this
}
Expand Down Expand Up @@ -1824,7 +1842,7 @@ export default class Elysia<
const { name, seed } = plugin.config

plugin.getServer = () => this.getServer()
plugin.header(this.setHeader)
plugin.headers(this.setHeaders)

const isScoped = plugin.config.scoped
if (isScoped) {
Expand Down
File renamed without changes.
17 changes: 17 additions & 0 deletions test/lifecycle/error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
InternalServerError,
ParseError,
ValidationError,
error,
t
} from '../../src'
import { describe, expect, it } from 'bun:test'
Expand Down Expand Up @@ -95,4 +96,20 @@ describe('error', () => {
expect(await response.text()).toBe('UwU')
expect(response.status).toBe(500)
})

it('error function status', async () => {
const app = new Elysia().get('/', () => error(418, 'I am a teapot'))

const response = await app.handle(req('/'))

expect(response.status).toBe(418)
})

it('error function name', async () => {
const app = new Elysia().get('/', () => error("I'm a teapot", 'I am a teapot'))

const response = await app.handle(req('/'))

expect(response.status).toBe(418)
})
})
Loading

0 comments on commit e941e21

Please sign in to comment.