spiceflow 0.0.7 → 1.0.1

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 +15 -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 +570 -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/index.d.ts +2 -7
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +1 -22
  45. package/dist/index.js.map +1 -1
  46. package/dist/spiceflow.d.ts +237 -0
  47. package/dist/spiceflow.d.ts.map +1 -0
  48. package/dist/spiceflow.js +484 -0
  49. package/dist/spiceflow.js.map +1 -0
  50. package/dist/spiceflow.test.d.ts +2 -0
  51. package/dist/spiceflow.test.d.ts.map +1 -0
  52. package/dist/spiceflow.test.js +225 -0
  53. package/dist/spiceflow.test.js.map +1 -0
  54. package/dist/stream.test.d.ts +2 -0
  55. package/dist/stream.test.d.ts.map +1 -0
  56. package/dist/stream.test.js +286 -0
  57. package/dist/stream.test.js.map +1 -0
  58. package/dist/types.d.ts +1 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils.d.ts +4 -20
  63. package/dist/utils.d.ts.map +1 -1
  64. package/dist/utils.js +17 -46
  65. package/dist/utils.js.map +1 -1
  66. package/package.json +12 -37
  67. package/src/client/errors.ts +21 -0
  68. package/src/client/index.ts +541 -0
  69. package/src/client/types.ts +233 -0
  70. package/src/client/utils.ts +7 -0
  71. package/src/client/ws.ts +99 -0
  72. package/src/client.test.ts +235 -0
  73. package/src/elysia-fork/context.ts +196 -0
  74. package/src/elysia-fork/error.ts +293 -0
  75. package/src/elysia-fork/types.ts +1353 -0
  76. package/src/elysia-fork/utils.ts +85 -0
  77. package/src/index.ts +2 -34
  78. package/src/spiceflow.test.ts +290 -0
  79. package/src/spiceflow.ts +1251 -0
  80. package/src/stream.test.ts +342 -0
  81. package/src/types.ts +0 -0
  82. package/src/utils.ts +21 -70
  83. package/context.d.ts +0 -2
  84. package/context.js +0 -1
  85. package/dist/babel.test.d.ts +0 -2
  86. package/dist/babel.test.d.ts.map +0 -1
  87. package/dist/babel.test.js +0 -27
  88. package/dist/babel.test.js.map +0 -1
  89. package/dist/babelDebugOutputs.d.ts +0 -9
  90. package/dist/babelDebugOutputs.d.ts.map +0 -1
  91. package/dist/babelDebugOutputs.js +0 -34
  92. package/dist/babelDebugOutputs.js.map +0 -1
  93. package/dist/babelTransformRpc.d.ts +0 -19
  94. package/dist/babelTransformRpc.d.ts.map +0 -1
  95. package/dist/babelTransformRpc.js +0 -285
  96. package/dist/babelTransformRpc.js.map +0 -1
  97. package/dist/browser.d.ts +0 -8
  98. package/dist/browser.d.ts.map +0 -1
  99. package/dist/browser.js +0 -126
  100. package/dist/browser.js.map +0 -1
  101. package/dist/build.d.ts +0 -13
  102. package/dist/build.d.ts.map +0 -1
  103. package/dist/build.js +0 -230
  104. package/dist/build.js.map +0 -1
  105. package/dist/cli.d.ts +0 -3
  106. package/dist/cli.d.ts.map +0 -1
  107. package/dist/cli.js +0 -111
  108. package/dist/cli.js.map +0 -1
  109. package/dist/context-internal.d.ts +0 -20
  110. package/dist/context-internal.d.ts.map +0 -1
  111. package/dist/context-internal.js +0 -16
  112. package/dist/context-internal.js.map +0 -1
  113. package/dist/context.d.ts +0 -2
  114. package/dist/context.d.ts.map +0 -1
  115. package/dist/context.js +0 -2
  116. package/dist/context.js.map +0 -1
  117. package/dist/expose.d.ts +0 -6
  118. package/dist/expose.d.ts.map +0 -1
  119. package/dist/expose.js +0 -32
  120. package/dist/expose.js.map +0 -1
  121. package/dist/headers.d.ts +0 -2
  122. package/dist/headers.d.ts.map +0 -1
  123. package/dist/headers.js +0 -18
  124. package/dist/headers.js.map +0 -1
  125. package/dist/jsonRpc.d.ts +0 -32
  126. package/dist/jsonRpc.d.ts.map +0 -1
  127. package/dist/jsonRpc.js +0 -3
  128. package/dist/jsonRpc.js.map +0 -1
  129. package/dist/server.d.ts +0 -32
  130. package/dist/server.d.ts.map +0 -1
  131. package/dist/server.js +0 -292
  132. package/dist/server.js.map +0 -1
  133. package/headers.d.ts +0 -2
  134. package/headers.js +0 -1
  135. package/sdk-template/package.json +0 -22
  136. package/sdk-template/src/index.ts +0 -2
  137. package/sdk-template/src/v1/example.ts +0 -5
  138. package/sdk-template/src/v1/generator.ts +0 -12
  139. package/sdk-template/tsconfig.json +0 -16
  140. package/src/babel.test.ts +0 -35
  141. package/src/babelDebugOutputs.ts +0 -56
  142. package/src/babelTransformRpc.ts +0 -394
  143. package/src/browser.ts +0 -141
  144. package/src/build.ts +0 -298
  145. package/src/cli.ts +0 -132
  146. package/src/context-internal.ts +0 -36
  147. package/src/context.ts +0 -5
  148. package/src/expose.ts +0 -34
  149. package/src/headers.ts +0 -19
  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
package/src/index.ts CHANGED
@@ -1,34 +1,2 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { PluginOptions } from './babelTransformRpc.js';
4
-
5
- import { WrapMethod, WrapMethodMeta } from './server.js';
6
-
7
- export interface WithRpcConfig {}
8
-
9
- export { WrapMethod };
10
-
11
- import pluginSyntaxJsx from '@babel/plugin-syntax-jsx';
12
- import pluginTransformTypescript from '@babel/plugin-syntax-typescript';
13
- import babelTransformRpc from './babelTransformRpc.js';
14
- import babelDebugOutputs from './babelDebugOutputs.js';
15
-
16
- export function plugins(options: PluginOptions) {
17
- return [
18
- pluginSyntaxJsx,
19
- [pluginTransformTypescript, { isTSX: true }],
20
- [babelTransformRpc, options],
21
- process.env.DEBUG_ACTIONS && [babelDebugOutputs, options],
22
- ].filter(Boolean);
23
- }
24
-
25
- export function findRootDir(dir: string): string {
26
- {
27
- let curDir = path.resolve(dir, 'src');
28
- if (fs.existsSync(curDir)) return path.resolve(curDir);
29
- }
30
-
31
- throw new Error(
32
- "Couldn't find a src directory. Please create one under the project root",
33
- );
34
- }
1
+ export * from './spiceflow.js'
2
+ export { Static } from '@sinclair/typebox'
@@ -0,0 +1,290 @@
1
+ import { test, describe, expect } from 'vitest'
2
+ import { Type } from '@sinclair/typebox'
3
+ import { Spiceflow } from './spiceflow'
4
+
5
+ test('works', async () => {
6
+ const res = await new Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow()
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 Spiceflow({ 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 Spiceflow()
173
+ .use(
174
+ new Spiceflow({ basePath: '/one' })
175
+ .onRequest(({ request }) => {
176
+ oneOnReq = true
177
+ })
178
+ .get('/ids/:id', ({ params }) => params.id)
179
+ )
180
+ .use(
181
+ new Spiceflow({ 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 Spiceflow({ basePath: '/zero' })
210
+ .use(
211
+ new Spiceflow({ basePath: '/one' }).get(
212
+ '/ids/:id',
213
+ ({ params }) => params.id
214
+ )
215
+ )
216
+ .use(
217
+ new Spiceflow({ basePath: '/two' }).use(
218
+ new Spiceflow({ 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 Spiceflow({ 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 Spiceflow({ 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 Spiceflow({ 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
+ })