Skip to content

Commit 63e305b

Browse files
committed
🔧 fix: custom t.Transform, unwrap macro with hook function
1 parent e6ca813 commit 63e305b

File tree

9 files changed

+166
-92
lines changed

9 files changed

+166
-92
lines changed

CHANGELOG.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Improvement:
3232
- refactor `parseQuery` and `parseQueryFromURL`
3333
- add `config` options to `mount`
3434
- recompile automatically after async modules is mounted
35+
- support macro on when hook has function
36+
- support resolve macro on ws
3537

3638
Bug fix:
3739
- `Response` returned from `onError` is using octet stream
@@ -47,9 +49,8 @@ Change:
4749
- `Elysia.mount` now set `detail.hide = true` by default
4850

4951
Breaking Change:
50-
- Minimum Node version is now `node22` LTS
5152
- remove `as('plugin')` in favor of `as('scoped')`
52-
- remove root `index`
53+
- remove root `index` for Eden Treaty
5354
- remove `websocket` from `ElysiaAdapter`
5455
- remove `inference.request`
5556

example/a.ts

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import Elysia, { t } from '../src'
2-
3-
function addTwo(num: number) {
4-
return num + 2
5-
}
1+
import { Elysia, t } from '../src'
62

73
const app = new Elysia()
8-
.get('', async ({ query: { foo } }) => addTwo(foo), {
9-
query: t.Object({
10-
foo: t
11-
.Transform(t.String())
12-
.Decode((x) => 12)
13-
.Encode((x) => x.toString())
14-
})
4+
.macro({
5+
a: {
6+
resolve: () => ({
7+
a: 'a'
8+
})
9+
}
10+
})
11+
.get('/a', ({ a }) => {}, {
12+
a: true,
13+
beforeHandle: ({ query }) => {}
14+
})
15+
.ws('/', {
16+
a: true,
17+
message({ data: { a } }) {}
1518
})
16-
.listen(1234)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "elysia",
33
"description": "Ergonomic Framework for Human",
4-
"version": "1.3.0-exp.76",
4+
"version": "1.3.0-exp.77",
55
"author": {
66
"name": "saltyAom",
77
"url": "https://github.com/SaltyAom",

src/index.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -3837,7 +3837,7 @@ export default class Elysia<
38373837
}
38383838

38393839
if (options?.scoped)
3840-
return this.guard({}, (app) => app.use(plugin as any))
3840+
return this.guard({} as any, (app) => app.use(plugin as any))
38413841

38423842
if (Array.isArray(plugin)) {
38433843
// eslint-disable-next-line @typescript-eslint/no-this-alias
@@ -5415,16 +5415,20 @@ export default class Elysia<
54155415
Volatile['schema'],
54165416
MergeSchema<Ephemeral['schema'], Metadata['schema']>
54175417
>
5418-
>
5418+
>,
5419+
const Macro extends Metadata['macro']
54195420
>(
54205421
path: Path,
54215422
options: WSLocalHook<
54225423
LocalSchema,
54235424
Schema,
54245425
Singleton & {
54255426
derive: Ephemeral['derive'] & Volatile['derive']
5426-
resolve: Ephemeral['resolve'] & Volatile['resolve']
5427-
}
5427+
resolve: Ephemeral['resolve'] &
5428+
Volatile['resolve'] &
5429+
MacroToContext<Metadata['macroFn'], Macro>
5430+
},
5431+
Macro
54285432
>
54295433
): Elysia<
54305434
BasePath,

src/type-system/index.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,23 @@ import {
3838
FilesOptions,
3939
NonEmptyArray,
4040
TForm,
41-
TUnionEnum
41+
TUnionEnum,
42+
ElysiaTransformDecodeBuilder
4243
} from './types'
4344

4445
import { ELYSIA_FORM_DATA, form } from '../utils'
4546
import { ValidationError } from '../error'
4647
import { parseDateTimeEmptySpace } from './format'
4748

48-
const t = Object.assign({}, Type) as Omit<JavaScriptTypeBuilder, 'String'> &
49-
typeof ElysiaType
49+
const t = Object.assign({}, Type) as unknown as Omit<
50+
JavaScriptTypeBuilder,
51+
'String' | 'Transform'
52+
> &
53+
typeof ElysiaType & {
54+
Transform<Type extends TSchema>(
55+
type: Type
56+
): ElysiaTransformDecodeBuilder<Type>
57+
}
5058

5159
createType<TUnionEnum>(
5260
'UnionEnum',

src/type-system/types.ts

+39
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import type {
33
NumberOptions,
44
ObjectOptions,
55
SchemaOptions,
6+
StaticDecode,
67
TObject,
78
TProperties,
9+
TransformKind,
810
TSchema,
911
TUnsafe
1012
} from '@sinclair/typebox'
@@ -148,3 +150,40 @@ declare module '@sinclair/typebox' {
148150
}) => string | boolean | number | Object | void)
149151
}
150152
}
153+
154+
export declare class ElysiaTransformDecodeBuilder<T extends TSchema> {
155+
private readonly schema
156+
constructor(schema: T)
157+
Decode<U extends unknown, D extends TransformFunction<StaticDecode<T>, U>>(
158+
decode: D
159+
): ElysiaTransformEncodeBuilder<T, D>
160+
}
161+
export declare class ElysiaTransformEncodeBuilder<
162+
T extends TSchema,
163+
D extends TransformFunction
164+
> {
165+
private readonly schema
166+
private readonly decode
167+
constructor(schema: T, decode: D)
168+
private EncodeTransform
169+
private EncodeSchema
170+
Encode<E extends TransformFunction<ReturnType<D>, StaticDecode<T>>>(
171+
encode: E
172+
): TTransform<T, ReturnType<D>>
173+
}
174+
export type TransformFunction<T = any, U = any> = (value: T) => U
175+
export interface TransformOptions<
176+
I extends TSchema = TSchema,
177+
O extends unknown = unknown
178+
> {
179+
Decode: TransformFunction<StaticDecode<I>, O>
180+
Encode: TransformFunction<O, StaticDecode<I>>
181+
}
182+
export interface TTransform<
183+
I extends TSchema = TSchema,
184+
O extends unknown = unknown
185+
> extends TSchema {
186+
static: O
187+
[TransformKind]: TransformOptions<I, O>
188+
[key: string]: any
189+
}

src/types.ts

+24-34
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import type { Serve } from './universal/server'
55

66
import {
77
TSchema,
8-
TObject,
98
TAnySchema,
10-
StaticDecode,
119
OptionalKind,
1210
TModule,
1311
TImport,
@@ -404,35 +402,31 @@ export type UnwrapSchema<
404402
: Schema extends TSchema
405403
? Schema extends OptionalField
406404
? Partial<
407-
StaticDecode<
408-
TImport<
409-
Definitions & {
410-
readonly __elysia: Schema
411-
},
412-
'__elysia'
413-
>
414-
>
415-
>
416-
: StaticDecode<
417405
TImport<
418406
Definitions & {
419407
readonly __elysia: Schema
420408
},
421409
'__elysia'
422-
>
410+
>['static']
423411
>
412+
: TImport<
413+
Definitions & {
414+
readonly __elysia: Schema
415+
},
416+
'__elysia'
417+
>['static']
424418
: Schema extends `${infer Key}[]`
425419
? Definitions extends Record<
426420
Key,
427421
infer NamedSchema extends TAnySchema
428422
>
429-
? StaticDecode<NamedSchema>[]
430-
: StaticDecode<TImport<Definitions, TrimArrayName<Schema>>>[]
423+
? NamedSchema['static'][]
424+
: TImport<Definitions, TrimArrayName<Schema>>['static'][]
431425
: Schema extends string
432426
? Definitions extends keyof Schema
433427
? // @ts-ignore Definitions is always a Record<string, TAnySchema>
434-
StaticDecode<NamedSchema>
435-
: StaticDecode<TImport<Definitions, Schema>>
428+
NamedSchema['static']
429+
: TImport<Definitions, Schema>['static']
436430
: unknown
437431

438432
export type UnwrapBodySchema<
@@ -443,35 +437,31 @@ export type UnwrapBodySchema<
443437
: Schema extends TSchema
444438
? Schema extends OptionalField
445439
? Partial<
446-
StaticDecode<
447-
TImport<
448-
Definitions & {
449-
readonly __elysia: Schema
450-
},
451-
'__elysia'
452-
>
453-
>
454-
> | null
455-
: StaticDecode<
456440
TImport<
457441
Definitions & {
458442
readonly __elysia: Schema
459443
},
460444
'__elysia'
461-
>
462-
>
445+
>['static']
446+
> | null
447+
: TImport<
448+
Definitions & {
449+
readonly __elysia: Schema
450+
},
451+
'__elysia'
452+
>['static']
463453
: Schema extends `${infer Key}[]`
464454
? Definitions extends Record<
465455
Key,
466456
infer NamedSchema extends TAnySchema
467457
>
468-
? StaticDecode<NamedSchema>[]
469-
: StaticDecode<TImport<Definitions, TrimArrayName<Schema>>>[]
458+
? NamedSchema['static'][]
459+
: TImport<Definitions, TrimArrayName<Schema>>['static'][]
470460
: Schema extends string
471461
? Definitions extends keyof Schema
472462
? // @ts-ignore Definitions is always a Record<string, TAnySchema>
473-
StaticDecode<NamedSchema>
474-
: StaticDecode<TImport<Definitions, Schema>>
463+
NamedSchema['static']
464+
: TImport<Definitions, Schema>['static']
475465
: unknown
476466

477467
export interface UnwrapRoute<
@@ -1269,7 +1259,7 @@ export type LocalHook<
12691259
Errors extends { [key in string]: Error },
12701260
Macro extends BaseMacro,
12711261
Parser extends keyof any = ''
1272-
> = Macro &
1262+
> = Prettify<Macro> &
12731263
// Kind of an inference hack, I have no idea why it work either
12741264
(LocalSchema extends any ? LocalSchema : Prettify<LocalSchema>) & {
12751265
detail?: DocumentDecoration

src/ws/types.ts

+37-35
Original file line numberDiff line numberDiff line change
@@ -118,46 +118,48 @@ export type WSParseHandler<Route extends RouteSchema, Context = {}> = (
118118
message: unknown
119119
) => MaybePromise<Route['body'] | void | undefined>
120120

121-
export type AnyWSLocalHook = WSLocalHook<any, any, any>
121+
export type AnyWSLocalHook = WSLocalHook<any, any, any, any>
122122

123123
export type WSLocalHook<
124124
LocalSchema extends InputSchema,
125125
Schema extends RouteSchema,
126-
Singleton extends SingletonBase
127-
> = (LocalSchema extends any ? LocalSchema : Prettify<LocalSchema>) & {
128-
detail?: DocumentDecoration
129-
/**
130-
* Headers to register to websocket before `upgrade`
131-
*/
132-
upgrade?: Record<string, unknown> | ((context: Context) => unknown)
133-
parse?: MaybeArray<WSParseHandler<Schema>>
126+
Singleton extends SingletonBase,
127+
Macro extends MetadataBase['macro']
128+
> = Prettify<Macro> &
129+
(LocalSchema extends any ? LocalSchema : Prettify<LocalSchema>) & {
130+
detail?: DocumentDecoration
131+
/**
132+
* Headers to register to websocket before `upgrade`
133+
*/
134+
upgrade?: Record<string, unknown> | ((context: Context) => unknown)
135+
parse?: MaybeArray<WSParseHandler<Schema>>
134136

135-
/**
136-
* Transform context's value
137-
*/
138-
transform?: MaybeArray<TransformHandler<Schema, Singleton>>
139-
/**
140-
* Execute before main handler
141-
*/
142-
beforeHandle?: MaybeArray<OptionalHandler<Schema, Singleton>>
143-
/**
144-
* Execute after main handler
145-
*/
146-
afterHandle?: MaybeArray<OptionalHandler<Schema, Singleton>>
147-
/**
148-
* Execute after main handler
149-
*/
150-
mapResponse?: MaybeArray<MapResponse<Schema, Singleton>>
151-
/**
152-
* Execute after response is sent
153-
*/
154-
afterResponse?: MaybeArray<AfterResponseHandler<Schema, Singleton>>
155-
/**
156-
* Catch error
157-
*/
158-
error?: MaybeArray<ErrorHandler<{}, Schema, Singleton>>
159-
tags?: DocumentDecoration['tags']
160-
} & TypedWebSocketHandler<
137+
/**
138+
* Transform context's value
139+
*/
140+
transform?: MaybeArray<TransformHandler<Schema, Singleton>>
141+
/**
142+
* Execute before main handler
143+
*/
144+
beforeHandle?: MaybeArray<OptionalHandler<Schema, Singleton>>
145+
/**
146+
* Execute after main handler
147+
*/
148+
afterHandle?: MaybeArray<OptionalHandler<Schema, Singleton>>
149+
/**
150+
* Execute after main handler
151+
*/
152+
mapResponse?: MaybeArray<MapResponse<Schema, Singleton>>
153+
/**
154+
* Execute after response is sent
155+
*/
156+
afterResponse?: MaybeArray<AfterResponseHandler<Schema, Singleton>>
157+
/**
158+
* Catch error
159+
*/
160+
error?: MaybeArray<ErrorHandler<{}, Schema, Singleton>>
161+
tags?: DocumentDecoration['tags']
162+
} & TypedWebSocketHandler<
161163
Omit<Context<Schema, Singleton>, 'body'> & {
162164
body: never
163165
},

0 commit comments

Comments
 (0)