Skip to content

Commit

Permalink
🎉 release: 1.0.14
Browse files Browse the repository at this point in the history
  • Loading branch information
SaltyAom committed Apr 22, 2024
1 parent 925f5c5 commit cc16953
Show file tree
Hide file tree
Showing 8 changed files with 581 additions and 466 deletions.
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# 1.0.14 - 22 Apr 2024
Improvement:
- [#596](https://github.com/elysiajs/elysia/pull/596) account for 20x response status schemas for type safety

Bug fix:
- [#615](https://github.com/elysiajs/elysia/issues/615)
- [588](https://github.com/elysiajs/elysia/issues/588) separate async derive/resolve function doesn't get await
- primitive thrown result in invalid type

# 1.0.12 - 5 Apr 2024
Improvement:
- export `InferContext` and `InferHandler`
Expand Down Expand Up @@ -151,7 +160,7 @@ Bug fix:
Feature:
- [#474](https://github.com/elysiajs/elysia/pull/474) Numeric Cookie with length >= 16 cant be parsed to number
- [#476](https://github.com/elysiajs/elysia/pull/476) Using a query key that contains a hyphen or a dot raises a SyntaxError
- [#460](https://github.com/elysiajs/elysia/pull/460)
- [#460](https://github.com/elysiajs/elysia/pull/460)
- [#458](https://github.com/elysiajs/elysia/pull/458) Multiple scoped plugins do not register routes
- [#457](https://github.com/elysiajs/elysia/pull/457) Elysia arguments scoped and prefix do not work at the same time

Expand All @@ -164,7 +173,7 @@ Feature:

Bug fix:
- [#451](https://github.com/elysiajs/elysia/pull/464) handle spread operator use on possible null or undefined
- [#460](https://github.com/elysiajs/elysia/pull/460)
- [#460](https://github.com/elysiajs/elysia/pull/460)
- [#457](https://github.com/elysiajs/elysia/pull/457) scoped plugin instances now respect the prefix property
- [#458](https://github.com/elysiajs/elysia/pull/458) adding a second scoped plugin does not unmount the route handler of a previously added scoped instance anymore.

Expand Down Expand Up @@ -313,7 +322,7 @@ Bug fix:
- [#309](https://github.com/elysiajs/elysia/issues/309) t.RegExp doesn't work due to requiring default value
- [#308](https://github.com/elysiajs/elysia/issues/308) t.Numeric should not convert empty string to 0
- [#305](https://github.com/elysiajs/elysia/issues/305) Elysia({ scoped: true }) should still expose defined routes on type level
- [#304](https://github.com/elysiajs/elysia/issues/304) Using a hook/guard/schema with a handler function and request without body results in a "Unexpected end of JSON input"-error
- [#304](https://github.com/elysiajs/elysia/issues/304) Using a hook/guard/schema with a handler function and request without body results in a "Unexpected end of JSON input"-error
- [#299](https://github.com/elysiajs/elysia/issues/299) Missing request.path parameter in .onRequest
- [#289](https://github.com/elysiajs/elysia/issues/289) Ability to localize TypeBox errors
- [#272](https://github.com/elysiajs/elysia/issues/272) onError handler has error property as undefined on Cloudflare Workers
Expand Down
39 changes: 13 additions & 26 deletions example/a.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
import { Elysia, t } from '../src'
import { InferContext, InferHandler } from '../src/types'
import { req } from '../test/utils'
import { Elysia } from '../src'
import { req } from '../test/utils';

const setup = new Elysia({ name: 'setup' })
.decorate('a', 'a')
.derive(() => {
return {
hello: 'world'
}
})

const app = new Elysia({ precompile: true }).get(
'/',
({ cookie: { profile } }) => {
profile.value = 'a'
},
{
cookie: t.Cookie({
profile: t.String()
}, {
secrets: 'awd'
})
}
)
export const app = new Elysia()
.derive({ as: "scoped" }, async () => {
return { myProp: 42 };
})
.macro(({ onBeforeHandle }) => ({
public: (_?: boolean) => {
onBeforeHandle(ctx => {
ctx.myProp; // myProp is number | undefined, but it is always undefined in runtime
});
},
}));

app.handle(req('/'))
.then((x) => x.text())
.then((x) => console.log({ x }))
10 changes: 10 additions & 0 deletions example/spawn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { $ } from 'bun'
import { cpus } from 'os'

const total = cpus().length - 1
const ops = []

for (let i = 0; i < total; i++)
ops.push($`NODE_ENV=production bun example/a.ts`)

await Promise.all(ops)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "elysia",
"description": "Ergonomic Framework for Human",
"version": "1.0.13",
"version": "1.0.14",
"author": {
"name": "saltyAom",
"url": "https://github.com/SaltyAom",
Expand Down
49 changes: 27 additions & 22 deletions src/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const composeValidationFactory = (
let code = '\n' + injectResponse + '\n'

code += `let er
if(${name} && typeof ${name} === "object" && ELYSIA_RESPONSE in ${name})
er = ${name}[ELYSIA_RESPONSE]\n`

Expand Down Expand Up @@ -327,6 +327,8 @@ export const isAsync = (v: Function | HookContainer) => {

const literal = fn.toString()
if (literal.includes('=> response.clone(')) return false
if (literal.includes('await')) return true
if (literal.includes('async')) return true

return !!literal.match(matchFnReturn)
}
Expand Down Expand Up @@ -425,7 +427,7 @@ export const composeHandler = ({
config: validator.cookie?.config ?? {},
// @ts-expect-error
models: app.definitions.type
})
})
: undefined

// @ts-ignore private property
Expand All @@ -446,8 +448,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 @@ -505,21 +507,24 @@ export const composeHandler = ({
? typeof cookieMeta.secrets === 'string'
? `'${cookieMeta.secrets}'`
: '[' +
cookieMeta.secrets.reduce(
cookieMeta.secrets.reduce(
(a, b) => a + `'${b}',`,
''
) +
']'
) +
']'
: 'undefined'
},
sign: ${
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 @@ -646,7 +651,7 @@ export const composeHandler = ({
case 'application/json':
if (hasErrorHandler)
fnLiteral += `const tempBody = await c.request.text()
try {
c.body = JSON.parse(tempBody)
} catch {
Expand Down Expand Up @@ -764,7 +769,7 @@ export const composeHandler = ({
hasErrorHandler
? `
const tempBody = await c.request.text()
try {
c.body = JSON.parse(tempBody)
} catch {
Expand Down Expand Up @@ -1195,7 +1200,7 @@ export const composeHandler = ({
if (hooks.mapResponse.length) {
fnLiteral += 'c.response = r'
for (let i = 0; i < hooks.mapResponse.length; i++) {
fnLiteral += `\nif(mr === undefined) {
fnLiteral += `\nif(mr === undefined) {
mr = onMapResponse[${i}](c)
if(mr instanceof Promise) mr = await mr
if(mr !== undefined) r = c.response = mr
Expand Down Expand Up @@ -1466,11 +1471,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\n`
Expand Down Expand Up @@ -1506,7 +1511,7 @@ export const composeGeneralHandler = (
let path
if(qi === -1)
path = url.substring(s)
else
else
path = url.substring(s, qi)\n`

fnLiteral += `const {
Expand Down Expand Up @@ -1739,7 +1744,7 @@ export const composeErrorHandler = (
context.code = error.code
context.error = error
if(ELYSIA_RESPONSE in error) {
if(typeof error === "object" && ELYSIA_RESPONSE in error) {
error.status = error[ELYSIA_RESPONSE]
error.message = error.response
}\n`
Expand All @@ -1761,7 +1766,7 @@ export const composeErrorHandler = (
error.status = error[ELYSIA_RESPONSE]
error.message = error.response
}
if(set.status === 200) set.status = error.status
return mapResponse(r, set, context.request)
}\n`
Expand All @@ -1774,11 +1779,11 @@ export const composeErrorHandler = (
set.status = error.status ?? 422
return new Response(
error.message,
{
{
headers: Object.assign(
{ 'content-type': 'application/json'},
{ 'content-type': 'application/json'},
set.headers
),
),
status: set.status
}
)
Expand Down
76 changes: 65 additions & 11 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,64 @@ type WithoutNullableKeys<Type> = {
[Key in keyof Type]-?: NonNullable<Type[Key]>
}

type SetCookie = {
'Set-Cookie'?: string | string[]
}

export type ErrorContext<
in out Route extends RouteSchema = {},
in out Singleton extends SingletonBase = {
decorator: {}
store: {}
derive: {}
resolve: {}
},
Path extends string = ''
> = Prettify<
{
body: Route['body']
query: undefined extends Route['query']
? Record<string, string | undefined>
: Route['query']
params: undefined extends Route['params']
? Path extends `${string}/${':' | '*'}${string}`
? Record<GetPathParameter<Path>, string>
: never
: Route['params']
headers: undefined extends Route['headers']
? Record<string, string | undefined>
: Route['headers']
cookie: undefined extends Route['cookie']
? Record<string, Cookie<any>>
: Record<string, Cookie<any>> &
Prettify<
WithoutNullableKeys<{
[key in keyof Route['cookie']]: Cookie<
Route['cookie'][key]
>
}>
>

set: {
headers: Record<string, string> & SetCookie
status?: number | keyof StatusMap
redirect?: string
/**
* ! Internal Property
*
* Use `Context.cookie` instead
*/
cookie?: Record<string, ElysiaCookie>
}

path: string
request: Request
store: Singleton['store']
} & Singleton['decorator'] &
Singleton['derive'] &
Singleton['resolve']
>

export type Context<
in out Route extends RouteSchema = {},
in out Singleton extends SingletonBase = {
Expand Down Expand Up @@ -50,9 +108,7 @@ export type Context<
>

set: {
headers: Record<string, string> & {
'Set-Cookie'?: string | string[]
}
headers: Record<string, string> & SetCookie
status?: number | keyof StatusMap
redirect?: string
/**
Expand All @@ -78,9 +134,9 @@ export type Context<
const T extends Code extends keyof Route['response']
? Route['response'][Code]
: Code extends keyof StatusMap
? // @ts-ignore StatusMap[Code] always valid because Code generic check
Route['response'][StatusMap[Code]]
: never
? // @ts-ignore StatusMap[Code] always valid because Code generic check
Route['response'][StatusMap[Code]]
: never
>(
code: Code,
response: T
Expand All @@ -95,10 +151,10 @@ export type Context<
: Code]: T
}
}
}
}
: {
error: typeof error
}) &
}) &
Singleton['decorator'] &
Singleton['derive'] &
Singleton['resolve']
Expand All @@ -118,9 +174,7 @@ export type PreContext<
request: Request

set: {
headers: { [header: string]: string } & {
['Set-Cookie']?: string | string[]
}
headers: { [header: string]: string } & SetCookie
status?: number
redirect?: string
}
Expand Down

0 comments on commit cc16953

Please sign in to comment.