spiceflow 0.0.7 → 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.
Files changed (151) hide show
  1. package/README.md +1 -171
  2. package/dist/client/errors.d.ts +7 -0
  3. package/dist/client/errors.d.ts.map +1 -0
  4. package/dist/client/errors.js +18 -0
  5. package/dist/client/errors.js.map +1 -0
  6. package/dist/client/index.d.ts +14 -0
  7. package/dist/client/index.d.ts.map +1 -0
  8. package/dist/client/index.js +376 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/client/types.d.ts +87 -0
  11. package/dist/client/types.d.ts.map +1 -0
  12. package/dist/client/types.js +2 -0
  13. package/dist/client/types.js.map +1 -0
  14. package/dist/client/utils.d.ts +2 -0
  15. package/dist/client/utils.d.ts.map +1 -0
  16. package/dist/client/utils.js +9 -0
  17. package/dist/client/utils.js.map +1 -0
  18. package/dist/client/ws.d.ts +15 -0
  19. package/dist/client/ws.d.ts.map +1 -0
  20. package/dist/client/ws.js +51 -0
  21. package/dist/client/ws.js.map +1 -0
  22. package/dist/client.test.d.ts +2 -0
  23. package/dist/client.test.d.ts.map +1 -0
  24. package/dist/client.test.js +237 -0
  25. package/dist/client.test.js.map +1 -0
  26. package/dist/elysia-fork/context.d.ts +87 -0
  27. package/dist/elysia-fork/context.d.ts.map +1 -0
  28. package/dist/elysia-fork/context.js +2 -0
  29. package/dist/elysia-fork/context.js.map +1 -0
  30. package/dist/elysia-fork/error.d.ts +246 -0
  31. package/dist/elysia-fork/error.d.ts.map +1 -0
  32. package/dist/elysia-fork/error.js +195 -0
  33. package/dist/elysia-fork/error.js.map +1 -0
  34. package/dist/elysia-fork/types.d.ts +652 -0
  35. package/dist/elysia-fork/types.d.ts.map +1 -0
  36. package/dist/elysia-fork/types.js +3 -0
  37. package/dist/elysia-fork/types.js.map +1 -0
  38. package/dist/elysia-fork/utils.d.ts +134 -0
  39. package/dist/elysia-fork/utils.d.ts.map +1 -0
  40. package/dist/elysia-fork/utils.js +70 -0
  41. package/dist/elysia-fork/utils.js.map +1 -0
  42. package/dist/spiceflow.d.ts +253 -0
  43. package/dist/spiceflow.d.ts.map +1 -0
  44. package/dist/spiceflow.js +500 -0
  45. package/dist/spiceflow.js.map +1 -0
  46. package/dist/spiceflow.test.d.ts +2 -0
  47. package/dist/spiceflow.test.d.ts.map +1 -0
  48. package/dist/spiceflow.test.js +225 -0
  49. package/dist/spiceflow.test.js.map +1 -0
  50. package/dist/stream.test.d.ts +2 -0
  51. package/dist/stream.test.d.ts.map +1 -0
  52. package/dist/stream.test.js +286 -0
  53. package/dist/stream.test.js.map +1 -0
  54. package/dist/types.d.ts +1 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +2 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/utils.d.ts +4 -20
  59. package/dist/utils.d.ts.map +1 -1
  60. package/dist/utils.js +17 -46
  61. package/dist/utils.js.map +1 -1
  62. package/package.json +12 -36
  63. package/src/client/errors.ts +21 -0
  64. package/src/client/index.ts +539 -0
  65. package/src/client/types.ts +233 -0
  66. package/src/client/utils.ts +7 -0
  67. package/src/client/ws.ts +99 -0
  68. package/src/client.test.ts +235 -0
  69. package/src/elysia-fork/context.ts +196 -0
  70. package/src/elysia-fork/error.ts +293 -0
  71. package/src/elysia-fork/types.ts +1454 -0
  72. package/src/elysia-fork/utils.ts +85 -0
  73. package/src/spiceflow.test.ts +290 -0
  74. package/src/spiceflow.ts +1266 -0
  75. package/src/stream.test.ts +342 -0
  76. package/src/types.ts +0 -0
  77. package/src/utils.ts +21 -70
  78. package/context.d.ts +0 -2
  79. package/context.js +0 -1
  80. package/dist/babel.test.d.ts +0 -2
  81. package/dist/babel.test.d.ts.map +0 -1
  82. package/dist/babel.test.js +0 -27
  83. package/dist/babel.test.js.map +0 -1
  84. package/dist/babelDebugOutputs.d.ts +0 -9
  85. package/dist/babelDebugOutputs.d.ts.map +0 -1
  86. package/dist/babelDebugOutputs.js +0 -34
  87. package/dist/babelDebugOutputs.js.map +0 -1
  88. package/dist/babelTransformRpc.d.ts +0 -19
  89. package/dist/babelTransformRpc.d.ts.map +0 -1
  90. package/dist/babelTransformRpc.js +0 -285
  91. package/dist/babelTransformRpc.js.map +0 -1
  92. package/dist/browser.d.ts +0 -8
  93. package/dist/browser.d.ts.map +0 -1
  94. package/dist/browser.js +0 -126
  95. package/dist/browser.js.map +0 -1
  96. package/dist/build.d.ts +0 -13
  97. package/dist/build.d.ts.map +0 -1
  98. package/dist/build.js +0 -230
  99. package/dist/build.js.map +0 -1
  100. package/dist/cli.d.ts +0 -3
  101. package/dist/cli.d.ts.map +0 -1
  102. package/dist/cli.js +0 -111
  103. package/dist/cli.js.map +0 -1
  104. package/dist/context-internal.d.ts +0 -20
  105. package/dist/context-internal.d.ts.map +0 -1
  106. package/dist/context-internal.js +0 -16
  107. package/dist/context-internal.js.map +0 -1
  108. package/dist/context.d.ts +0 -2
  109. package/dist/context.d.ts.map +0 -1
  110. package/dist/context.js +0 -2
  111. package/dist/context.js.map +0 -1
  112. package/dist/expose.d.ts +0 -6
  113. package/dist/expose.d.ts.map +0 -1
  114. package/dist/expose.js +0 -32
  115. package/dist/expose.js.map +0 -1
  116. package/dist/headers.d.ts +0 -2
  117. package/dist/headers.d.ts.map +0 -1
  118. package/dist/headers.js +0 -18
  119. package/dist/headers.js.map +0 -1
  120. package/dist/index.d.ts +0 -8
  121. package/dist/index.d.ts.map +0 -1
  122. package/dist/index.js +0 -23
  123. package/dist/index.js.map +0 -1
  124. package/dist/jsonRpc.d.ts +0 -32
  125. package/dist/jsonRpc.d.ts.map +0 -1
  126. package/dist/jsonRpc.js +0 -3
  127. package/dist/jsonRpc.js.map +0 -1
  128. package/dist/server.d.ts +0 -32
  129. package/dist/server.d.ts.map +0 -1
  130. package/dist/server.js +0 -292
  131. package/dist/server.js.map +0 -1
  132. package/headers.d.ts +0 -2
  133. package/headers.js +0 -1
  134. package/sdk-template/package.json +0 -22
  135. package/sdk-template/src/index.ts +0 -2
  136. package/sdk-template/src/v1/example.ts +0 -5
  137. package/sdk-template/src/v1/generator.ts +0 -12
  138. package/sdk-template/tsconfig.json +0 -16
  139. package/src/babel.test.ts +0 -35
  140. package/src/babelDebugOutputs.ts +0 -56
  141. package/src/babelTransformRpc.ts +0 -394
  142. package/src/browser.ts +0 -141
  143. package/src/build.ts +0 -298
  144. package/src/cli.ts +0 -132
  145. package/src/context-internal.ts +0 -36
  146. package/src/context.ts +0 -5
  147. package/src/expose.ts +0 -34
  148. package/src/headers.ts +0 -19
  149. package/src/index.ts +0 -34
  150. package/src/jsonRpc.ts +0 -43
  151. package/src/server.ts +0 -384
@@ -0,0 +1,85 @@
1
+ export const StatusMap = {
2
+ Continue: 100,
3
+ 'Switching Protocols': 101,
4
+ Processing: 102,
5
+ 'Early Hints': 103,
6
+ OK: 200,
7
+ Created: 201,
8
+ Accepted: 202,
9
+ 'Non-Authoritative Information': 203,
10
+ 'No Content': 204,
11
+ 'Reset Content': 205,
12
+ 'Partial Content': 206,
13
+ 'Multi-Status': 207,
14
+ 'Already Reported': 208,
15
+ 'Multiple Choices': 300,
16
+ 'Moved Permanently': 301,
17
+ Found: 302,
18
+ 'See Other': 303,
19
+ 'Not Modified': 304,
20
+ 'Temporary Redirect': 307,
21
+ 'Permanent Redirect': 308,
22
+ 'Bad Request': 400,
23
+ Unauthorized: 401,
24
+ 'Payment Required': 402,
25
+ Forbidden: 403,
26
+ 'Not Found': 404,
27
+ 'Method Not Allowed': 405,
28
+ 'Not Acceptable': 406,
29
+ 'Proxy Authentication Required': 407,
30
+ 'Request Timeout': 408,
31
+ Conflict: 409,
32
+ Gone: 410,
33
+ 'Length Required': 411,
34
+ 'Precondition Failed': 412,
35
+ 'Payload Too Large': 413,
36
+ 'URI Too Long': 414,
37
+ 'Unsupported Media Type': 415,
38
+ 'Range Not Satisfiable': 416,
39
+ 'Expectation Failed': 417,
40
+ "I'm a teapot": 418,
41
+ 'Misdirected Request': 421,
42
+ 'Unprocessable Content': 422,
43
+ Locked: 423,
44
+ 'Failed Dependency': 424,
45
+ 'Too Early': 425,
46
+ 'Upgrade Required': 426,
47
+ 'Precondition Required': 428,
48
+ 'Too Many Requests': 429,
49
+ 'Request Header Fields Too Large': 431,
50
+ 'Unavailable For Legal Reasons': 451,
51
+ 'Internal Server Error': 500,
52
+ 'Not Implemented': 501,
53
+ 'Bad Gateway': 502,
54
+ 'Service Unavailable': 503,
55
+ 'Gateway Timeout': 504,
56
+ 'HTTP Version Not Supported': 505,
57
+ 'Variant Also Negotiates': 506,
58
+ 'Insufficient Storage': 507,
59
+ 'Loop Detected': 508,
60
+ 'Not Extended': 510,
61
+ 'Network Authentication Required': 511
62
+ } as const
63
+
64
+ export const InvertedStatusMap = Object.fromEntries(
65
+ Object.entries(StatusMap).map(([k, v]) => [v, k])
66
+ ) as {
67
+ [K in keyof StatusMap as StatusMap[K]]: K
68
+ }
69
+
70
+ export type StatusMap = typeof StatusMap
71
+ export type InvertedStatusMap = typeof InvertedStatusMap
72
+
73
+
74
+
75
+ /**
76
+ *
77
+ * @param url URL to redirect to
78
+ * @param HTTP status code to send,
79
+ */
80
+ export const redirect = (
81
+ url: string,
82
+ status: 301 | 302 | 303 | 307 | 308 = 302
83
+ ) => Response.redirect(url, status)
84
+
85
+ export type redirect = typeof redirect
@@ -0,0 +1,290 @@
1
+ import { test, describe, expect } from 'vitest'
2
+ import { Type } from '@sinclair/typebox'
3
+ import { Elysia } from './spiceflow'
4
+
5
+ test('works', async () => {
6
+ const res = await new Elysia()
7
+ .post('/xxx', () => 'hi')
8
+ .handle(new Request('http://localhost/xxx', { method: 'POST' }))
9
+ expect(res.status).toBe(200)
10
+ expect(await res.text()).toBe(JSON.stringify('hi'))
11
+ })
12
+ test('dynamic route', async () => {
13
+ const res = await new Elysia()
14
+ .post('/ids/:id', () => 'hi')
15
+ .handle(new Request('http://localhost/ids/xxx', { method: 'POST' }))
16
+ expect(res.status).toBe(200)
17
+ expect(await res.text()).toBe(JSON.stringify('hi'))
18
+ })
19
+ test('GET dynamic route', async () => {
20
+ const res = await new Elysia()
21
+ .get('/ids/:id', () => 'hi')
22
+ .handle(new Request('http://localhost/ids/xxx', { method: 'GET' }))
23
+ expect(res.status).toBe(200)
24
+ expect(await res.text()).toBe(JSON.stringify('hi'))
25
+ })
26
+
27
+ test('missing route is not found', async () => {
28
+ const res = await new Elysia()
29
+ .get('/ids/:id', () => 'hi')
30
+ .handle(new Request('http://localhost/zxxx', { method: 'GET' }))
31
+ expect(res.status).toBe(404)
32
+ })
33
+ test('state works', async () => {
34
+ const res = await new Elysia()
35
+ .state('id', '')
36
+ .onRequest(({ store, request }) => {
37
+ store.id = 'xxx'
38
+ })
39
+ .get('/get', ({ store }) => {
40
+ expect(store.id).toBe('xxx')
41
+ })
42
+ .handle(new Request('http://localhost/get'))
43
+ expect(res.status).toBe(200)
44
+ })
45
+
46
+ test('body is parsed as json', async () => {
47
+ let body
48
+ const res = await new Elysia()
49
+ .state('id', '')
50
+
51
+ .post('/post', (c) => {
52
+ body = c.body
53
+ // console.log({ body })
54
+ return body
55
+ })
56
+ .handle(
57
+ new Request('http://localhost/post', {
58
+ method: 'POST',
59
+ headers: {
60
+ 'content-type': 'application/json'
61
+ },
62
+ body: JSON.stringify({ name: 'John' })
63
+ })
64
+ )
65
+ expect(res.status).toBe(200)
66
+ expect(await res.text()).toBe(JSON.stringify({ name: 'John' }))
67
+ })
68
+
69
+ test('validate body works, request success', async () => {
70
+ const res = await new Elysia()
71
+
72
+ .post(
73
+ '/post',
74
+ ({ body }) => {
75
+ // console.log({ body })
76
+ expect(body).toEqual({ name: 'John' })
77
+ return 'ok'
78
+ },
79
+ {
80
+ body: Type.Object({
81
+ name: Type.String()
82
+ })
83
+ }
84
+ )
85
+ .handle(
86
+ new Request('http://localhost/post', {
87
+ method: 'POST',
88
+ headers: {
89
+ 'content-type': 'application/json'
90
+ },
91
+ body: JSON.stringify({ name: 'John' })
92
+ })
93
+ )
94
+ expect(res.status).toBe(200)
95
+ expect(await res.text()).toMatchInlineSnapshot(`""ok""`)
96
+ })
97
+
98
+ test('validate body works, request fails', async () => {
99
+ const res = await new Elysia()
100
+
101
+ .post(
102
+ '/post',
103
+ ({ body, redirect, error }) => {
104
+ // console.log({ body })
105
+ expect(body).toEqual({ name: 'John' })
106
+ },
107
+ {
108
+ body: Type.Object({
109
+ name: Type.String(),
110
+ requiredField: Type.String()
111
+ })
112
+ }
113
+ )
114
+ .handle(
115
+ new Request('http://localhost/post', {
116
+ method: 'POST',
117
+ headers: {
118
+ 'content-type': 'application/json'
119
+ },
120
+ body: JSON.stringify({ name: 'John' })
121
+ })
122
+ )
123
+ expect(res.status).toBe(400)
124
+ expect(await res.text()).toMatchInlineSnapshot(
125
+ `"data must have required property 'requiredField'"`
126
+ )
127
+ })
128
+
129
+ test('run onRequest', async () => {
130
+ const res = await new Elysia()
131
+ .onRequest(({ request }) => {
132
+ expect(request.method).toBe('HEAD')
133
+ return new Response('ok', { status: 401 })
134
+ })
135
+ .onRequest(({ request }) => {
136
+ expect(request.method).toBe('HEAD')
137
+ return 'second one'
138
+ })
139
+ .head('/ids/:id', () => 'hi')
140
+ .handle(new Request('http://localhost/ids/zxxx', { method: 'HEAD' }))
141
+ expect(res.status).toBe(401)
142
+ expect(await res.text()).toBe('ok')
143
+ })
144
+
145
+ test('run onRequest', async () => {
146
+ const res = await new Elysia()
147
+ .onRequest(({ request }) => {
148
+ expect(request.method).toBe('HEAD')
149
+ return new Response('ok', { status: 401 })
150
+ })
151
+ .onRequest(({ request }) => {
152
+ expect(request.method).toBe('HEAD')
153
+ return 'second one'
154
+ })
155
+ .head('/ids/:id', () => 'hi')
156
+ .handle(new Request('http://localhost/ids/zxxx', { method: 'HEAD' }))
157
+ expect(res.status).toBe(401)
158
+ expect(await res.text()).toBe('ok')
159
+ })
160
+
161
+ test('basPath works', async () => {
162
+ const res = await new Elysia({ basePath: '/one' })
163
+ .get('/ids/:id', () => 'hi')
164
+ .handle(new Request('http://localhost/one/ids/xxx', { method: 'GET' }))
165
+ expect(res.status).toBe(200)
166
+ expect(await res.text()).toBe(JSON.stringify('hi'))
167
+ })
168
+
169
+ test('use with 2 basPath works', async () => {
170
+ let oneOnReq = false
171
+ let twoOnReq = false
172
+ const app = await new Elysia()
173
+ .use(
174
+ new Elysia({ basePath: '/one' })
175
+ .onRequest(({ request }) => {
176
+ oneOnReq = true
177
+ })
178
+ .get('/ids/:id', ({ params }) => params.id)
179
+ )
180
+ .use(
181
+ new Elysia({ basePath: '/two' })
182
+ .onRequest((c) => {
183
+ twoOnReq = true
184
+ })
185
+ .get('/ids/:id', ({ params }) => params.id)
186
+ )
187
+
188
+ {
189
+ const res = await app.handle(
190
+ new Request('http://localhost/one/ids/one')
191
+ )
192
+ expect(res.status).toBe(200)
193
+
194
+ expect(await res.text()).toBe(JSON.stringify('one'))
195
+ }
196
+ {
197
+ const res = await app.handle(
198
+ new Request('http://localhost/two/ids/two')
199
+ )
200
+ expect(res.status).toBe(200)
201
+
202
+ expect(await res.text()).toBe(JSON.stringify('two'))
203
+ }
204
+ expect(oneOnReq).toBe(true)
205
+ expect(twoOnReq).toBe(true)
206
+ })
207
+
208
+ test('use with nested basPath works', async () => {
209
+ const app = await new Elysia({ basePath: '/zero' })
210
+ .use(
211
+ new Elysia({ basePath: '/one' }).get(
212
+ '/ids/:id',
213
+ ({ params }) => params.id
214
+ )
215
+ )
216
+ .use(
217
+ new Elysia({ basePath: '/two' }).use(
218
+ new Elysia({ basePath: '/nested' }).get(
219
+ '/ids/:id',
220
+ ({ params }) => params.id
221
+ )
222
+ )
223
+ )
224
+ {
225
+ const res = await app.handle(
226
+ new Request('http://localhost/zero/one/ids/one')
227
+ )
228
+ expect(res.status).toBe(200)
229
+ expect(await res.text()).toBe(JSON.stringify('one'))
230
+ }
231
+
232
+ {
233
+ const res = await app.handle(
234
+ new Request('http://localhost/zero/two/nested/ids/nested')
235
+ )
236
+ expect(res.status).toBe(200)
237
+ expect(await res.text()).toBe(JSON.stringify('nested'))
238
+ }
239
+ })
240
+
241
+ test('errors inside basPath works', async () => {
242
+ let onErrorTriggered = [] as string[]
243
+ let onReqTriggered = [] as string[]
244
+ const app = await new Elysia({ basePath: '/zero' })
245
+ .onError(({ error }) => {
246
+ onErrorTriggered.push('root')
247
+ // return new Response('root', { status: 500 })
248
+ })
249
+ .onRequest(({ request }) => {
250
+ onReqTriggered.push('root')
251
+ // return new Response('root', { status: 500 })
252
+ })
253
+
254
+ .use(
255
+ new Elysia({ basePath: '/two' })
256
+ .onError(({ error }) => {
257
+ onErrorTriggered.push('two')
258
+ // return new Response('two', { status: 500 })
259
+ })
260
+ .onRequest(({ request }) => {
261
+ onReqTriggered.push('two')
262
+ // return new Response('two', { status: 500 })
263
+ })
264
+ .use(
265
+ new Elysia({ basePath: '/nested' })
266
+ .onError(({ error }) => {
267
+ onErrorTriggered.push('nested')
268
+ // return new Response('nested', { status: 500 })
269
+ })
270
+ .onRequest(({ request }) => {
271
+ onReqTriggered.push('nested')
272
+ // return new Response('nested', { status: 500 })
273
+ })
274
+ .get('/ids/:id', ({ params }) => {
275
+ throw new Error('error message')
276
+ })
277
+ )
278
+ )
279
+
280
+ {
281
+ const res = await app.handle(
282
+ new Request('http://localhost/zero/two/nested/ids/nested')
283
+ )
284
+ expect(onErrorTriggered).toEqual(['nested', 'two', 'root'])
285
+ expect(onReqTriggered).toEqual(['nested', 'two', 'root'])
286
+ expect(res.status).toBe(500)
287
+ expect(await res.text()).toBe('error message')
288
+ // expect(await res.text()).toBe(JSON.stringify('nested'))
289
+ }
290
+ })