spiceflow 1.0.0 → 1.0.2
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 +147 -0
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +5 -5
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +4 -5
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/ws.d.ts +4 -4
- package/dist/client/ws.d.ts.map +1 -1
- package/dist/client/ws.js.map +1 -1
- package/dist/client.test.js +9 -8
- package/dist/client.test.js.map +1 -1
- package/dist/elysia-fork/error.d.ts +5 -65
- package/dist/elysia-fork/error.d.ts.map +1 -1
- package/dist/elysia-fork/error.js +2 -2
- package/dist/elysia-fork/error.js.map +1 -1
- package/dist/elysia-fork/types.d.ts +27 -116
- package/dist/elysia-fork/types.d.ts.map +1 -1
- package/dist/elysia-fork/types.js +1 -2
- package/dist/elysia-fork/types.js.map +1 -1
- package/dist/elysia-fork/utils.d.ts +1 -62
- package/dist/elysia-fork/utils.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi.d.ts +68 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +250 -0
- package/dist/openapi.js.map +1 -0
- package/dist/spiceflow.d.ts +48 -52
- package/dist/spiceflow.d.ts.map +1 -1
- package/dist/spiceflow.js +148 -87
- package/dist/spiceflow.js.map +1 -1
- package/dist/spiceflow.test.js +80 -43
- package/dist/spiceflow.test.js.map +1 -1
- package/dist/stream.test.js +14 -14
- package/dist/stream.test.js.map +1 -1
- package/dist/zod.test.d.ts +2 -0
- package/dist/zod.test.d.ts.map +1 -0
- package/dist/zod.test.js +59 -0
- package/dist/zod.test.js.map +1 -0
- package/package.json +7 -4
- package/src/client/index.ts +10 -8
- package/src/client/types.ts +4 -4
- package/src/client/ws.ts +4 -4
- package/src/client.test.ts +9 -8
- package/src/elysia-fork/context.ts +2 -2
- package/src/elysia-fork/error.ts +3 -3
- package/src/elysia-fork/types.ts +108 -284
- package/src/index.ts +2 -0
- package/src/openapi.ts +426 -0
- package/src/spiceflow.test.ts +117 -64
- package/src/spiceflow.ts +261 -179
- package/src/stream.test.ts +14 -14
- package/src/zod.test.ts +71 -0
package/src/spiceflow.test.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
import { test, describe, expect } from 'vitest'
|
|
2
2
|
import { Type } from '@sinclair/typebox'
|
|
3
|
-
import {
|
|
3
|
+
import { bfs, Spiceflow } from './spiceflow'
|
|
4
4
|
|
|
5
5
|
test('works', async () => {
|
|
6
|
-
const res = await new
|
|
6
|
+
const res = await new Spiceflow()
|
|
7
7
|
.post('/xxx', () => 'hi')
|
|
8
8
|
.handle(new Request('http://localhost/xxx', { method: 'POST' }))
|
|
9
9
|
expect(res.status).toBe(200)
|
|
10
|
-
expect(await res.
|
|
10
|
+
expect(await res.json()).toEqual('hi')
|
|
11
11
|
})
|
|
12
12
|
test('dynamic route', async () => {
|
|
13
|
-
const res = await new
|
|
13
|
+
const res = await new Spiceflow()
|
|
14
14
|
.post('/ids/:id', () => 'hi')
|
|
15
15
|
.handle(new Request('http://localhost/ids/xxx', { method: 'POST' }))
|
|
16
16
|
expect(res.status).toBe(200)
|
|
17
|
-
expect(await res.
|
|
17
|
+
expect(await res.json()).toEqual('hi')
|
|
18
18
|
})
|
|
19
19
|
test('GET dynamic route', async () => {
|
|
20
|
-
const res = await new
|
|
20
|
+
const res = await new Spiceflow()
|
|
21
21
|
.get('/ids/:id', () => 'hi')
|
|
22
22
|
.handle(new Request('http://localhost/ids/xxx', { method: 'GET' }))
|
|
23
23
|
expect(res.status).toBe(200)
|
|
24
|
-
expect(await res.
|
|
24
|
+
expect(await res.json()).toEqual('hi')
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
test('missing route is not found', async () => {
|
|
28
|
-
const res = await new
|
|
28
|
+
const res = await new Spiceflow()
|
|
29
29
|
.get('/ids/:id', () => 'hi')
|
|
30
30
|
.handle(new Request('http://localhost/zxxx', { method: 'GET' }))
|
|
31
31
|
expect(res.status).toBe(404)
|
|
32
32
|
})
|
|
33
33
|
test('state works', async () => {
|
|
34
|
-
const res = await new
|
|
34
|
+
const res = await new Spiceflow()
|
|
35
35
|
.state('id', '')
|
|
36
36
|
.onRequest(({ store, request }) => {
|
|
37
37
|
store.id = 'xxx'
|
|
@@ -45,7 +45,7 @@ test('state works', async () => {
|
|
|
45
45
|
|
|
46
46
|
test('body is parsed as json', async () => {
|
|
47
47
|
let body
|
|
48
|
-
const res = await new
|
|
48
|
+
const res = await new Spiceflow()
|
|
49
49
|
.state('id', '')
|
|
50
50
|
|
|
51
51
|
.post('/post', (c) => {
|
|
@@ -57,17 +57,17 @@ test('body is parsed as json', async () => {
|
|
|
57
57
|
new Request('http://localhost/post', {
|
|
58
58
|
method: 'POST',
|
|
59
59
|
headers: {
|
|
60
|
-
'content-type': 'application/json'
|
|
60
|
+
'content-type': 'application/json',
|
|
61
61
|
},
|
|
62
|
-
body: JSON.stringify({ name: 'John' })
|
|
63
|
-
})
|
|
62
|
+
body: JSON.stringify({ name: 'John' }),
|
|
63
|
+
}),
|
|
64
64
|
)
|
|
65
65
|
expect(res.status).toBe(200)
|
|
66
|
-
expect(await res.
|
|
66
|
+
expect(await res.json()).toEqual({ name: 'John' })
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
test('validate body works, request success', async () => {
|
|
70
|
-
const res = await new
|
|
70
|
+
const res = await new Spiceflow()
|
|
71
71
|
|
|
72
72
|
.post(
|
|
73
73
|
'/post',
|
|
@@ -78,25 +78,25 @@ test('validate body works, request success', async () => {
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
body: Type.Object({
|
|
81
|
-
name: Type.String()
|
|
82
|
-
})
|
|
83
|
-
}
|
|
81
|
+
name: Type.String(),
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
84
|
)
|
|
85
85
|
.handle(
|
|
86
86
|
new Request('http://localhost/post', {
|
|
87
87
|
method: 'POST',
|
|
88
88
|
headers: {
|
|
89
|
-
'content-type': 'application/json'
|
|
89
|
+
'content-type': 'application/json',
|
|
90
90
|
},
|
|
91
|
-
body: JSON.stringify({ name: 'John' })
|
|
92
|
-
})
|
|
91
|
+
body: JSON.stringify({ name: 'John' }),
|
|
92
|
+
}),
|
|
93
93
|
)
|
|
94
94
|
expect(res.status).toBe(200)
|
|
95
95
|
expect(await res.text()).toMatchInlineSnapshot(`""ok""`)
|
|
96
96
|
})
|
|
97
97
|
|
|
98
98
|
test('validate body works, request fails', async () => {
|
|
99
|
-
const res = await new
|
|
99
|
+
const res = await new Spiceflow()
|
|
100
100
|
|
|
101
101
|
.post(
|
|
102
102
|
'/post',
|
|
@@ -107,27 +107,27 @@ test('validate body works, request fails', async () => {
|
|
|
107
107
|
{
|
|
108
108
|
body: Type.Object({
|
|
109
109
|
name: Type.String(),
|
|
110
|
-
requiredField: Type.String()
|
|
111
|
-
})
|
|
112
|
-
}
|
|
110
|
+
requiredField: Type.String(),
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
113
|
)
|
|
114
114
|
.handle(
|
|
115
115
|
new Request('http://localhost/post', {
|
|
116
116
|
method: 'POST',
|
|
117
117
|
headers: {
|
|
118
|
-
'content-type': 'application/json'
|
|
118
|
+
'content-type': 'application/json',
|
|
119
119
|
},
|
|
120
|
-
body: JSON.stringify({ name: 'John' })
|
|
121
|
-
})
|
|
120
|
+
body: JSON.stringify({ name: 'John' }),
|
|
121
|
+
}),
|
|
122
122
|
)
|
|
123
123
|
expect(res.status).toBe(400)
|
|
124
124
|
expect(await res.text()).toMatchInlineSnapshot(
|
|
125
|
-
`"data must have required property 'requiredField'"
|
|
125
|
+
`"data must have required property 'requiredField'"`,
|
|
126
126
|
)
|
|
127
127
|
})
|
|
128
128
|
|
|
129
129
|
test('run onRequest', async () => {
|
|
130
|
-
const res = await new
|
|
130
|
+
const res = await new Spiceflow()
|
|
131
131
|
.onRequest(({ request }) => {
|
|
132
132
|
expect(request.method).toBe('HEAD')
|
|
133
133
|
return new Response('ok', { status: 401 })
|
|
@@ -143,7 +143,7 @@ test('run onRequest', async () => {
|
|
|
143
143
|
})
|
|
144
144
|
|
|
145
145
|
test('run onRequest', async () => {
|
|
146
|
-
const res = await new
|
|
146
|
+
const res = await new Spiceflow()
|
|
147
147
|
.onRequest(({ request }) => {
|
|
148
148
|
expect(request.method).toBe('HEAD')
|
|
149
149
|
return new Response('ok', { status: 401 })
|
|
@@ -159,89 +159,142 @@ test('run onRequest', async () => {
|
|
|
159
159
|
})
|
|
160
160
|
|
|
161
161
|
test('basPath works', async () => {
|
|
162
|
-
const res = await new
|
|
162
|
+
const res = await new Spiceflow({ basePath: '/one' })
|
|
163
163
|
.get('/ids/:id', () => 'hi')
|
|
164
164
|
.handle(new Request('http://localhost/one/ids/xxx', { method: 'GET' }))
|
|
165
165
|
expect(res.status).toBe(200)
|
|
166
|
-
expect(await res.
|
|
166
|
+
expect(await res.json()).toEqual('hi')
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('basPath works with use', async () => {
|
|
170
|
+
let app = new Spiceflow({ basePath: '/one' }).use(
|
|
171
|
+
new Spiceflow({})
|
|
172
|
+
.get('/two', () => 'hi')
|
|
173
|
+
.use(
|
|
174
|
+
new Spiceflow({ basePath: '/three' }).get('/four', () => 'hi'),
|
|
175
|
+
),
|
|
176
|
+
)
|
|
177
|
+
{
|
|
178
|
+
const res = await app.handle(
|
|
179
|
+
new Request('http://localhost/one/two', { method: 'GET' }),
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
expect(res.status).toBe(200)
|
|
183
|
+
expect(await res.json()).toEqual('hi')
|
|
184
|
+
}
|
|
185
|
+
{
|
|
186
|
+
const res = await app.handle(
|
|
187
|
+
new Request('http://localhost/one/three/four', { method: 'GET' }),
|
|
188
|
+
)
|
|
189
|
+
expect(res.status).toBe(200)
|
|
190
|
+
expect(await res.json()).toEqual('hi')
|
|
191
|
+
}
|
|
167
192
|
})
|
|
168
193
|
|
|
194
|
+
test('getRouteAndParents', async () => {
|
|
195
|
+
let app = new Spiceflow({ basePath: '/one' })
|
|
196
|
+
.get('/ids/:id', () => 'hi')
|
|
197
|
+
.use(
|
|
198
|
+
new Spiceflow({ basePath: '/two' }).use(
|
|
199
|
+
new Spiceflow({ basePath: '/three' }).get('/four', () => 'hi'),
|
|
200
|
+
),
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
let routers = bfs(app['routerTree'])
|
|
204
|
+
let last = routers[routers.length - 1]
|
|
205
|
+
|
|
206
|
+
expect(app['getRouteAndParents'](last).map((x) => x.prefix))
|
|
207
|
+
.toMatchInlineSnapshot(`
|
|
208
|
+
[
|
|
209
|
+
"/three",
|
|
210
|
+
"/two",
|
|
211
|
+
"/one",
|
|
212
|
+
]
|
|
213
|
+
`)
|
|
214
|
+
})
|
|
169
215
|
test('use with 2 basPath works', async () => {
|
|
170
216
|
let oneOnReq = false
|
|
171
217
|
let twoOnReq = false
|
|
172
|
-
|
|
218
|
+
let onReqCalled: string[] = []
|
|
219
|
+
const app = await new Spiceflow()
|
|
220
|
+
.onRequest(({ request }) => {
|
|
221
|
+
onReqCalled.push('root')
|
|
222
|
+
})
|
|
173
223
|
.use(
|
|
174
|
-
new
|
|
224
|
+
new Spiceflow({ basePath: '/one' })
|
|
175
225
|
.onRequest(({ request }) => {
|
|
176
226
|
oneOnReq = true
|
|
227
|
+
onReqCalled.push('one')
|
|
177
228
|
})
|
|
178
|
-
.get('/ids/:id', ({ params }) => params.id)
|
|
229
|
+
.get('/ids/:id', ({ params }) => params.id),
|
|
179
230
|
)
|
|
180
231
|
.use(
|
|
181
|
-
new
|
|
232
|
+
new Spiceflow({ basePath: '/two' })
|
|
182
233
|
.onRequest((c) => {
|
|
183
234
|
twoOnReq = true
|
|
235
|
+
onReqCalled.push('two')
|
|
184
236
|
})
|
|
185
|
-
.get('/ids/:id', ({ params }) => params.id)
|
|
237
|
+
.get('/ids/:id', ({ params }) => params.id),
|
|
186
238
|
)
|
|
187
239
|
|
|
188
240
|
{
|
|
189
241
|
const res = await app.handle(
|
|
190
|
-
new Request('http://localhost/one/ids/one')
|
|
242
|
+
new Request('http://localhost/one/ids/one'),
|
|
191
243
|
)
|
|
192
244
|
expect(res.status).toBe(200)
|
|
193
245
|
|
|
194
|
-
expect(await res.
|
|
246
|
+
expect(await res.json()).toEqual('one')
|
|
195
247
|
}
|
|
248
|
+
expect(onReqCalled).toEqual(['root', 'one'])
|
|
196
249
|
{
|
|
197
250
|
const res = await app.handle(
|
|
198
|
-
new Request('http://localhost/two/ids/two')
|
|
251
|
+
new Request('http://localhost/two/ids/two'),
|
|
199
252
|
)
|
|
200
253
|
expect(res.status).toBe(200)
|
|
201
254
|
|
|
202
|
-
expect(await res.
|
|
255
|
+
expect(await res.json()).toEqual('two')
|
|
203
256
|
}
|
|
204
257
|
expect(oneOnReq).toBe(true)
|
|
205
258
|
expect(twoOnReq).toBe(true)
|
|
206
259
|
})
|
|
207
260
|
|
|
208
261
|
test('use with nested basPath works', async () => {
|
|
209
|
-
const app = await new
|
|
262
|
+
const app = await new Spiceflow({ basePath: '/zero' })
|
|
210
263
|
.use(
|
|
211
|
-
new
|
|
264
|
+
new Spiceflow({ basePath: '/one' }).get(
|
|
212
265
|
'/ids/:id',
|
|
213
|
-
({ params }) => params.id
|
|
214
|
-
)
|
|
266
|
+
({ params }) => params.id,
|
|
267
|
+
),
|
|
215
268
|
)
|
|
216
269
|
.use(
|
|
217
|
-
new
|
|
218
|
-
new
|
|
270
|
+
new Spiceflow({ basePath: '/two' }).use(
|
|
271
|
+
new Spiceflow({ basePath: '/nested' }).get(
|
|
219
272
|
'/ids/:id',
|
|
220
|
-
({ params }) => params.id
|
|
221
|
-
)
|
|
222
|
-
)
|
|
273
|
+
({ params }) => params.id,
|
|
274
|
+
),
|
|
275
|
+
),
|
|
223
276
|
)
|
|
224
277
|
{
|
|
225
278
|
const res = await app.handle(
|
|
226
|
-
new Request('http://localhost/zero/one/ids/one')
|
|
279
|
+
new Request('http://localhost/zero/one/ids/one'),
|
|
227
280
|
)
|
|
228
281
|
expect(res.status).toBe(200)
|
|
229
|
-
expect(await res.
|
|
282
|
+
expect(await res.json()).toEqual('one')
|
|
230
283
|
}
|
|
231
284
|
|
|
232
285
|
{
|
|
233
286
|
const res = await app.handle(
|
|
234
|
-
new Request('http://localhost/zero/two/nested/ids/nested')
|
|
287
|
+
new Request('http://localhost/zero/two/nested/ids/nested'),
|
|
235
288
|
)
|
|
236
289
|
expect(res.status).toBe(200)
|
|
237
|
-
expect(await res.
|
|
290
|
+
expect(await res.json()).toEqual('nested')
|
|
238
291
|
}
|
|
239
292
|
})
|
|
240
293
|
|
|
241
294
|
test('errors inside basPath works', async () => {
|
|
242
295
|
let onErrorTriggered = [] as string[]
|
|
243
296
|
let onReqTriggered = [] as string[]
|
|
244
|
-
const app = await new
|
|
297
|
+
const app = await new Spiceflow({ basePath: '/zero' })
|
|
245
298
|
.onError(({ error }) => {
|
|
246
299
|
onErrorTriggered.push('root')
|
|
247
300
|
// return new Response('root', { status: 500 })
|
|
@@ -252,7 +305,7 @@ test('errors inside basPath works', async () => {
|
|
|
252
305
|
})
|
|
253
306
|
|
|
254
307
|
.use(
|
|
255
|
-
new
|
|
308
|
+
new Spiceflow({ basePath: '/two' })
|
|
256
309
|
.onError(({ error }) => {
|
|
257
310
|
onErrorTriggered.push('two')
|
|
258
311
|
// return new Response('two', { status: 500 })
|
|
@@ -262,7 +315,7 @@ test('errors inside basPath works', async () => {
|
|
|
262
315
|
// return new Response('two', { status: 500 })
|
|
263
316
|
})
|
|
264
317
|
.use(
|
|
265
|
-
new
|
|
318
|
+
new Spiceflow({ basePath: '/nested' })
|
|
266
319
|
.onError(({ error }) => {
|
|
267
320
|
onErrorTriggered.push('nested')
|
|
268
321
|
// return new Response('nested', { status: 500 })
|
|
@@ -273,18 +326,18 @@ test('errors inside basPath works', async () => {
|
|
|
273
326
|
})
|
|
274
327
|
.get('/ids/:id', ({ params }) => {
|
|
275
328
|
throw new Error('error message')
|
|
276
|
-
})
|
|
277
|
-
)
|
|
329
|
+
}),
|
|
330
|
+
),
|
|
278
331
|
)
|
|
279
332
|
|
|
280
333
|
{
|
|
281
334
|
const res = await app.handle(
|
|
282
|
-
new Request('http://localhost/zero/two/nested/ids/nested')
|
|
335
|
+
new Request('http://localhost/zero/two/nested/ids/nested'),
|
|
283
336
|
)
|
|
284
|
-
expect(onErrorTriggered).toEqual(['
|
|
285
|
-
expect(onReqTriggered).toEqual(['
|
|
337
|
+
expect(onErrorTriggered).toEqual(['root', 'two', 'nested'])
|
|
338
|
+
expect(onReqTriggered).toEqual(['root', 'two', 'nested'])
|
|
286
339
|
expect(res.status).toBe(500)
|
|
287
340
|
expect(await res.text()).toBe('error message')
|
|
288
|
-
// expect(await res.
|
|
341
|
+
// expect(await res.json()).toEqual('nested'))
|
|
289
342
|
}
|
|
290
343
|
})
|