spiceflow 1.1.8 → 1.1.10
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 +177 -92
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js.map +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -13
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/utils.js.map +1 -1
- package/dist/client/ws.d.ts.map +1 -1
- package/dist/client/ws.js +1 -3
- package/dist/client/ws.js.map +1 -1
- package/dist/client.test.js +1 -1
- package/dist/client.test.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/cors.d.ts.map +1 -1
- package/dist/cors.js.map +1 -1
- package/dist/cors.test.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/middleware.test.js.map +1 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/openapi.js +1 -1
- package/dist/openapi.js.map +1 -1
- package/dist/openapi.test.js.map +1 -1
- package/dist/simple.benchmark.d.ts +2 -0
- package/dist/simple.benchmark.d.ts.map +1 -0
- package/dist/{benchmark.benchmark.js → simple.benchmark.js} +1 -1
- package/dist/simple.benchmark.js.map +1 -0
- package/dist/spiceflow.d.ts.map +1 -1
- package/dist/spiceflow.js +14 -2
- package/dist/spiceflow.js.map +1 -1
- package/dist/spiceflow.test.js.map +1 -1
- package/dist/static-node.d.ts +4 -0
- package/dist/static-node.d.ts.map +1 -0
- package/dist/static-node.js +35 -0
- package/dist/static-node.js.map +1 -0
- package/dist/static.benchmark.d.ts +2 -0
- package/dist/static.benchmark.d.ts.map +1 -0
- package/dist/static.benchmark.js +19 -0
- package/dist/static.benchmark.js.map +1 -0
- package/dist/static.d.ts +28 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +181 -0
- package/dist/static.js.map +1 -0
- package/dist/stream.test.js +1 -1
- package/dist/stream.test.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/types.test.js +3 -7
- package/dist/types.test.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/zod.test.js.map +1 -1
- package/package.json +1 -1
- package/src/client/errors.ts +17 -17
- package/src/client/index.ts +437 -469
- package/src/client/types.ts +168 -191
- package/src/client/utils.ts +5 -5
- package/src/client/ws.ts +87 -89
- package/src/client.test.ts +176 -183
- package/src/context.ts +82 -82
- package/src/cors.test.ts +38 -38
- package/src/cors.ts +87 -92
- package/src/error.ts +13 -13
- package/src/middleware.test.ts +201 -201
- package/src/openapi.test.ts +97 -97
- package/src/openapi.ts +365 -365
- package/src/simple.benchmark.ts +16 -0
- package/src/spiceflow.test.ts +461 -467
- package/src/spiceflow.ts +1132 -1161
- package/src/static-node.ts +38 -0
- package/src/static.benchmark.ts +22 -0
- package/src/static.ts +240 -0
- package/src/stream.test.ts +310 -310
- package/src/types.test.ts +46 -50
- package/src/types.ts +698 -701
- package/src/utils.ts +79 -79
- package/src/zod.test.ts +64 -64
- package/dist/benchmark.benchmark.d.ts +0 -2
- package/dist/benchmark.benchmark.d.ts.map +0 -1
- package/dist/benchmark.benchmark.js.map +0 -1
- package/src/benchmark.benchmark.ts +0 -16
package/src/cors.test.ts
CHANGED
|
@@ -4,47 +4,47 @@ import { cors } from './cors.js'
|
|
|
4
4
|
import { Spiceflow } from './spiceflow.js'
|
|
5
5
|
|
|
6
6
|
function request(path, method = 'GET') {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
return new Request(`http://localhost/${path}`, {
|
|
8
|
+
method,
|
|
9
|
+
headers: {
|
|
10
|
+
Origin: 'http://example.com',
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
13
|
}
|
|
14
14
|
describe('cors middleware', () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
const app = new Spiceflow()
|
|
16
|
+
.state('x', 1)
|
|
17
|
+
.use(cors())
|
|
18
|
+
.get('/ids/:id', ({ state }) => {
|
|
19
|
+
state.x
|
|
20
|
+
// @ts-expect-error
|
|
21
|
+
state.y
|
|
22
|
+
return 'hi'
|
|
23
|
+
})
|
|
24
|
+
.post('/ids/:id', ({ params: { id } }) => id, {
|
|
25
|
+
params: z.object({ id: z.string() }),
|
|
26
|
+
})
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
test('GET request returns correct response and CORS headers', async () => {
|
|
29
|
+
const res = await app.handle(request('ids/xxx'))
|
|
30
|
+
expect(res.status).toBe(200)
|
|
31
|
+
expect(await res.json()).toBe('hi')
|
|
32
|
+
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
33
|
+
})
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
test('OPTIONS request returns correct CORS headers', async () => {
|
|
36
|
+
const res = await app.handle(request('ids/xxx', 'OPTIONS'))
|
|
37
|
+
expect(res.status).toBe(204)
|
|
38
|
+
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
39
|
+
expect(res.headers.get('Access-Control-Allow-Methods')).toBe(
|
|
40
|
+
'GET,HEAD,PUT,POST,DELETE,PATCH',
|
|
41
|
+
)
|
|
42
|
+
})
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
test('POST request respects CORS and returns correct response', async () => {
|
|
45
|
+
const res = await app.handle(request('ids/123', 'POST'))
|
|
46
|
+
expect(res.status).toBe(200)
|
|
47
|
+
expect(await res.json()).toBe('123')
|
|
48
|
+
expect(res.headers.get('Access-Control-Allow-Origin')).toBe('*')
|
|
49
|
+
})
|
|
50
50
|
})
|
package/src/cors.ts
CHANGED
|
@@ -4,112 +4,107 @@ import { MiddlewareHandler } from './types.js'
|
|
|
4
4
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS MDN CORS documentation}
|
|
5
5
|
*/
|
|
6
6
|
type CORSOptions = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
/** Configures the Access-Control-Allow-Origin CORS header */
|
|
8
|
+
origin: string | string[]
|
|
9
|
+
/** Configures the Access-Control-Allow-Methods CORS header */
|
|
10
|
+
allowMethods?: string[]
|
|
11
|
+
/** Configures the Access-Control-Allow-Headers CORS header */
|
|
12
|
+
allowHeaders?: string[]
|
|
13
|
+
/** Configures the Access-Control-Max-Age CORS header */
|
|
14
|
+
maxAge?: number
|
|
15
|
+
/** Configures the Access-Control-Allow-Credentials CORS header */
|
|
16
|
+
credentials?: boolean
|
|
17
|
+
/** Configures the Access-Control-Expose-Headers CORS header */
|
|
18
|
+
exposeHeaders?: string[]
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const cors = (options?: CORSOptions): MiddlewareHandler => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
const defaults: CORSOptions = {
|
|
23
|
+
origin: '*',
|
|
24
|
+
allowMethods: ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'],
|
|
25
|
+
allowHeaders: [],
|
|
26
|
+
exposeHeaders: [],
|
|
27
|
+
}
|
|
28
|
+
const opts = {
|
|
29
|
+
...defaults,
|
|
30
|
+
...options,
|
|
31
|
+
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
const findAllowOrigin = ((optsOrigin) => {
|
|
34
|
+
if (typeof optsOrigin === 'string') {
|
|
35
|
+
return () => optsOrigin
|
|
36
|
+
} else if (typeof optsOrigin === 'function') {
|
|
37
|
+
return optsOrigin
|
|
38
|
+
} else {
|
|
39
|
+
return (origin: string) =>
|
|
40
|
+
optsOrigin.includes(origin) ? origin : optsOrigin[0]
|
|
41
|
+
}
|
|
42
|
+
})(opts.origin)
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
return async function cors(c, next) {
|
|
45
|
+
let response = await next()
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
function set(key: string, value: string) {
|
|
48
|
+
response.headers.set(key, value)
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
set('Access-Control-Allow-Origin', allowOrigin)
|
|
56
|
-
}
|
|
51
|
+
const allowOrigin = findAllowOrigin(c.request.headers.get('origin') || '')
|
|
52
|
+
if (allowOrigin) {
|
|
53
|
+
set('Access-Control-Allow-Origin', allowOrigin)
|
|
54
|
+
}
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
// Suppose the server sends a response with an Access-Control-Allow-Origin value with an explicit origin (rather than the "*" wildcard).
|
|
57
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
|
58
|
+
if (opts.origin !== '*') {
|
|
59
|
+
const existingVary = c.request.headers.get('Vary')
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
if (existingVary) {
|
|
62
|
+
set('Vary', existingVary)
|
|
63
|
+
} else {
|
|
64
|
+
set('Vary', 'Origin')
|
|
65
|
+
}
|
|
66
|
+
}
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
if (opts.credentials) {
|
|
69
|
+
set('Access-Control-Allow-Credentials', 'true')
|
|
70
|
+
}
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
if (opts.exposeHeaders?.length) {
|
|
73
|
+
set('Access-Control-Expose-Headers', opts.exposeHeaders.join(','))
|
|
74
|
+
}
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
if (c.request.method === 'OPTIONS') {
|
|
77
|
+
if (opts.maxAge != null) {
|
|
78
|
+
set('Access-Control-Max-Age', opts.maxAge.toString())
|
|
79
|
+
}
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
if (opts.allowMethods?.length) {
|
|
82
|
+
set('Access-Control-Allow-Methods', opts.allowMethods.join(','))
|
|
83
|
+
}
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
'Access-Control-Request-Headers',
|
|
101
|
-
)
|
|
102
|
-
}
|
|
85
|
+
let headers = opts.allowHeaders
|
|
86
|
+
if (!headers?.length) {
|
|
87
|
+
const requestHeaders = c.request.headers.get(
|
|
88
|
+
'Access-Control-Request-Headers',
|
|
89
|
+
)
|
|
90
|
+
if (requestHeaders) {
|
|
91
|
+
headers = requestHeaders.split(/\s*,\s*/)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (headers?.length) {
|
|
95
|
+
set('Access-Control-Allow-Headers', headers.join(','))
|
|
96
|
+
c.request.headers.append('Vary', 'Access-Control-Request-Headers')
|
|
97
|
+
}
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
response.headers.delete('Content-Length')
|
|
100
|
+
response.headers.delete('Content-Type')
|
|
106
101
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
return new Response(null, {
|
|
103
|
+
headers: response.headers,
|
|
104
|
+
status: 204,
|
|
105
|
+
statusText: response.statusText,
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
return response
|
|
109
|
+
}
|
|
115
110
|
}
|
package/src/error.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// ? Cloudflare worker support
|
|
2
2
|
const env =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
typeof Bun !== 'undefined'
|
|
5
|
+
? // @ts-ignore
|
|
6
|
+
Bun.env
|
|
7
|
+
: typeof process !== 'undefined'
|
|
8
|
+
? process?.env
|
|
9
|
+
: undefined
|
|
10
10
|
|
|
11
11
|
export const ERROR_CODE = Symbol('SpiceflowErrorCode')
|
|
12
12
|
export type ERROR_CODE = typeof ERROR_CODE
|
|
@@ -17,16 +17,16 @@ export type ELYSIA_RESPONSE = typeof ELYSIA_RESPONSE
|
|
|
17
17
|
export const isProduction = (env?.NODE_ENV ?? env?.ENV) === 'production'
|
|
18
18
|
|
|
19
19
|
export class ValidationError extends Error {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
code = 'VALIDATION'
|
|
21
|
+
status = 422
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export class ParseError extends Error {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
code = 'PARSE'
|
|
26
|
+
status = 400
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export class InternalServerError extends Error {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
code = 'INTERNAL_SERVER_ERROR'
|
|
31
|
+
status = 500
|
|
32
32
|
}
|