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.
Files changed (56) hide show
  1. package/README.md +147 -0
  2. package/dist/client/index.d.ts +4 -3
  3. package/dist/client/index.d.ts.map +1 -1
  4. package/dist/client/index.js +5 -5
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/client/types.d.ts +4 -5
  7. package/dist/client/types.d.ts.map +1 -1
  8. package/dist/client/ws.d.ts +4 -4
  9. package/dist/client/ws.d.ts.map +1 -1
  10. package/dist/client/ws.js.map +1 -1
  11. package/dist/client.test.js +9 -8
  12. package/dist/client.test.js.map +1 -1
  13. package/dist/elysia-fork/error.d.ts +5 -65
  14. package/dist/elysia-fork/error.d.ts.map +1 -1
  15. package/dist/elysia-fork/error.js +2 -2
  16. package/dist/elysia-fork/error.js.map +1 -1
  17. package/dist/elysia-fork/types.d.ts +27 -116
  18. package/dist/elysia-fork/types.d.ts.map +1 -1
  19. package/dist/elysia-fork/types.js +1 -2
  20. package/dist/elysia-fork/types.js.map +1 -1
  21. package/dist/elysia-fork/utils.d.ts +1 -62
  22. package/dist/elysia-fork/utils.d.ts.map +1 -1
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +2 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/openapi.d.ts +68 -0
  28. package/dist/openapi.d.ts.map +1 -0
  29. package/dist/openapi.js +250 -0
  30. package/dist/openapi.js.map +1 -0
  31. package/dist/spiceflow.d.ts +48 -52
  32. package/dist/spiceflow.d.ts.map +1 -1
  33. package/dist/spiceflow.js +148 -87
  34. package/dist/spiceflow.js.map +1 -1
  35. package/dist/spiceflow.test.js +80 -43
  36. package/dist/spiceflow.test.js.map +1 -1
  37. package/dist/stream.test.js +14 -14
  38. package/dist/stream.test.js.map +1 -1
  39. package/dist/zod.test.d.ts +2 -0
  40. package/dist/zod.test.d.ts.map +1 -0
  41. package/dist/zod.test.js +59 -0
  42. package/dist/zod.test.js.map +1 -0
  43. package/package.json +7 -4
  44. package/src/client/index.ts +10 -8
  45. package/src/client/types.ts +4 -4
  46. package/src/client/ws.ts +4 -4
  47. package/src/client.test.ts +9 -8
  48. package/src/elysia-fork/context.ts +2 -2
  49. package/src/elysia-fork/error.ts +3 -3
  50. package/src/elysia-fork/types.ts +108 -284
  51. package/src/index.ts +2 -0
  52. package/src/openapi.ts +426 -0
  53. package/src/spiceflow.test.ts +117 -64
  54. package/src/spiceflow.ts +261 -179
  55. package/src/stream.test.ts +14 -14
  56. package/src/zod.test.ts +71 -0
@@ -1,37 +1,37 @@
1
1
  import { test, describe, expect } from 'vitest'
2
2
  import { Type } from '@sinclair/typebox'
3
- import { Elysia } from './spiceflow'
3
+ import { bfs, Spiceflow } from './spiceflow'
4
4
 
5
5
  test('works', async () => {
6
- const res = await new Elysia()
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.text()).toBe(JSON.stringify('hi'))
10
+ expect(await res.json()).toEqual('hi')
11
11
  })
12
12
  test('dynamic route', async () => {
13
- const res = await new Elysia()
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.text()).toBe(JSON.stringify('hi'))
17
+ expect(await res.json()).toEqual('hi')
18
18
  })
19
19
  test('GET dynamic route', async () => {
20
- const res = await new Elysia()
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.text()).toBe(JSON.stringify('hi'))
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 Elysia()
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 Elysia()
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 Elysia()
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.text()).toBe(JSON.stringify({ name: 'John' }))
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 Elysia()
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 Elysia()
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 Elysia()
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 Elysia()
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 Elysia({ basePath: '/one' })
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.text()).toBe(JSON.stringify('hi'))
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
- const app = await new Elysia()
218
+ let onReqCalled: string[] = []
219
+ const app = await new Spiceflow()
220
+ .onRequest(({ request }) => {
221
+ onReqCalled.push('root')
222
+ })
173
223
  .use(
174
- new Elysia({ basePath: '/one' })
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 Elysia({ basePath: '/two' })
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.text()).toBe(JSON.stringify('one'))
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.text()).toBe(JSON.stringify('two'))
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 Elysia({ basePath: '/zero' })
262
+ const app = await new Spiceflow({ basePath: '/zero' })
210
263
  .use(
211
- new Elysia({ basePath: '/one' }).get(
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 Elysia({ basePath: '/two' }).use(
218
- new Elysia({ basePath: '/nested' }).get(
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.text()).toBe(JSON.stringify('one'))
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.text()).toBe(JSON.stringify('nested'))
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 Elysia({ basePath: '/zero' })
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 Elysia({ basePath: '/two' })
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 Elysia({ basePath: '/nested' })
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(['nested', 'two', 'root'])
285
- expect(onReqTriggered).toEqual(['nested', 'two', 'root'])
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.text()).toBe(JSON.stringify('nested'))
341
+ // expect(await res.json()).toEqual('nested'))
289
342
  }
290
343
  })