elysia 0.2.8 → 0.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context.d.ts +5 -2
- package/dist/custom-types.d.ts +26 -0
- package/dist/custom-types.js +1 -0
- package/dist/fn.d.ts +32 -0
- package/dist/fn.js +1 -0
- package/dist/handler.d.ts +1 -0
- package/dist/handler.js +1 -1
- package/dist/index.d.ts +47 -36
- package/dist/index.js +1 -1
- package/dist/schema.d.ts +8 -6
- package/dist/schema.js +1 -1
- package/dist/types.d.ts +69 -48
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +1 -1
- package/package.json +20 -8
- package/src/context.ts +31 -0
- package/src/custom-types.ts +148 -0
- package/src/error.ts +14 -0
- package/src/fn.ts +221 -0
- package/src/handler.ts +333 -0
- package/src/index.ts +1617 -0
- package/src/schema.ts +206 -0
- package/src/types.ts +606 -0
- package/src/utils.ts +173 -0
- package/.husky/pre-commit +0 -4
- package/CODE_OF_CONDUCT.md +0 -80
- package/CONTRIBUTING.md +0 -49
package/dist/context.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/// <reference types="bun-types" />
|
|
2
|
-
import { Elysia } from '.';
|
|
3
|
-
import type { TypedRoute } from './types';
|
|
2
|
+
import type { Elysia, TypedRoute, DEFS, SCHEMA, TypedSchema } from '.';
|
|
4
3
|
export interface Context<Route extends TypedRoute = TypedRoute, Store extends Elysia['store'] = Elysia['store']> {
|
|
5
4
|
request: Request;
|
|
6
5
|
query: Route['query'] extends undefined ? Record<string, unknown> : Route['query'];
|
|
7
6
|
params: Route['params'];
|
|
8
7
|
body: Route['body'];
|
|
9
8
|
store: Store;
|
|
9
|
+
[SCHEMA]: TypedSchema;
|
|
10
|
+
[DEFS]: {
|
|
11
|
+
[index: string]: Record<string, unknown>;
|
|
12
|
+
};
|
|
10
13
|
set: {
|
|
11
14
|
headers: Record<string, string>;
|
|
12
15
|
status?: number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
import { Type, type SchemaOptions } from '@sinclair/typebox';
|
|
3
|
+
type MaybeArray<T> = T | T[];
|
|
4
|
+
export declare namespace ElysiaTypeOptions {
|
|
5
|
+
type FileUnit = number | `${number}${'k' | 'm'}`;
|
|
6
|
+
interface File extends SchemaOptions {
|
|
7
|
+
type?: MaybeArray<(string & {}) | 'image' | 'image/jpeg' | 'image/png' | 'image/gif' | 'image/tiff' | 'image/x-icon' | 'image/svg' | 'image/webp' | 'image/avif' | 'audio' | 'audio/mpeg' | 'audio/x-ms-wma' | 'audio/vnd.rn-realaudio' | 'audio/x-wav' | 'video' | 'video/mpeg' | 'video/mp4' | 'video/quicktime' | 'video/x-ms-wmv' | 'video/x-msvideo' | 'video/x-flv' | 'video/webm' | 'text' | 'text/css' | 'text/csv' | 'text/html' | 'text/javascript' | 'text/plain' | 'text/xml' | 'application' | 'application/ogg' | 'application/pdf' | 'application/xhtml' | 'application/html' | 'application/json' | 'application/ld+json' | 'application/xml' | 'application/zip'>;
|
|
8
|
+
minSize?: FileUnit;
|
|
9
|
+
maxSize?: FileUnit;
|
|
10
|
+
}
|
|
11
|
+
interface Files extends File {
|
|
12
|
+
minItems?: number;
|
|
13
|
+
maxItems?: number;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export declare const ElysiaType: {
|
|
17
|
+
readonly File: (options?: Partial<ElysiaTypeOptions.File> | undefined) => import("@sinclair/typebox").TUnsafe<Blob>;
|
|
18
|
+
readonly Files: (options?: Partial<ElysiaTypeOptions.Files> | undefined) => import("@sinclair/typebox").TUnsafe<Blob[]>;
|
|
19
|
+
};
|
|
20
|
+
declare module '@sinclair/typebox' {
|
|
21
|
+
interface TypeBuilder {
|
|
22
|
+
File: typeof ElysiaType.File;
|
|
23
|
+
Files: typeof ElysiaType.Files;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export { Type as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Type as e}from"@sinclair/typebox";import{TypeSystem as t}from"@sinclair/typebox/system";let i=e=>{if("string"==typeof e)switch(e.slice(-1)){case"k":return 1024*+e.slice(0,e.length-1);case"m":return 1048576*+e.slice(0,e.length-1);default:return+e}return e},r=(e,t)=>{if(!(t instanceof Blob)||e.minSize&&t.size<i(e.minSize)||e.maxSize&&t.size>i(e.maxSize))return!1;if(e.extension){if("string"==typeof e.extension){if(!t.type.startsWith(e.extension))return!1}else{for(let i=0;i<e.extension.length;i++)if(t.type.startsWith(e.extension[i]))return!0;return!1}}return!0};export const ElysiaType={File:t.CreateType("File",r),Files:t.CreateType("Files",(e,t)=>{if(!Array.isArray(t)||e.minItems&&t.length<e.minItems||e.maxItems&&t.length>e.maxItems)return!1;for(let i=0;i<t.length;i++)if(!r(e,t[i]))return!1;return!0})};e.File=e=>ElysiaType.File({default:"File",...e,extension:e?.type,type:"string",format:"binary"}),e.Files=e=>ElysiaType.Files({default:"Files",...e,extension:e?.type,type:"string",format:"binary"});export{e as t};
|
package/dist/fn.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
import { EXPOSED } from './utils';
|
|
3
|
+
import type { Context } from './context';
|
|
4
|
+
import type { ConnectedKeysType, ElysiaInstance, FunctionProperties, JoinKeys } from './types';
|
|
5
|
+
export declare const permission: <T, Key extends JoinKeys<FunctionProperties<T>, ""> = JoinKeys<FunctionProperties<T>, "">>({ value, allow, deny, check }: {
|
|
6
|
+
value: T;
|
|
7
|
+
allow?: Key[] | undefined;
|
|
8
|
+
deny?: Key[] | undefined;
|
|
9
|
+
check?: boolean | ((context: {
|
|
10
|
+
request: Request;
|
|
11
|
+
key: Key;
|
|
12
|
+
params: T extends (...args: infer Args) => any ? Args : Key extends string ? ConnectedKeysType<T, Key> : unknown;
|
|
13
|
+
match: <Case extends Key>(a: Case extends string ? Partial<{ [x in Case]: (params: ConnectedKeysType<T, Case>) => any; } | {
|
|
14
|
+
default?: ((params: T extends (...args: infer Args_1) => any ? Args_1 : Key extends string ? ConnectedKeysType<T, Key> : unknown) => any) | undefined;
|
|
15
|
+
}> : {}) => void;
|
|
16
|
+
}) => unknown) | undefined;
|
|
17
|
+
}) => {
|
|
18
|
+
[EXPOSED]: boolean;
|
|
19
|
+
value: T;
|
|
20
|
+
check: boolean | ((context: {
|
|
21
|
+
request: Request;
|
|
22
|
+
key: Key;
|
|
23
|
+
params: T extends (...args: infer Args) => any ? Args : Key extends string ? ConnectedKeysType<T, Key> : unknown;
|
|
24
|
+
match: <Case extends Key>(a: Case extends string ? Partial<{ [x in Case]: (params: ConnectedKeysType<T, Case>) => any; } | {
|
|
25
|
+
default?: ((params: T extends (...args: infer Args_1) => any ? Args_1 : Key extends string ? ConnectedKeysType<T, Key> : unknown) => any) | undefined;
|
|
26
|
+
}> : {}) => void;
|
|
27
|
+
}) => unknown);
|
|
28
|
+
allow: Key[] | undefined;
|
|
29
|
+
deny: Key[] | undefined;
|
|
30
|
+
};
|
|
31
|
+
export type Permission = typeof permission;
|
|
32
|
+
export declare const runFn: (context: Context, exposed: ElysiaInstance['meta'][typeof EXPOSED]) => Promise<Record<string, any>>;
|
package/dist/fn.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{EXPOSED as e}from"./utils";import{serialize as n}from"superjson";export const permission=({value:n,allow:r,deny:i,check:t=!0})=>({[e]:!0,value:n,check:t,allow:r,deny:i});export const runFn=(r,i)=>{let t=[],o=r.body;e:for(let n=0;n<o.length;n++){let c=o[n],l=i,u=c.n;if(!Array.isArray(c.n)){t.push(Error("Invalid procedure"));continue e}let s=u[u.length-1];if(1===u.length){if(s in l&&e in l[s]){if(!1==l[s].check){t.push(Error("Forbidden"));continue e}if(!0!==l[s].check){try{let e=l[s].check({...r,key:s,params:c.p??null,match(e){}});if(e instanceof Error){t.push(e);continue e}}catch(e){t.push(e);continue e}l=l[s],s="value"}}}else for(let n=0;n<u.length-1;n++){if(!(l=l[u[n]])){t.push(Error("Invalid procedure"));continue e}if(e in l){let e=u.slice(n+1).join("."),i="function"==typeof l.check;if(!0===l.allow?.includes(e)&&!i){l=l.value;continue}if(!1!=l.check&&!0!==l.deny?.includes(e)&&(!1!==l.allow?.includes(e)||l.deny||i)){if(!0!==l.check)try{let n;let i=l.check({...r,key:e,params:c.p??null,match(e){n=e}});if(n)try{let r=(n[e]??n.default)?.(c.p??null);if(r instanceof Error)throw r}catch(r){if(!(e in n)&&l.allow?.includes(e)){l=l.value;continue}t.push(r);continue e}if(i instanceof Error){t.push(i);continue e}}catch(e){t.push(e);continue e}}else{t.push(Error("Forbidden"));continue e}l=l.value}}"function"!=typeof l[s]?t.push(Error("Invalid procedure")):void 0===c.p?t.push(l[s]()):1===c.p.length?t.push(l[s](c.p[0])):t.push(l[s](...c.p))}return Promise.all(t).then(n)};
|
package/dist/handler.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="bun-types" />
|
|
2
2
|
import type { Context } from './context';
|
|
3
|
+
export declare const isNotEmpty: (obj: Object) => boolean;
|
|
3
4
|
export declare const mapEarlyResponse: (response: unknown, set: Context['set']) => Response | undefined;
|
|
4
5
|
export declare const mapResponse: (response: unknown, set: Context['set']) => Response;
|
|
5
6
|
export declare const errorToResponse: (error: Error, headers?: HeadersInit) => Response;
|
package/dist/handler.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export const isNotEmpty=e=>{for(let s in e)return!0;return!1};let e=(e,s)=>{if(Array.isArray(s)){e.delete("Set-Cookie");for(let r=0;r<s.length;r++){let t=s[r].indexOf("=");e.append("Set-Cookie",`${s[r].slice(0,t)}=${s[r].slice(t+1)}`)}}return e};export const mapEarlyResponse=(s,r)=>{if(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers["Set-Cookie"]&&(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"])),isNotEmpty(r.headers)||200!==r.status)switch(typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Response){for(let e in r.headers)s.headers.append(e,r.headers[e]);return s}if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers});case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers})}else switch(typeof s){case"string":return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s;case"number":case"boolean":return new Response(s.toString())}};export const mapResponse=(s,r)=>{if(r.redirect&&(r.headers.Location=r.redirect,r.status=302),r.headers?.["Set-Cookie"])switch(r.headers=e(new Headers(r.headers),r.headers["Set-Cookie"]),typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":switch(s.constructor){case Error:return errorToResponse(s,r.headers);case Response:for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case Blob:return new Response(s,{status:r.status,headers:r.headers});default:return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers})}case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return s();case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers});case"undefined":return new Response("",{status:r.status,headers:r.headers});default:return new Response(s,{status:r.status,headers:r.headers})}if(r.redirect)return Response.redirect(r.redirect,{headers:r.headers});if(Object.keys(r.headers).length||200!==r.status)switch(typeof s){case"string":return new Response(s,{status:r.status,headers:r.headers});case"object":switch(s?.constructor){case Error:return errorToResponse(s,r.headers);case Response:for(let e in r.headers)s.headers.append(e,r.headers[e]);return s;case Blob:return new Response(s,{status:r.status,headers:r.headers});default:return r.headers["Content-Type"]||(r.headers["Content-Type"]="application/json"),new Response(JSON.stringify(s),{status:r.status,headers:r.headers})}case"function":if(s instanceof Blob)return new Response(s,{status:r.status,headers:r.headers});return s();case"number":case"boolean":return new Response(s.toString(),{status:r.status,headers:r.headers});case"undefined":return new Response("",{status:r.status,headers:r.headers});default:return new Response(s,{status:r.status,headers:r.headers})}else switch(typeof s){case"string":default:return new Response(s);case"object":if(s instanceof Response)return s;if(s instanceof Error)return errorToResponse(s,r.headers);if(s instanceof Blob)return new Response(s);return new Response(JSON.stringify(s),{headers:{"content-type":"application/json"}});case"function":if(s instanceof Blob)return new Response(s);return s();case"number":case"boolean":return new Response(s.toString());case"undefined":return new Response("")}};export const errorToResponse=(e,s)=>new Response(JSON.stringify({name:e?.name,message:e?.message,cause:e?.cause}),{status:500,headers:s});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/// <reference types="bun-types" />
|
|
2
2
|
import type { Serve, Server } from 'bun';
|
|
3
|
-
import {
|
|
3
|
+
import { permission, type Permission } from './fn';
|
|
4
|
+
import { SCHEMA, EXPOSED, DEFS } from './utils';
|
|
4
5
|
import type { Context } from './context';
|
|
5
|
-
import type { Handler, BeforeRequestHandler, TypedRoute, ElysiaInstance, ElysiaConfig, HTTPMethod, InternalRoute, BodyParser, ErrorHandler, TypedSchema, LocalHook, LocalHandler, LifeCycle, LifeCycleEvent, LifeCycleStore, VoidLifeCycle, AfterRequestHandler,
|
|
6
|
+
import type { Handler, BeforeRequestHandler, TypedRoute, ElysiaInstance, ElysiaConfig, HTTPMethod, InternalRoute, BodyParser, ErrorHandler, TypedSchema, LocalHook, LocalHandler, LifeCycle, LifeCycleEvent, LifeCycleStore, VoidLifeCycle, AfterRequestHandler, IsAny, OverwritableTypeRoute, MergeSchema, ListenCallback, NoReturnHandler, ElysiaRoute, MaybePromise, IsNever } from './types';
|
|
6
7
|
import { type TSchema } from '@sinclair/typebox';
|
|
7
8
|
export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
8
9
|
config: ElysiaConfig;
|
|
9
10
|
store: Instance['store'];
|
|
10
|
-
|
|
11
|
+
meta: Instance['meta'];
|
|
12
|
+
protected decorators: ElysiaInstance['request'];
|
|
11
13
|
event: LifeCycleStore<Instance>;
|
|
12
14
|
server: Server | null;
|
|
13
15
|
private $schema;
|
|
@@ -29,40 +31,44 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
|
29
31
|
request: Instance['request'];
|
|
30
32
|
store: Omit<Instance['store'], typeof SCHEMA> & ElysiaInstance['store'];
|
|
31
33
|
schema: Instance['schema'];
|
|
34
|
+
meta: Omit<Instance['meta'], typeof SCHEMA> & ElysiaInstance['meta'];
|
|
32
35
|
}>) => NewElysia): NewElysia extends Elysia<infer NewInstance> ? Elysia<{
|
|
33
36
|
request: Instance['request'] & NewInstance['request'];
|
|
34
37
|
schema: Instance['schema'] & NewInstance['schema'];
|
|
35
|
-
store: Instance['store'] &
|
|
38
|
+
store: Instance['store'] & NewInstance['store'];
|
|
39
|
+
meta: Instance['meta'] & (Omit<NewInstance['meta'], typeof SCHEMA> & {
|
|
36
40
|
[key in typeof SCHEMA]: {
|
|
37
|
-
[key in keyof NewInstance['
|
|
41
|
+
[key in keyof NewInstance['meta'][typeof SCHEMA] as key extends `${infer Rest}` ? `${Prefix}${Rest}` : key]: NewInstance['meta'][typeof SCHEMA][key];
|
|
38
42
|
};
|
|
39
43
|
});
|
|
40
44
|
}> : this;
|
|
41
|
-
guard<Schema extends TypedSchema = {}, NewElysia extends Elysia<any> = Elysia<any>>(hook: LocalHook<Schema, Instance>, run: (group: Elysia<{
|
|
45
|
+
guard<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, NewElysia extends Elysia<any> = Elysia<any>>(hook: LocalHook<Schema, Instance>, run: (group: Elysia<{
|
|
42
46
|
request: Instance['request'];
|
|
43
47
|
store: Instance['store'];
|
|
44
|
-
schema:
|
|
48
|
+
schema: Schema & Instance['schema'];
|
|
49
|
+
meta: Instance['meta'];
|
|
45
50
|
}>) => NewElysia): NewElysia extends Elysia<infer NewInstance> ? Elysia<NewInstance & Instance> : this;
|
|
46
51
|
use<NewElysia extends MaybePromise<Elysia<any>> = Elysia<any>, Params extends Elysia = Elysia<any>, LazyLoadElysia extends never | ElysiaInstance = never>(plugin: MaybePromise<(app: Params extends Elysia<infer ParamsInstance> ? IsAny<ParamsInstance> extends true ? this : Params : Params) => MaybePromise<NewElysia>> | Promise<{
|
|
47
52
|
default: (elysia: Elysia<any>) => MaybePromise<Elysia<LazyLoadElysia>>;
|
|
48
53
|
}>): IsNever<LazyLoadElysia> extends false ? Elysia<LazyLoadElysia & Instance> : NewElysia extends Elysia<infer NewInstance> ? IsNever<NewInstance> extends true ? Elysia<Instance> : Elysia<NewInstance & Instance> : NewElysia extends Promise<Elysia<infer NewInstance>> ? Elysia<NewInstance & Instance> : this;
|
|
49
|
-
get<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
50
|
-
post<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
51
|
-
put<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
52
|
-
patch<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
53
|
-
delete<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
54
|
-
options<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
55
|
-
all<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
56
|
-
head<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
57
|
-
trace<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
58
|
-
connect<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
59
|
-
route<Schema extends TypedSchema<Exclude<keyof Instance['
|
|
60
|
-
state<Key extends string | number | symbol = keyof Instance['store'], Value = Instance['store'][keyof Instance['store']],
|
|
54
|
+
get<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'GET', Schema, Instance, Path, Response>;
|
|
55
|
+
post<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'POST', Schema, Instance, Path, Response>;
|
|
56
|
+
put<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'PUT', Schema, Instance, Path, Response>;
|
|
57
|
+
patch<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'PATCH', Schema, Instance, Path, Response>;
|
|
58
|
+
delete<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'DELETE', Schema, Instance, Path, Response>;
|
|
59
|
+
options<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'OPTIONS', Schema, Instance, Path, Response>;
|
|
60
|
+
all<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'ALL', Schema, Instance, Path, Response>;
|
|
61
|
+
head<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'HEAD', Schema, Instance, Path, Response>;
|
|
62
|
+
trace<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'TRACE', Schema, Instance, Path, Response>;
|
|
63
|
+
connect<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Path extends string = string, Response = unknown>(path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<'CONNECT', Schema, Instance, Path, Response>;
|
|
64
|
+
route<Schema extends TypedSchema<Exclude<keyof Instance['meta'][typeof DEFS], number | symbol>> = {}, Method extends HTTPMethod = HTTPMethod, Path extends string = string, Response = unknown>(method: Method, path: Path, handler: LocalHandler<Schema, Instance, Path, Response>, hook?: LocalHook<Schema, Instance, Path>): ElysiaRoute<Method, Schema, Instance, Path, Response>;
|
|
65
|
+
state<Key extends string | number | symbol = keyof Instance['store'], Value = Instance['store'][keyof Instance['store']], NewInstance = Elysia<{
|
|
61
66
|
store: Instance['store'] & {
|
|
62
|
-
[key in Key]:
|
|
67
|
+
[key in Key]: Value;
|
|
63
68
|
};
|
|
64
69
|
request: Instance['request'];
|
|
65
70
|
schema: Instance['schema'];
|
|
71
|
+
meta: Instance['meta'];
|
|
66
72
|
}>>(name: Key, value: Value): NewInstance;
|
|
67
73
|
decorate<Name extends string, Value = any, NewInstance = Elysia<{
|
|
68
74
|
store: Instance['store'];
|
|
@@ -70,43 +76,48 @@ export default class Elysia<Instance extends ElysiaInstance = ElysiaInstance> {
|
|
|
70
76
|
[key in Name]: Value;
|
|
71
77
|
};
|
|
72
78
|
schema: Instance['schema'];
|
|
79
|
+
meta: Instance['meta'];
|
|
73
80
|
}>>(name: Name, value: Value): NewInstance;
|
|
74
|
-
derive<Returned extends Record<string | number | symbol, () => any> = Record<string | number | symbol, () => any>>(transform: (store: () => Readonly<Instance['store']>) => Returned): Elysia<{
|
|
75
|
-
store: Instance['store'] & Returned;
|
|
76
|
-
request: Instance['request'];
|
|
77
|
-
schema: Instance['schema'];
|
|
78
|
-
}>;
|
|
79
81
|
inject<Returned extends Object = Object>(transform: (context: Context<{}, Instance['store']> & Instance['request']) => Returned extends {
|
|
80
82
|
store: any;
|
|
81
83
|
} ? never : Returned): Elysia<{
|
|
82
84
|
store: Instance['store'];
|
|
83
85
|
request: Instance['request'] & Returned;
|
|
84
86
|
schema: Instance['schema'];
|
|
87
|
+
meta: Instance['meta'];
|
|
88
|
+
}>;
|
|
89
|
+
fn<T extends Record<string, unknown> | ((app: Instance['request'] & {
|
|
90
|
+
store: Instance['store'];
|
|
91
|
+
permission: Permission;
|
|
92
|
+
}) => Record<string, unknown>) = Record<string, unknown> | ((app: Instance['request'] & {
|
|
93
|
+
store: Instance['store'];
|
|
94
|
+
permission: Permission;
|
|
95
|
+
}) => Record<string, unknown>)>(value: T): Elysia<{
|
|
96
|
+
store: Instance['store'];
|
|
97
|
+
request: Instance['request'];
|
|
98
|
+
schema: Instance['schema'];
|
|
99
|
+
meta: Instance['meta'] & Record<typeof EXPOSED, T extends (store: any) => infer Returned ? Returned : T>;
|
|
85
100
|
}>;
|
|
86
101
|
schema<Schema extends TypedSchema<Exclude<keyof Instance['store'][typeof DEFS], number | symbol>> = TypedSchema<Exclude<keyof Instance['store'][typeof DEFS], number | symbol>>, NewInstance = Elysia<{
|
|
87
102
|
request: Instance['request'];
|
|
88
103
|
store: Instance['store'];
|
|
89
104
|
schema: MergeSchema<Schema, Instance['schema']>;
|
|
105
|
+
meta: Instance['meta'];
|
|
90
106
|
}>>(schema: Schema): NewInstance;
|
|
91
107
|
handle: (request: Request) => Promise<Response>;
|
|
92
108
|
handleError(request: Request, error: Error, set?: Context['set']): Promise<Response>;
|
|
93
109
|
listen: (options: string | number | Partial<Serve>, callback?: ListenCallback) => this;
|
|
94
110
|
stop: () => Promise<void>;
|
|
95
|
-
get modules(): Promise<Elysia<
|
|
96
|
-
store: Record<any, any> & Record<typeof SCHEMA, {}> & Record<typeof DEFS, {}>;
|
|
97
|
-
request: {};
|
|
98
|
-
schema: {};
|
|
99
|
-
}>>[]>;
|
|
111
|
+
get modules(): Promise<Elysia<any>[]>;
|
|
100
112
|
setModel<Recorder extends Record<string, TSchema>>(record: Recorder): Elysia<{
|
|
101
|
-
store: Instance['store']
|
|
102
|
-
[Defs in typeof DEFS]: Recorder;
|
|
103
|
-
};
|
|
113
|
+
store: Instance['store'];
|
|
104
114
|
request: Instance['request'];
|
|
105
115
|
schema: Instance['schema'];
|
|
116
|
+
meta: Instance['meta'] & Record<typeof DEFS, Recorder>;
|
|
106
117
|
}>;
|
|
107
118
|
}
|
|
108
|
-
export { Elysia };
|
|
109
|
-
export {
|
|
110
|
-
export { SCHEMA, DEFS, createValidationError, getSchemaValidator, mergeDeep, mergeHook, mergeObjectArray, mapPathnameAndQueryRegEx, mapQuery } from './utils';
|
|
119
|
+
export { Elysia, permission };
|
|
120
|
+
export { t } from './custom-types';
|
|
121
|
+
export { SCHEMA, DEFS, EXPOSED, createValidationError, getSchemaValidator, mergeDeep, mergeHook, mergeObjectArray, mapPathnameAndQueryRegEx, mapQuery } from './utils';
|
|
111
122
|
export type { Context, PreContext } from './context';
|
|
112
123
|
export type { Handler, RegisteredHook, BeforeRequestHandler, TypedRoute, OverwritableTypeRoute, ElysiaInstance, ElysiaConfig, HTTPMethod, ComposedHandler, InternalRoute, BodyParser, ErrorHandler, ErrorCode, TypedSchema, LocalHook, LocalHandler, LifeCycle, LifeCycleEvent, AfterRequestHandler, HookHandler, TypedSchemaToRoute, UnwrapSchema, LifeCycleStore, VoidLifeCycle, SchemaValidator, ElysiaRoute, ExtractPath, IsPathParameter, IsAny, IsNever, UnknownFallback, WithArray, ObjectValues, PickInOrder, MaybePromise, MergeIfNotNull } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Raikiri as e}from"raikiri";import{mapResponse as t,mapEarlyResponse as r}from"./handler";import{
|
|
1
|
+
import{Raikiri as e}from"raikiri";import{mapResponse as t,mapEarlyResponse as r}from"./handler";import{permission as s}from"./fn";import{SCHEMA as a,EXPOSED as n,DEFS as i,mapQuery as o,clone as h,mergeHook as l,mergeDeep as u,createValidationError as d,getSchemaValidator as f,getResponseSchemaValidator as c,mapPathnameAndQueryRegEx as m}from"./utils";import{registerSchemaPath as p}from"./schema";import{mapErrorCode as v,mapErrorStatus as g}from"./error";import{runFn as y}from"./fn";import{deserialize as b}from"superjson";export default class H{store={};meta={[a]:Object.create(null),[i]:Object.create(null),[n]:Object.create(null)};decorators={query:{},set:{status:200,headers:{}},store:this.store,[a]:this.meta[a],[i]:this.meta[i]};event={start:[],request:[],parse:[],transform:[],beforeHandle:[],afterHandle:[],error:[],stop:[]};server=null;$schema=null;router=new e;routes=[];lazyLoadModules=[];constructor(e){this.config={fn:"/~fn",...e}}_addHandler(e,t,r,s){t=t.startsWith("/")?t:`/${t}`,this.routes.push({method:e,path:t,handler:r,hooks:l(h(this.event),s)});let n=this.meta[i],o=f(s?.schema?.body??this.$schema?.body,n),u=f(s?.schema?.headers??this.$schema?.headers,n,!0),d=f(s?.schema?.params??this.$schema?.params,n),m=f(s?.schema?.query??this.$schema?.query,n),v=c(s?.schema?.response??this.$schema?.response,n);p({schema:this.meta[a],contentType:s?.schema?.contentType,hook:s,method:e,path:t,models:this.meta[i]});let g=l(h(this.event),s);g.schema||g.transform.length||g.beforeHandle.length||g.error.length||g.afterHandle.length||(g=void 0);let y={handle:r,hooks:g,validator:o||u||d||m||v?{body:o,header:u,params:d,query:m,response:v}:void 0};this.router.add(e,t,y)}onStart(e){return this.event.start.push(e),this}onRequest(e){return this.event.request.push(e),this}onParse(e){return this.event.parse.splice(this.event.parse.length-1,0,e),this}onTransform(e){return this.event.transform.push(e),this}onBeforeHandle(e){return this.event.beforeHandle.push(e),this}onAfterHandle(e){return this.event.afterHandle.push(e),this}onError(e){return this.event.error.push(e),this}onStop(e){return this.event.stop.push(e),this}on(e,t){switch(e){case"start":this.event.start.push(t);break;case"request":this.event.request.push(t);break;case"parse":this.event.parse.push(t);break;case"transform":this.event.transform.push(t);break;case"beforeHandle":this.event.beforeHandle.push(t);break;case"afterHandle":this.event.afterHandle.push(t);break;case"error":this.event.error.push(t);break;case"stop":this.event.stop.push(t)}return this}group(e,t){let r=new H;r.store=this.store;let s=t(r);return s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),Object.values(r.routes).forEach(({method:t,path:r,handler:a,hooks:n})=>{"/"===r?this._addHandler(t,e,a,l(n,{error:s.event.error})):this._addHandler(t,`${e}${r}`,a,l(n,{error:s.event.error}))}),this}guard(e,t){let r=new H;r.store=this.store;let s=t(r);return s.event.request.length&&(this.event.request=[...this.event.request,...s.event.request]),Object.values(r.routes).forEach(({method:t,path:r,handler:s,hooks:a})=>{this._addHandler(t,r,s,l(e,a))}),this}use(e){if(e instanceof Promise)return this.lazyLoadModules.push(e.then(e=>"function"==typeof e?e(this):e.default(this))),this;let t=e(this);return t instanceof Promise?(this.lazyLoadModules.push(t),this):t}get(e,t,r){return this._addHandler("GET",e,t,r),this}post(e,t,r){return this._addHandler("POST",e,t,r),this}put(e,t,r){return this._addHandler("PUT",e,t,r),this}patch(e,t,r){return this._addHandler("PATCH",e,t,r),this}delete(e,t,r){return this._addHandler("DELETE",e,t,r),this}options(e,t,r){return this._addHandler("OPTIONS",e,t,r),this}all(e,t,r){return this._addHandler("ALL",e,t,r),this}head(e,t,r){return this._addHandler("HEAD",e,t,r),this}trace(e,t,r){return this._addHandler("TRACE",e,t,r),this}connect(e,t,r){return this._addHandler("CONNECT",e,t,r),this}route(e,t,r,s){return this._addHandler(e,t,r,s),this}state(e,t){return e in this.store||(this.store[e]=t),this}decorate(e,t){return e in this.decorators||(this.decorators[e]=t),this}inject(e){return this.onTransform(t=>{Object.assign(t,e(t))})}fn(e){return 0===Object.keys(this.meta[n]).length&&this.post(this.config.fn??"/~fn",e=>y(e,this.meta[n])),this.meta[n]=u(this.meta[n],"function"==typeof e?e({...this.decorators,store:this.store,permission:s}):e),this}schema(e){let t=this.meta[i];return this.$schema={body:f(e.body,t),headers:f(e?.headers,t,!0),params:f(e?.params,t),query:f(e?.query,t),response:f(e?.response,t)},this}handle=async e=>{let s;let a=h(this.decorators);a.request=e;try{let n;if(this.event.request.length)for(let e=0;e<this.event.request.length;e++){let t=this.event.request[e](a);if(t instanceof Promise&&(t=await t),t=r(t,a.set))return t}let i=e.url.match(m);if(!i)throw Error("NOT_FOUND");let h=this.router.match(e.method,i[1])??this.router.match("ALL",i[1]);if(!h)throw Error("NOT_FOUND");let l=h.store,u=l.hooks;if(u?.error&&(s=u?.error),"GET"!==e.method){let t=e.headers.get("content-type");if(t){let r=t.indexOf(";");if(-1!==r&&(t=t.slice(0,r)),this.event.parse.length)for(let e=0;e<this.event.parse.length;e++){let r=this.event.parse[e](a,t);if(r instanceof Promise&&(r=await r),void 0!==r){n=r;break}}if(void 0===n)switch(t){case"application/json":n=await e.json();break;case"text/plain":n=await e.text();break;case"application/x-www-form-urlencoded":n=o(await e.text());break;case"multipart/form-data":n={},await e.formData().then(e=>{for(let t of e.keys()){if(t in n)continue;let r=e.getAll(t);1===r.length?n[t]=r[0]:n[t]=r}});break;case"elysia/fn":n=b(await e.json())}}}if(a.body=n,a.params=h.params,i[2]&&(a.query=o(i[2])),u?.transform.length)for(let e=0;e<u.transform.length;e++){let t=u.transform[e](a);t instanceof Promise&&await t}if(l.validator){let t=l.validator;if(u?.error&&(s=u?.error),t.headers){let r={};for(let t in e.headers)r[t]=e.headers.get(t);if(!1===t.headers.Check(r))throw d("header",t.headers,r)}if(!1===t.params?.Check(a.params))throw d("params",t.params,a.params);if(!1===t.query?.Check(a.query))throw d("query",t.query,a.query);if(!1===t.body?.Check(n))throw d("body",t.body,n)}if(u?.beforeHandle.length)for(let e=0;e<u.beforeHandle.length;e++){let t=u.beforeHandle[e](a);if(t instanceof Promise&&(t=await t),null!=t){for(let e=0;e<u.afterHandle.length;e++){let r=u.afterHandle[e](a,t);r instanceof Promise&&(r=await r),r&&(t=r)}let e=r(t,a.set);if(e)return e}}let f=l.handle(a);if(f instanceof Promise&&(f=await f),!1===l.validator?.response?.Check(f))throw u?.error&&(s=u?.error),d("response",l.validator.response,f);if(u?.afterHandle.length)for(let e=0;e<u.afterHandle.length;e++){let t=u.afterHandle[e](a,f);t instanceof Promise&&(t=await t);let s=r(t,a.set);if(s)return s}return t(f,a.set)}catch(n){let t=a.set;if((!t.status||t.status<300)&&(t.status=500),s){let a=v(n.message);for(let i=0;i<s.length;i++){let o=s[i]({request:e,error:n,set:t,code:a});o instanceof Promise&&(o=await o);let h=r(o,t);if(h)return h}}return this.handleError(e,n,t)}};async handleError(e,r,s={headers:{}}){for(let a=0;a<this.event.error.length;a++){let n=this.event.error[a]({request:e,code:v(r.message),error:r,set:s});if(n instanceof Promise&&(n=await n),null!=n)return t(n,s)}return new Response("string"==typeof r.cause?r.cause:r.message,{headers:s.headers,status:g(v(r.message))})}listen=(e,t)=>{if(!Bun)throw Error("Bun to run");if("string"==typeof e&&Number.isNaN(e=+e))throw Error("Port must be a numeric value");let r=this.handle,s="object"==typeof e?{...this.config.serve,...e,fetch:r}:{...this.config.serve,port:e,fetch:r},a=`$$Elysia:${s.port}`;globalThis[a]?(this.server=globalThis[a],this.server.reload(s)):globalThis[a]=this.server=Bun.serve(s);for(let e=0;e<this.event.start.length;e++)this.event.start[e](this);return t&&t(this.server),Promise.all(this.lazyLoadModules).then(()=>{this.server.pendingRequests||Bun.gc(!0)}),this};stop=async()=>{if(!this.server)throw Error("Elysia isn't running. Call `app.listen` to start the server.");this.server.stop();for(let e=0;e<this.event.stop.length;e++)await this.event.stop[e](this)};get modules(){return Promise.all(this.lazyLoadModules)}setModel(e){return Object.entries(e).forEach(([e,t])=>{e in this.meta[i]||(this.meta[i][e]=t)}),this}}export{t}from"./custom-types";export{SCHEMA,DEFS,EXPOSED,createValidationError,getSchemaValidator,mergeDeep,mergeHook,mergeObjectArray,mapPathnameAndQueryRegEx,mapQuery}from"./utils";export{H as Elysia,s as permission};
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { TSchema } from '@sinclair/typebox';
|
|
2
|
-
import type {
|
|
1
|
+
import { type TSchema } from '@sinclair/typebox';
|
|
2
|
+
import type { OpenAPIV3 } from 'openapi-types';
|
|
3
3
|
import type { HTTPMethod, LocalHook } from './types';
|
|
4
4
|
export declare const toOpenAPIPath: (path: string) => string;
|
|
5
5
|
export declare const mapProperties: (name: string, schema: TSchema | string | undefined, models: Record<string, TSchema>) => any[];
|
|
6
|
-
export declare const registerSchemaPath: ({ schema, path, method, hook, models }: {
|
|
7
|
-
schema:
|
|
6
|
+
export declare const registerSchemaPath: ({ schema, contentType, path, method, hook, models }: {
|
|
7
|
+
schema: Partial<OpenAPIV3.PathsObject>;
|
|
8
|
+
contentType?: string | string[] | undefined;
|
|
8
9
|
path: string;
|
|
9
10
|
method: HTTPMethod;
|
|
10
11
|
hook?: LocalHook<import("./types").TypedSchema<string>, import("./types").ElysiaInstance<{
|
|
11
|
-
store: Record<any, any
|
|
12
|
+
store: Record<any, any>;
|
|
12
13
|
request: {};
|
|
13
14
|
schema: {};
|
|
14
|
-
|
|
15
|
+
meta: Record<typeof import("./utils").SCHEMA, {}> & Record<typeof import("./utils").DEFS, {}> & Record<typeof import("./utils").EXPOSED, {}>;
|
|
16
|
+
}>, string, import("./types").MergeSchema<import("./types").TypedSchema<string>, {}>, import("./types").TypedSchema<string>> | undefined;
|
|
15
17
|
models: Record<string, TSchema>;
|
|
16
18
|
}) => void;
|
package/dist/schema.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Kind as e}from"@sinclair/typebox";export const toOpenAPIPath=e=>e.split("/").map(e=>e.startsWith(":")?`{${e.slice(1,e.length)}}`:e).join("/");export const mapProperties=(e,t,r)=>{if(void 0===t)return[];if("string"==typeof t){if(t in r)t=r[t];else throw Error(`Can't find model ${t}`)}return Object.entries(t?.properties??[]).map(([r,
|
|
1
|
+
import{Kind as e}from"@sinclair/typebox";export const toOpenAPIPath=e=>e.split("/").map(e=>e.startsWith(":")?`{${e.slice(1,e.length)}}`:e).join("/");export const mapProperties=(e,t,r)=>{if(void 0===t)return[];if("string"==typeof t){if(t in r)t=r[t];else throw Error(`Can't find model ${t}`)}return Object.entries(t?.properties??[]).map(([r,o])=>({...o,in:e,name:r,type:o?.type,required:t.required?.includes(r)??!1}))};let t=(e,t)=>{let r={};for(let o of e)r[o]={schema:"string"==typeof t?{$ref:`#/components/schemas/${t}`}:{...t}};return r};export const registerSchemaPath=({schema:r,contentType:o=["application/json","multipart/form-data","text/plain"],path:s,method:i,hook:n,models:p})=>{s=toOpenAPIPath(s);let a="string"==typeof o?[o]:o??["application/json"],c=n?.schema?.body,l=n?.schema?.params,m=n?.schema?.headers,f=n?.schema?.query,h=n?.schema?.response;if("object"==typeof h){if(e in h){let{type:e,properties:r,required:o,...s}=h;h={200:{...s,description:s.description,content:t(a,"object"===e||"array"===e?{type:e,properties:r,required:o}:h)}}}else Object.entries(h).forEach(([e,r])=>{if("string"==typeof r){let{type:o,properties:s,required:i,...n}=p[r];h[e]={...n,description:n.description,content:t(a,r)}}else{let{type:o,properties:s,required:i,...n}=r;h[e]={...n,description:n.description,content:t(a,{type:o,properties:s,required:i})}}})}else if("string"==typeof h){let{type:e,properties:r,required:o,...s}=p[h];h={200:{...s,content:t(a,h)}}}let d=[...mapProperties("header",m,p),...mapProperties("path",l,p),...mapProperties("query",f,p)];r[s]={...r[s]?r[s]:{},[i.toLowerCase()]:{...m||l||f||c?{parameters:d}:{},...h?{responses:h}:{},...n?.schema?.detail,...c?{requestBody:{content:t(a,"string"==typeof c?{$ref:`#/components/schemas/${c}`}:c)}}:null}}};
|
package/dist/types.d.ts
CHANGED
|
@@ -4,26 +4,33 @@ import type { Serve, Server } from 'bun';
|
|
|
4
4
|
import type { Context, PreContext } from './context';
|
|
5
5
|
import type { Static, TObject, TSchema } from '@sinclair/typebox';
|
|
6
6
|
import type { TypeCheck } from '@sinclair/typebox/compiler';
|
|
7
|
-
import type { SCHEMA, DEFS } from './utils';
|
|
8
|
-
import type {
|
|
7
|
+
import type { SCHEMA, DEFS, EXPOSED } from './utils';
|
|
8
|
+
import type { OpenAPIV3 } from 'openapi-types';
|
|
9
9
|
export type WithArray<T> = T | T[];
|
|
10
10
|
export type ObjectValues<T extends object> = T[keyof T];
|
|
11
|
-
export
|
|
12
|
-
store?: Record<any, any
|
|
13
|
-
[x in string]: TSchema;
|
|
14
|
-
}>;
|
|
11
|
+
export type ElysiaInstance<Instance extends {
|
|
12
|
+
store?: Record<any, any>;
|
|
15
13
|
request?: Record<any, any>;
|
|
16
14
|
schema?: TypedSchema;
|
|
15
|
+
meta?: Record<typeof SCHEMA, Partial<OpenAPIV3.PathsObject>> & Record<typeof DEFS, {
|
|
16
|
+
[x in string]: TSchema;
|
|
17
|
+
}> & Record<typeof EXPOSED, Record<string, Record<string, unknown>>>;
|
|
17
18
|
} = {
|
|
18
|
-
store: Record<any, any
|
|
19
|
+
store: Record<any, any>;
|
|
19
20
|
request: {};
|
|
20
21
|
schema: {};
|
|
21
|
-
}> {
|
|
22
|
-
|
|
22
|
+
meta: Record<typeof SCHEMA, {}> & Record<typeof DEFS, {}> & Record<typeof EXPOSED, {}>;
|
|
23
|
+
}> = {
|
|
24
|
+
request: Instance['request'];
|
|
23
25
|
store: Instance['store'] extends undefined ? {} : Instance['store'];
|
|
24
26
|
schema: Instance['schema'] extends undefined ? TypedSchema : Instance['schema'];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
meta: Instance['meta'];
|
|
28
|
+
};
|
|
29
|
+
export type Handler<Route extends TypedRoute = TypedRoute, Instance extends ElysiaInstance = ElysiaInstance, CatchResponse = Route['response']> = (context: Context<Route, Instance['store']> & Instance['request'] & {
|
|
30
|
+
a: Instance;
|
|
31
|
+
r: Route;
|
|
32
|
+
merged: MergeSchema<Instance['schema'], Route>;
|
|
33
|
+
}) => Route['response'] extends (models: Record<string, TSchema>) => TSchema ? undefined extends ReturnType<Route['response']> ? MaybePromise<CatchResponse> | Response : MaybePromise<ReturnType<Route['response']>> | Response : undefined extends Route['response'] ? MaybePromise<CatchResponse> | Response : MaybePromise<Route['response']> | Response;
|
|
27
34
|
export type NoReturnHandler<Route extends TypedRoute = TypedRoute, Instance extends ElysiaInstance = ElysiaInstance> = (context: Context<Route, Instance['store']> & Instance['request']) => void | Promise<void>;
|
|
28
35
|
export type LifeCycleEvent = 'start' | 'request' | 'parse' | 'transform' | 'beforeHandle' | 'afterHandle' | 'error' | 'stop';
|
|
29
36
|
export type ListenCallback = ((server: Server) => void) | ((server: Server) => Promise<void>);
|
|
@@ -65,17 +72,17 @@ export interface TypedSchema<ModelName extends string = string> {
|
|
|
65
72
|
params?: TObject | ModelName;
|
|
66
73
|
response?: TSchema | Record<string | '200', TSchema> | ModelName | Record<string, ModelName | TSchema>;
|
|
67
74
|
}
|
|
68
|
-
export type UnwrapSchema<Schema extends TSchema | undefined | string,
|
|
75
|
+
export type UnwrapSchema<Schema extends TSchema | undefined | string, Definitions extends ElysiaInstance['meta'][typeof DEFS] = {}, Fallback = unknown> = Schema extends string ? Definitions extends {
|
|
69
76
|
[name in Schema]: infer NamedSchema extends TSchema;
|
|
70
77
|
} ? Static<NamedSchema> : Fallback : Schema extends TSchema ? Static<NonNullable<Schema>> : Fallback;
|
|
71
|
-
export type TypedSchemaToRoute<Schema extends TypedSchema
|
|
72
|
-
body: UnwrapSchema<Schema['body'],
|
|
73
|
-
headers: UnwrapSchema<Schema['headers'],
|
|
74
|
-
query: UnwrapSchema<Schema['query'],
|
|
75
|
-
params: UnwrapSchema<Schema['params'],
|
|
76
|
-
response: Schema['response'] extends TSchema | string ? UnwrapSchema<Schema['response'],
|
|
78
|
+
export type TypedSchemaToRoute<Schema extends TypedSchema<any>, Definitions extends ElysiaInstance['meta'][typeof DEFS]> = {
|
|
79
|
+
body: UnwrapSchema<Schema['body'], Definitions>;
|
|
80
|
+
headers: UnwrapSchema<Schema['headers'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
81
|
+
query: UnwrapSchema<Schema['query'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
82
|
+
params: UnwrapSchema<Schema['params'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
83
|
+
response: Schema['response'] extends TSchema | string ? UnwrapSchema<Schema['response'], Definitions> : Schema['response'] extends {
|
|
77
84
|
[k in string]: TSchema | string;
|
|
78
|
-
} ? UnwrapSchema<ObjectValues<Schema['response']>,
|
|
85
|
+
} ? UnwrapSchema<ObjectValues<Schema['response']>, Definitions> : unknown;
|
|
79
86
|
};
|
|
80
87
|
export type AnyTypedSchema = {
|
|
81
88
|
body: unknown;
|
|
@@ -91,7 +98,7 @@ export type SchemaValidator = {
|
|
|
91
98
|
params?: TypeCheck<any>;
|
|
92
99
|
response?: TypeCheck<any>;
|
|
93
100
|
};
|
|
94
|
-
export type HookHandler<Schema extends TypedSchema = TypedSchema, Instance extends ElysiaInstance = ElysiaInstance, Path extends string = string, Typed extends AnyTypedSchema = TypedSchemaToRoute<Schema, Instance>> = Handler<Typed['params'] extends {} ? Omit<Typed, 'response'> & {
|
|
101
|
+
export type HookHandler<Schema extends TypedSchema = TypedSchema, Instance extends ElysiaInstance = ElysiaInstance, Path extends string = string, Typed extends AnyTypedSchema = TypedSchemaToRoute<Schema, Instance['meta'][typeof DEFS]>> = Handler<Typed['params'] extends {} ? Omit<Typed, 'response'> & {
|
|
95
102
|
response: void | Typed['response'];
|
|
96
103
|
} : Omit<Omit<Typed, 'response'> & {
|
|
97
104
|
response: void | Typed['response'];
|
|
@@ -101,62 +108,65 @@ export type HookHandler<Schema extends TypedSchema = TypedSchema, Instance exten
|
|
|
101
108
|
export type MergeIfNotNull<A, B> = B extends null ? A : A & B;
|
|
102
109
|
export type UnknownFallback<A, B> = unknown extends A ? B : A;
|
|
103
110
|
export type PickInOrder<A, B> = A extends NonNullable<A> ? A : B;
|
|
104
|
-
export type MergeSchema<A extends TypedSchema
|
|
111
|
+
export type MergeSchema<A extends TypedSchema<any>, B extends TypedSchema<any>> = {
|
|
105
112
|
body: PickInOrder<PickInOrder<A['body'], B['body']>, undefined>;
|
|
106
113
|
headers: PickInOrder<PickInOrder<A['headers'], B['headers']>, undefined>;
|
|
107
114
|
query: PickInOrder<PickInOrder<A['query'], B['query']>, undefined>;
|
|
108
115
|
params: PickInOrder<PickInOrder<A['params'], B['params']>, undefined>;
|
|
109
116
|
response: PickInOrder<PickInOrder<A['response'], B['response']>, undefined>;
|
|
110
117
|
};
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
type MaybeArray<T> = T | T[];
|
|
119
|
+
type ExtractModelName<Type> = Type extends TypedSchema<infer X> ? X : never;
|
|
120
|
+
type ContentType = MaybeArray<(string & {}) | 'text/plain' | 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded'>;
|
|
121
|
+
export interface LocalHook<Schema extends TypedSchema = TypedSchema, Instance extends ElysiaInstance<any> = ElysiaInstance, Path extends string = string, FinalSchema extends MergeSchema<Schema, Instance['schema']> = MergeSchema<Schema, Instance['schema']>, Models extends TypedSchema = TypedSchema<ExtractModelName<Schema>>> {
|
|
122
|
+
schema?: (Models extends Schema ? Models : Models) & {
|
|
123
|
+
contentType?: ContentType;
|
|
124
|
+
detail?: Partial<OpenAPIV3.OperationObject>;
|
|
114
125
|
};
|
|
115
126
|
transform?: WithArray<HookHandler<FinalSchema, Instance, Path>>;
|
|
116
127
|
beforeHandle?: WithArray<HookHandler<FinalSchema, Instance, Path>>;
|
|
117
128
|
afterHandle?: WithArray<AfterRequestHandler<any, Instance>>;
|
|
118
129
|
error?: WithArray<ErrorHandler>;
|
|
119
130
|
}
|
|
120
|
-
export type RouteToSchema<Schema extends TypedSchema
|
|
131
|
+
export type RouteToSchema<Schema extends TypedSchema, InstanceSchema extends ElysiaInstance['schema'], Definitions extends ElysiaInstance['meta'][typeof DEFS], Path extends string = string, FinalSchema extends MergeSchema<Schema, InstanceSchema> = MergeSchema<Schema, InstanceSchema>> = FinalSchema['params'] extends NonNullable<Schema['params']> ? TypedSchemaToRoute<FinalSchema, Definitions> : Omit<TypedSchemaToRoute<FinalSchema, Definitions>, 'params'> & {
|
|
121
132
|
params: Record<ExtractPath<Path>, string>;
|
|
122
133
|
};
|
|
123
134
|
export type ElysiaRoute<Method extends string = string, Schema extends TypedSchema = TypedSchema, Instance extends ElysiaInstance = ElysiaInstance, Path extends string = string, CatchResponse = unknown> = Elysia<{
|
|
124
135
|
request: Instance['request'];
|
|
125
|
-
store: Instance['store']
|
|
126
|
-
[SCHEMA]: {
|
|
127
|
-
[path in Path]: {
|
|
128
|
-
[method in Method]: TypedRouteToEden<Schema, Instance, Path> extends infer FinalSchema extends AnyTypedSchema ? Omit<FinalSchema, 'response'> & {
|
|
129
|
-
response: undefined extends FinalSchema['response'] ? {
|
|
130
|
-
'200': CatchResponse;
|
|
131
|
-
} : FinalSchema['response'];
|
|
132
|
-
} : never;
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
+
store: Instance['store'];
|
|
136
137
|
schema: Instance['schema'];
|
|
138
|
+
meta: Instance['meta'] & Record<typeof SCHEMA, {
|
|
139
|
+
[path in Path]: {
|
|
140
|
+
[method in Method]: TypedRouteToEden<Schema, Instance['schema'], Path> extends infer FinalSchema extends AnyTypedSchema ? Omit<FinalSchema, 'response'> & {
|
|
141
|
+
response: undefined extends FinalSchema['response'] ? {
|
|
142
|
+
'200': CatchResponse;
|
|
143
|
+
} : FinalSchema['response'];
|
|
144
|
+
} : never;
|
|
145
|
+
};
|
|
146
|
+
}>;
|
|
137
147
|
}>;
|
|
138
|
-
export type TypedRouteToEden<Schema extends TypedSchema = TypedSchema,
|
|
148
|
+
export type TypedRouteToEden<Schema extends TypedSchema = TypedSchema, InstanceSchema extends TypedSchema<string> = ElysiaInstance['schema'], Path extends string = string, FinalSchema extends MergeSchema<Schema, InstanceSchema> = MergeSchema<Schema, InstanceSchema>> = FinalSchema['params'] extends NonNullable<Schema['params']> ? TypedSchemaToEden<FinalSchema, InstanceSchema> : Omit<TypedSchemaToEden<FinalSchema, InstanceSchema>, 'params'> & {
|
|
139
149
|
params: Record<ExtractPath<Path>, string>;
|
|
140
150
|
};
|
|
141
|
-
export type TypedSchemaToEden<Schema extends TypedSchema,
|
|
142
|
-
body: UnwrapSchema<Schema['body'],
|
|
143
|
-
headers: UnwrapSchema<Schema['headers'],
|
|
144
|
-
query: UnwrapSchema<Schema['query'],
|
|
145
|
-
params: UnwrapSchema<Schema['params'],
|
|
151
|
+
export type TypedSchemaToEden<Schema extends TypedSchema, Definitions extends ElysiaInstance['meta'][typeof DEFS]> = {
|
|
152
|
+
body: UnwrapSchema<Schema['body'], Definitions>;
|
|
153
|
+
headers: UnwrapSchema<Schema['headers'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
154
|
+
query: UnwrapSchema<Schema['query'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
155
|
+
params: UnwrapSchema<Schema['params'], Definitions> extends infer Result extends Record<string, any> ? Result : undefined;
|
|
146
156
|
response: Schema['response'] extends TSchema | string ? {
|
|
147
|
-
'200': UnwrapSchema<Schema['response'],
|
|
157
|
+
'200': UnwrapSchema<Schema['response'], Definitions>;
|
|
148
158
|
} : Schema['response'] extends {
|
|
149
159
|
[x in string]: TSchema | string;
|
|
150
160
|
} ? {
|
|
151
|
-
[key in keyof Schema['response']]: UnwrapSchema<Schema['response'][key],
|
|
161
|
+
[key in keyof Schema['response']]: UnwrapSchema<Schema['response'][key], Definitions>;
|
|
152
162
|
} : unknown;
|
|
153
163
|
};
|
|
154
|
-
export type LocalHandler<Schema extends TypedSchema
|
|
164
|
+
export type LocalHandler<Schema extends TypedSchema, Instance extends ElysiaInstance, Path extends string = string, CatchResponse = unknown> = Handler<RouteToSchema<Schema, Instance['schema'], Instance['meta'][typeof DEFS], Path>, Instance, CatchResponse>;
|
|
155
165
|
export interface TypedRoute {
|
|
156
166
|
body?: unknown;
|
|
157
|
-
headers?: Record<string,
|
|
158
|
-
query?: Record<string,
|
|
159
|
-
params?: Record<string,
|
|
167
|
+
headers?: Record<string, unknown>;
|
|
168
|
+
query?: Record<string, unknown>;
|
|
169
|
+
params?: Record<string, unknown>;
|
|
160
170
|
response?: unknown;
|
|
161
171
|
}
|
|
162
172
|
export type OverwritableTypeRoute = {
|
|
@@ -172,6 +182,7 @@ export type ComposedHandler = {
|
|
|
172
182
|
validator?: SchemaValidator;
|
|
173
183
|
};
|
|
174
184
|
export interface ElysiaConfig {
|
|
185
|
+
fn?: string;
|
|
175
186
|
serve?: Partial<Serve>;
|
|
176
187
|
}
|
|
177
188
|
export type IsPathParameter<Part> = Part extends `:${infer Parameter}` ? Parameter : never;
|
|
@@ -219,4 +230,14 @@ export type DeepMergeTwoTypes<T, U> = [
|
|
|
219
230
|
export type IsAny<T> = unknown extends T ? [keyof T] extends [never] ? false : true : false;
|
|
220
231
|
export type MaybePromise<T> = T | Promise<T>;
|
|
221
232
|
export type IsNever<T> = [T] extends [never] ? true : false;
|
|
233
|
+
export type FunctionProperties<T> = {
|
|
234
|
+
[K in keyof T as T[K] extends Record<any, any> | ((...args: any[]) => any) ? IsAny<T[K]> extends true ? never : K : never]: T[K] extends (...args: any[]) => any ? T[K] : T[K] extends Record<string, any> ? FunctionProperties<T[K]> : never;
|
|
235
|
+
};
|
|
236
|
+
export type JoinKeys<T, Prefix extends string = ''> = {
|
|
237
|
+
[K in keyof T]-?: T[K] extends string | Function ? '' extends Prefix ? K : K extends string ? `${Prefix}.${K}` : never : K extends string ? JoinKeys<T[K], '' extends Prefix ? K : `${Prefix}.${K}`> : never;
|
|
238
|
+
}[keyof T];
|
|
239
|
+
export type ConnectedKeysType<T, K extends string> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? ConnectedKeysType<T[Key], Rest> : never : K extends keyof T ? T[K] extends (...args: infer A) => any ? A : never : never;
|
|
240
|
+
export type Prettify<T> = {
|
|
241
|
+
[K in keyof T]: T[K];
|
|
242
|
+
} & {};
|
|
222
243
|
export {};
|
package/dist/utils.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { TypeCheck } from '@sinclair/typebox/compiler';
|
|
|
3
3
|
import type { DeepMergeTwoTypes, LifeCycleStore, LocalHook, TypedSchema, RegisteredHook } from './types';
|
|
4
4
|
export declare const SCHEMA: unique symbol;
|
|
5
5
|
export declare const DEFS: unique symbol;
|
|
6
|
+
export declare const EXPOSED: unique symbol;
|
|
6
7
|
export declare const mergeObjectArray: <T>(a: T | T[], b: T | T[]) => T[];
|
|
7
8
|
export declare const mergeHook: (a: LocalHook<any> | LifeCycleStore<any>, b: LocalHook<any>) => RegisteredHook<any>;
|
|
8
9
|
export declare const clone: <T extends Object | any[] = Object | any[]>(value: T) => T;
|