spiceflow 0.0.6 → 1.0.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/README.md +1 -171
- package/dist/client/errors.d.ts +7 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +18 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/index.d.ts +14 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +376 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +87 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/utils.d.ts +2 -0
- package/dist/client/utils.d.ts.map +1 -0
- package/dist/client/utils.js +9 -0
- package/dist/client/utils.js.map +1 -0
- package/dist/client/ws.d.ts +15 -0
- package/dist/client/ws.d.ts.map +1 -0
- package/dist/client/ws.js +51 -0
- package/dist/client/ws.js.map +1 -0
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +237 -0
- package/dist/client.test.js.map +1 -0
- package/dist/elysia-fork/context.d.ts +87 -0
- package/dist/elysia-fork/context.d.ts.map +1 -0
- package/dist/elysia-fork/context.js +2 -0
- package/dist/elysia-fork/context.js.map +1 -0
- package/dist/elysia-fork/error.d.ts +246 -0
- package/dist/elysia-fork/error.d.ts.map +1 -0
- package/dist/elysia-fork/error.js +195 -0
- package/dist/elysia-fork/error.js.map +1 -0
- package/dist/elysia-fork/types.d.ts +652 -0
- package/dist/elysia-fork/types.d.ts.map +1 -0
- package/dist/elysia-fork/types.js +3 -0
- package/dist/elysia-fork/types.js.map +1 -0
- package/dist/elysia-fork/utils.d.ts +134 -0
- package/dist/elysia-fork/utils.d.ts.map +1 -0
- package/dist/elysia-fork/utils.js +70 -0
- package/dist/elysia-fork/utils.js.map +1 -0
- package/dist/spiceflow.d.ts +253 -0
- package/dist/spiceflow.d.ts.map +1 -0
- package/dist/spiceflow.js +500 -0
- package/dist/spiceflow.js.map +1 -0
- package/dist/spiceflow.test.d.ts +2 -0
- package/dist/spiceflow.test.d.ts.map +1 -0
- package/dist/spiceflow.test.js +225 -0
- package/dist/spiceflow.test.js.map +1 -0
- package/dist/stream.test.d.ts +2 -0
- package/dist/stream.test.d.ts.map +1 -0
- package/dist/stream.test.js +286 -0
- package/dist/stream.test.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -20
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +17 -46
- package/dist/utils.js.map +1 -1
- package/package.json +12 -36
- package/src/client/errors.ts +21 -0
- package/src/client/index.ts +539 -0
- package/src/client/types.ts +233 -0
- package/src/client/utils.ts +7 -0
- package/src/client/ws.ts +99 -0
- package/src/client.test.ts +235 -0
- package/src/elysia-fork/context.ts +196 -0
- package/src/elysia-fork/error.ts +293 -0
- package/src/elysia-fork/types.ts +1454 -0
- package/src/elysia-fork/utils.ts +85 -0
- package/src/spiceflow.test.ts +290 -0
- package/src/spiceflow.ts +1266 -0
- package/src/stream.test.ts +342 -0
- package/src/types.ts +0 -0
- package/src/utils.ts +21 -70
- package/context.d.ts +0 -2
- package/context.js +0 -1
- package/dist/babel.test.d.ts +0 -2
- package/dist/babel.test.d.ts.map +0 -1
- package/dist/babel.test.js +0 -27
- package/dist/babel.test.js.map +0 -1
- package/dist/babelDebugOutputs.d.ts +0 -9
- package/dist/babelDebugOutputs.d.ts.map +0 -1
- package/dist/babelDebugOutputs.js +0 -34
- package/dist/babelDebugOutputs.js.map +0 -1
- package/dist/babelTransformRpc.d.ts +0 -19
- package/dist/babelTransformRpc.d.ts.map +0 -1
- package/dist/babelTransformRpc.js +0 -285
- package/dist/babelTransformRpc.js.map +0 -1
- package/dist/browser.d.ts +0 -8
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.js +0 -126
- package/dist/browser.js.map +0 -1
- package/dist/build.d.ts +0 -13
- package/dist/build.d.ts.map +0 -1
- package/dist/build.js +0 -230
- package/dist/build.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -111
- package/dist/cli.js.map +0 -1
- package/dist/context-internal.d.ts +0 -20
- package/dist/context-internal.d.ts.map +0 -1
- package/dist/context-internal.js +0 -16
- package/dist/context-internal.js.map +0 -1
- package/dist/context.d.ts +0 -2
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -2
- package/dist/context.js.map +0 -1
- package/dist/expose.d.ts +0 -6
- package/dist/expose.d.ts.map +0 -1
- package/dist/expose.js +0 -32
- package/dist/expose.js.map +0 -1
- package/dist/headers.d.ts +0 -2
- package/dist/headers.d.ts.map +0 -1
- package/dist/headers.js +0 -18
- package/dist/headers.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -23
- package/dist/index.js.map +0 -1
- package/dist/jsonRpc.d.ts +0 -32
- package/dist/jsonRpc.d.ts.map +0 -1
- package/dist/jsonRpc.js +0 -3
- package/dist/jsonRpc.js.map +0 -1
- package/dist/server.d.ts +0 -32
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -292
- package/dist/server.js.map +0 -1
- package/headers.d.ts +0 -2
- package/headers.js +0 -1
- package/sdk-template/package.json +0 -22
- package/sdk-template/src/index.ts +0 -2
- package/sdk-template/src/v1/example.ts +0 -5
- package/sdk-template/src/v1/generator.ts +0 -12
- package/sdk-template/tsconfig.json +0 -16
- package/src/babel.test.ts +0 -35
- package/src/babelDebugOutputs.ts +0 -56
- package/src/babelTransformRpc.ts +0 -394
- package/src/browser.ts +0 -141
- package/src/build.ts +0 -298
- package/src/cli.ts +0 -132
- package/src/context-internal.ts +0 -36
- package/src/context.ts +0 -5
- package/src/expose.ts +0 -34
- package/src/headers.ts +0 -19
- package/src/index.ts +0 -34
- package/src/jsonRpc.ts +0 -43
- package/src/server.ts +0 -384
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import type { Elysia } from '../spiceflow'
|
|
3
|
+
// import { EdenWS } from './ws'
|
|
4
|
+
// import type { IsNever, Not, Prettify } from '../types'
|
|
5
|
+
import { EdenFetchError } from './errors'
|
|
6
|
+
import { EdenWS } from './ws'
|
|
7
|
+
|
|
8
|
+
export type Prettify<T> = {
|
|
9
|
+
[K in keyof T]: T[K]
|
|
10
|
+
} & {}
|
|
11
|
+
|
|
12
|
+
export type IsNever<T> = [T] extends [never] ? true : false
|
|
13
|
+
|
|
14
|
+
type Files = File | FileList
|
|
15
|
+
|
|
16
|
+
// type Replace<RecordType, TargetType, GenericType> = {
|
|
17
|
+
// [K in keyof RecordType]: RecordType[K] extends TargetType
|
|
18
|
+
// ? GenericType
|
|
19
|
+
// : RecordType[K]
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
type ReplaceBlobWithFiles<in out RecordType extends Record<string, unknown>> = {
|
|
23
|
+
[K in keyof RecordType]: RecordType[K] extends Blob | Blob[]
|
|
24
|
+
? Files
|
|
25
|
+
: RecordType[K]
|
|
26
|
+
} & {}
|
|
27
|
+
|
|
28
|
+
type And<A extends boolean, B extends boolean> = A extends true
|
|
29
|
+
? B extends true
|
|
30
|
+
? true
|
|
31
|
+
: false
|
|
32
|
+
: false
|
|
33
|
+
|
|
34
|
+
type ReplaceGeneratorWithAsyncGenerator<
|
|
35
|
+
in out RecordType extends Record<string, unknown>
|
|
36
|
+
> = {
|
|
37
|
+
[K in keyof RecordType]: RecordType[K] extends Generator<
|
|
38
|
+
infer A,
|
|
39
|
+
infer B,
|
|
40
|
+
infer C
|
|
41
|
+
>
|
|
42
|
+
? And<Not<IsNever<A>>, void extends B ? true : false> extends true
|
|
43
|
+
? AsyncGenerator<A, B, C>
|
|
44
|
+
: And<IsNever<A>, void extends B ? false : true> extends true
|
|
45
|
+
? B
|
|
46
|
+
: AsyncGenerator<A, B, C> | B
|
|
47
|
+
: RecordType[K] extends AsyncGenerator<infer A, infer B, infer C>
|
|
48
|
+
? And<Not<IsNever<A>>, void extends B ? true : false> extends true
|
|
49
|
+
? AsyncGenerator<A, B, C>
|
|
50
|
+
: And<IsNever<A>, void extends B ? false : true> extends true
|
|
51
|
+
? B
|
|
52
|
+
: AsyncGenerator<A, B, C> | B
|
|
53
|
+
: RecordType[K]
|
|
54
|
+
} & {}
|
|
55
|
+
|
|
56
|
+
type MaybeArray<T> = T | T[]
|
|
57
|
+
type MaybePromise<T> = T | Promise<T>
|
|
58
|
+
|
|
59
|
+
export namespace Treaty {
|
|
60
|
+
interface TreatyParam {
|
|
61
|
+
fetch?: RequestInit
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type Create<
|
|
65
|
+
App extends Elysia<any, any, any, any, any, any, any, any>
|
|
66
|
+
> = App extends {
|
|
67
|
+
_routes: infer Schema extends Record<string, any>
|
|
68
|
+
}
|
|
69
|
+
? Prettify<Sign<Schema>>
|
|
70
|
+
: 'Please install Elysia before using Eden'
|
|
71
|
+
|
|
72
|
+
export type Sign<in out Route extends Record<string, any>> = {
|
|
73
|
+
[K in keyof Route as K extends `:${string}`
|
|
74
|
+
? never
|
|
75
|
+
: K]: K extends 'subscribe' // ? Websocket route
|
|
76
|
+
? (undefined extends Route['subscribe']['headers']
|
|
77
|
+
? { headers?: Record<string, unknown> }
|
|
78
|
+
: {
|
|
79
|
+
headers: Route['subscribe']['headers']
|
|
80
|
+
}) &
|
|
81
|
+
(undefined extends Route['subscribe']['query']
|
|
82
|
+
? { query?: Record<string, unknown> }
|
|
83
|
+
: {
|
|
84
|
+
query: Route['subscribe']['query']
|
|
85
|
+
}) extends infer Param
|
|
86
|
+
? {} extends Param
|
|
87
|
+
? (options?: Param) => EdenWS<Route['subscribe']>
|
|
88
|
+
: (options?: Param) => EdenWS<Route['subscribe']>
|
|
89
|
+
: never
|
|
90
|
+
: Route[K] extends {
|
|
91
|
+
body: infer Body
|
|
92
|
+
headers: infer Headers
|
|
93
|
+
params: any
|
|
94
|
+
query: infer Query
|
|
95
|
+
response: infer Response extends Record<number, unknown>
|
|
96
|
+
}
|
|
97
|
+
? (undefined extends Headers
|
|
98
|
+
? { headers?: Record<string, unknown> }
|
|
99
|
+
: {
|
|
100
|
+
headers: Headers
|
|
101
|
+
}) &
|
|
102
|
+
(undefined extends Query
|
|
103
|
+
? { query?: Record<string, unknown> }
|
|
104
|
+
: { query: Query }) extends infer Param
|
|
105
|
+
? {} extends Param
|
|
106
|
+
? undefined extends Body
|
|
107
|
+
? K extends 'get' | 'head'
|
|
108
|
+
? (
|
|
109
|
+
options?: Prettify<Param & TreatyParam>
|
|
110
|
+
) => Promise<
|
|
111
|
+
TreatyResponse<
|
|
112
|
+
ReplaceGeneratorWithAsyncGenerator<Response>
|
|
113
|
+
>
|
|
114
|
+
>
|
|
115
|
+
: (
|
|
116
|
+
body?: Body,
|
|
117
|
+
options?: Prettify<Param & TreatyParam>
|
|
118
|
+
) => Promise<
|
|
119
|
+
TreatyResponse<
|
|
120
|
+
ReplaceGeneratorWithAsyncGenerator<Response>
|
|
121
|
+
>
|
|
122
|
+
>
|
|
123
|
+
: (
|
|
124
|
+
body: Body extends Record<string, unknown>
|
|
125
|
+
? ReplaceBlobWithFiles<Body>
|
|
126
|
+
: Body,
|
|
127
|
+
options?: Prettify<Param & TreatyParam>
|
|
128
|
+
) => Promise<
|
|
129
|
+
TreatyResponse<
|
|
130
|
+
ReplaceGeneratorWithAsyncGenerator<Response>
|
|
131
|
+
>
|
|
132
|
+
>
|
|
133
|
+
: K extends 'get' | 'head'
|
|
134
|
+
? (
|
|
135
|
+
options: Prettify<Param & TreatyParam>
|
|
136
|
+
) => Promise<
|
|
137
|
+
TreatyResponse<
|
|
138
|
+
ReplaceGeneratorWithAsyncGenerator<Response>
|
|
139
|
+
>
|
|
140
|
+
>
|
|
141
|
+
: (
|
|
142
|
+
body: Body extends Record<string, unknown>
|
|
143
|
+
? ReplaceBlobWithFiles<Body>
|
|
144
|
+
: Body,
|
|
145
|
+
options: Prettify<Param & TreatyParam>
|
|
146
|
+
) => Promise<
|
|
147
|
+
TreatyResponse<
|
|
148
|
+
ReplaceGeneratorWithAsyncGenerator<Response>
|
|
149
|
+
>
|
|
150
|
+
>
|
|
151
|
+
: never
|
|
152
|
+
: CreateParams<Route[K]>
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type CreateParams<Route extends Record<string, any>> = Extract<
|
|
156
|
+
keyof Route,
|
|
157
|
+
`:${string}`
|
|
158
|
+
> extends infer Path extends string
|
|
159
|
+
? IsNever<Path> extends true
|
|
160
|
+
? Prettify<Sign<Route>>
|
|
161
|
+
: // ! DO NOT USE PRETTIFY ON THIS LINE, OTHERWISE FUNCTION CALLING WILL BE OMITTED
|
|
162
|
+
(((params: {
|
|
163
|
+
[param in Path extends `:${infer Param}`
|
|
164
|
+
? Param extends `${infer Param}?`
|
|
165
|
+
? Param
|
|
166
|
+
: Param
|
|
167
|
+
: never]: string | number
|
|
168
|
+
}) => Prettify<Sign<Route[Path]>> & CreateParams<Route[Path]>) &
|
|
169
|
+
Prettify<Sign<Route>>) &
|
|
170
|
+
(Path extends `:${string}?`
|
|
171
|
+
? CreateParams<Route[Path]>
|
|
172
|
+
: {})
|
|
173
|
+
: never
|
|
174
|
+
|
|
175
|
+
export interface Config {
|
|
176
|
+
fetch?: Omit<RequestInit, 'headers' | 'method'>
|
|
177
|
+
fetcher?: typeof fetch
|
|
178
|
+
headers?: MaybeArray<
|
|
179
|
+
| RequestInit['headers']
|
|
180
|
+
| ((
|
|
181
|
+
path: string,
|
|
182
|
+
options: RequestInit
|
|
183
|
+
) => RequestInit['headers'] | void)
|
|
184
|
+
>
|
|
185
|
+
onRequest?: MaybeArray<
|
|
186
|
+
(
|
|
187
|
+
path: string,
|
|
188
|
+
options: RequestInit
|
|
189
|
+
) => MaybePromise<RequestInit | void>
|
|
190
|
+
>
|
|
191
|
+
onResponse?: MaybeArray<(response: Response) => MaybePromise<unknown>>
|
|
192
|
+
keepDomain?: boolean
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// type UnwrapAwaited<T extends Record<number, unknown>> = {
|
|
196
|
+
// [K in keyof T]: Awaited<T[K]>
|
|
197
|
+
// }
|
|
198
|
+
|
|
199
|
+
export type TreatyResponse<Res extends Record<number, unknown>> =
|
|
200
|
+
| {
|
|
201
|
+
data: Res[200]
|
|
202
|
+
error: null
|
|
203
|
+
response: Response
|
|
204
|
+
status: number
|
|
205
|
+
headers: RequestInit['headers']
|
|
206
|
+
}
|
|
207
|
+
| {
|
|
208
|
+
data: null
|
|
209
|
+
error: Exclude<keyof Res, 200> extends never
|
|
210
|
+
? EdenFetchError<number, any>
|
|
211
|
+
: {
|
|
212
|
+
[Status in keyof Res]: EdenFetchError<
|
|
213
|
+
Status,
|
|
214
|
+
Res[Status]
|
|
215
|
+
>
|
|
216
|
+
}[Exclude<keyof Res, 200>]
|
|
217
|
+
response: Response
|
|
218
|
+
status: number
|
|
219
|
+
headers: RequestInit['headers']
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface OnMessage<Data = unknown> extends MessageEvent {
|
|
223
|
+
data: Data
|
|
224
|
+
rawData: MessageEvent['data']
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export type WSEvent<
|
|
228
|
+
K extends keyof WebSocketEventMap,
|
|
229
|
+
Data = unknown
|
|
230
|
+
> = K extends 'message' ? OnMessage<Data> : WebSocketEventMap[K]
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export type Not<T> = T extends true ? false : true
|
package/src/client/ws.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { InputSchema } from '../elysia-fork/types'
|
|
2
|
+
import type { Treaty } from './types'
|
|
3
|
+
import { parseStringifiedValue } from './utils'
|
|
4
|
+
|
|
5
|
+
export class EdenWS<in out Schema extends InputSchema<any> = {}> {
|
|
6
|
+
ws: WebSocket
|
|
7
|
+
|
|
8
|
+
constructor(public url: string) {
|
|
9
|
+
this.ws = new WebSocket(url)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
send(data: Schema['body'] | Schema['body'][]) {
|
|
13
|
+
if (Array.isArray(data)) {
|
|
14
|
+
data.forEach((datum) => this.send(datum))
|
|
15
|
+
|
|
16
|
+
return this
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.ws.send(
|
|
20
|
+
typeof data === 'object' ? JSON.stringify(data) : data.toString()
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return this
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
on<K extends keyof WebSocketEventMap>(
|
|
27
|
+
type: K,
|
|
28
|
+
listener: (event: Treaty.WSEvent<K, Schema['response']>) => void,
|
|
29
|
+
options?: boolean | AddEventListenerOptions
|
|
30
|
+
) {
|
|
31
|
+
return this.addEventListener(type, listener, options)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
off<K extends keyof WebSocketEventMap>(
|
|
35
|
+
type: K,
|
|
36
|
+
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
|
|
37
|
+
options?: boolean | EventListenerOptions
|
|
38
|
+
) {
|
|
39
|
+
this.ws.removeEventListener(type, listener, options)
|
|
40
|
+
|
|
41
|
+
return this
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
subscribe(
|
|
45
|
+
onMessage: (
|
|
46
|
+
event: Treaty.WSEvent<'message', Schema['response']>
|
|
47
|
+
) => void,
|
|
48
|
+
options?: boolean | AddEventListenerOptions
|
|
49
|
+
) {
|
|
50
|
+
return this.addEventListener('message', onMessage, options)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
addEventListener<K extends keyof WebSocketEventMap>(
|
|
54
|
+
type: K,
|
|
55
|
+
listener: (event: Treaty.WSEvent<K, Schema['response']>) => void,
|
|
56
|
+
options?: boolean | AddEventListenerOptions
|
|
57
|
+
) {
|
|
58
|
+
this.ws.addEventListener(
|
|
59
|
+
type,
|
|
60
|
+
(ws) => {
|
|
61
|
+
if (type === 'message') {
|
|
62
|
+
const data = parseMessageEvent(ws as MessageEvent)
|
|
63
|
+
|
|
64
|
+
listener({
|
|
65
|
+
...ws,
|
|
66
|
+
data
|
|
67
|
+
} as any)
|
|
68
|
+
} else listener(ws as any)
|
|
69
|
+
},
|
|
70
|
+
options
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
removeEventListener<K extends keyof WebSocketEventMap>(
|
|
77
|
+
type: K,
|
|
78
|
+
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
|
|
79
|
+
options?: boolean | EventListenerOptions
|
|
80
|
+
) {
|
|
81
|
+
this.off(type, listener, options)
|
|
82
|
+
|
|
83
|
+
return this
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
close() {
|
|
87
|
+
this.ws.close()
|
|
88
|
+
|
|
89
|
+
return this
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const parseMessageEvent = (event: MessageEvent) => {
|
|
94
|
+
const messageString = event.data.toString()
|
|
95
|
+
|
|
96
|
+
return messageString === 'null'
|
|
97
|
+
? null
|
|
98
|
+
: parseStringifiedValue(messageString)
|
|
99
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { createSpiceflowClient } from './client'
|
|
2
|
+
import { Elysia, t } from './spiceflow'
|
|
3
|
+
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
const randomObject = {
|
|
7
|
+
a: 'a',
|
|
8
|
+
b: 2,
|
|
9
|
+
c: true,
|
|
10
|
+
d: false,
|
|
11
|
+
e: null,
|
|
12
|
+
f: new Date(0)
|
|
13
|
+
}
|
|
14
|
+
const randomArray = [
|
|
15
|
+
'a',
|
|
16
|
+
2,
|
|
17
|
+
true,
|
|
18
|
+
false,
|
|
19
|
+
null,
|
|
20
|
+
new Date(0),
|
|
21
|
+
{ a: 'a', b: 2, c: true, d: false, e: null, f: new Date(0) }
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const app = new Elysia()
|
|
25
|
+
.get('/', () => 'a')
|
|
26
|
+
.post('/', () => 'a')
|
|
27
|
+
.get('/number', () => 1)
|
|
28
|
+
.get('/true', () => true)
|
|
29
|
+
.get('/false', () => false)
|
|
30
|
+
.post('/array', ({ body }) => body, {
|
|
31
|
+
body: t.Array(t.String())
|
|
32
|
+
})
|
|
33
|
+
.post('/mirror', ({ body }) => body)
|
|
34
|
+
.post('/body', ({ body }) => body, {
|
|
35
|
+
body: t.String()
|
|
36
|
+
})
|
|
37
|
+
.delete('/empty', ({ body }) => ({ body: body ?? null }))
|
|
38
|
+
.post('/deep/nested/mirror', ({ body }) => body, {
|
|
39
|
+
body: t.Object({
|
|
40
|
+
username: t.String(),
|
|
41
|
+
password: t.String()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
.use(new Elysia({ basePath: '/nested' }).get('/data', ({ params }) => 'hi'))
|
|
46
|
+
// .get('/error', ({ error }) => error("I'm a teapot", 'Kirifuji Nagisa'), {
|
|
47
|
+
// response: {
|
|
48
|
+
// 200: t.Void(),
|
|
49
|
+
// 418: t.Literal('Kirifuji Nagisa'),
|
|
50
|
+
// 420: t.Literal('Snoop Dogg')
|
|
51
|
+
// }
|
|
52
|
+
// })
|
|
53
|
+
.get(
|
|
54
|
+
'/validationError',
|
|
55
|
+
// @ts-expect-error
|
|
56
|
+
() => {
|
|
57
|
+
return 'this errors because validation is wrong'
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
response: {
|
|
61
|
+
200: t.Object({
|
|
62
|
+
x: t.String()
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
.post('/date', ({ body: { date } }) => date, {
|
|
69
|
+
body: t.Object({
|
|
70
|
+
date: t.Date()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
.get('/dateObject', () => ({ date: new Date() }))
|
|
74
|
+
.get('/redirect', ({ redirect }) => redirect('http://localhost:8083/true'))
|
|
75
|
+
.post(
|
|
76
|
+
'/redirect',
|
|
77
|
+
({ redirect }) => redirect('http://localhost:8083/true'),
|
|
78
|
+
{
|
|
79
|
+
body: t.Object({
|
|
80
|
+
username: t.String()
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
// .get('/formdata', () => ({
|
|
85
|
+
// image: Bun.file('./test/kyuukurarin.mp4')
|
|
86
|
+
// }))
|
|
87
|
+
|
|
88
|
+
.get('/stream', function* stream() {
|
|
89
|
+
yield 'a'
|
|
90
|
+
yield 'b'
|
|
91
|
+
yield 'c'
|
|
92
|
+
})
|
|
93
|
+
.get('/stream-async', async function* stream() {
|
|
94
|
+
yield 'a'
|
|
95
|
+
yield 'b'
|
|
96
|
+
yield 'c'
|
|
97
|
+
})
|
|
98
|
+
.get('/stream-return', function* stream() {
|
|
99
|
+
return 'a'
|
|
100
|
+
})
|
|
101
|
+
.get('/stream-return-async', function* stream() {
|
|
102
|
+
return 'a'
|
|
103
|
+
})
|
|
104
|
+
.get('/id/:id?', ({ params: { id = 'unknown' } }) => id)
|
|
105
|
+
|
|
106
|
+
const client = createSpiceflowClient(app)
|
|
107
|
+
|
|
108
|
+
describe('client', () => {
|
|
109
|
+
it('get index', async () => {
|
|
110
|
+
const { data, error } = await client.index.get()
|
|
111
|
+
|
|
112
|
+
expect(data).toBe('a')
|
|
113
|
+
expect(error).toBeNull()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('post index', async () => {
|
|
117
|
+
const { data, error } = await client.index.post()
|
|
118
|
+
|
|
119
|
+
expect(data).toBe('a')
|
|
120
|
+
expect(error).toBeNull()
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('parse number', async () => {
|
|
124
|
+
const { data } = await client.number.get()
|
|
125
|
+
|
|
126
|
+
expect(data).toEqual(1)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('parse true', async () => {
|
|
130
|
+
const { data } = await client.true.get()
|
|
131
|
+
|
|
132
|
+
expect(data).toEqual(true)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('parse false', async () => {
|
|
136
|
+
const { data } = await client.false.get()
|
|
137
|
+
|
|
138
|
+
expect(data).toEqual(false)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it.todo('parse object with date', async () => {
|
|
142
|
+
const { data } = await client.dateObject.get()
|
|
143
|
+
|
|
144
|
+
expect(data?.date).toBeInstanceOf(Date)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('post array', async () => {
|
|
148
|
+
const { data } = await client.array.post(['a', 'b'])
|
|
149
|
+
|
|
150
|
+
expect(data).toEqual(['a', 'b'])
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('post body', async () => {
|
|
154
|
+
const { data } = await client.body.post('a')
|
|
155
|
+
|
|
156
|
+
expect(data).toEqual('a')
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('post mirror', async () => {
|
|
160
|
+
const body = { username: 'A', password: 'B' }
|
|
161
|
+
|
|
162
|
+
const { data } = await client.mirror.post(body)
|
|
163
|
+
|
|
164
|
+
expect(data).toEqual(body)
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('delete empty', async () => {
|
|
168
|
+
const { data } = await client.empty.delete()
|
|
169
|
+
|
|
170
|
+
expect(data).toEqual({ body: null })
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('post deep nested mirror', async () => {
|
|
174
|
+
const body = { username: 'A', password: 'B' }
|
|
175
|
+
|
|
176
|
+
const { data } = await client.deep.nested.mirror.post(body)
|
|
177
|
+
|
|
178
|
+
expect(data).toEqual(body)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('get nested data', async () => {
|
|
182
|
+
const { data } = await client.nested.data.get()
|
|
183
|
+
|
|
184
|
+
expect(data).toEqual('hi')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('stream ', async () => {
|
|
188
|
+
const { data } = await client.stream.get()
|
|
189
|
+
let all = ''
|
|
190
|
+
for await (const chunk of data!) {
|
|
191
|
+
// console.log(chunk)
|
|
192
|
+
all += chunk + '-'
|
|
193
|
+
}
|
|
194
|
+
expect(all).toEqual('a-b-c-')
|
|
195
|
+
})
|
|
196
|
+
it('stream async', async () => {
|
|
197
|
+
const { data } = await client['stream-async'].get()
|
|
198
|
+
let all = ''
|
|
199
|
+
for await (const chunk of data!) {
|
|
200
|
+
// console.log(chunk)
|
|
201
|
+
all += chunk + '-'
|
|
202
|
+
}
|
|
203
|
+
expect(all).toEqual('a-b-c-')
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('stream return', async () => {
|
|
207
|
+
const { data } = await client['stream-return'].get()
|
|
208
|
+
expect(data).toEqual('a')
|
|
209
|
+
})
|
|
210
|
+
it('stream return async', async () => {
|
|
211
|
+
const { data } = await client['stream-return-async'].get()
|
|
212
|
+
// console.log(data)
|
|
213
|
+
expect(data).toEqual('a')
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// it('handle error', async () => {
|
|
217
|
+
// const { data, error } = await client.error.get()
|
|
218
|
+
|
|
219
|
+
// let value
|
|
220
|
+
|
|
221
|
+
// if (error)
|
|
222
|
+
// switch (error.status) {
|
|
223
|
+
// case 418:
|
|
224
|
+
// value = error.value
|
|
225
|
+
// break
|
|
226
|
+
|
|
227
|
+
// case 420:
|
|
228
|
+
// value = error.value
|
|
229
|
+
// break
|
|
230
|
+
// }
|
|
231
|
+
|
|
232
|
+
// expect(data).toBeNull()
|
|
233
|
+
// expect(value).toEqual('Kirifuji Nagisa')
|
|
234
|
+
// })
|
|
235
|
+
})
|