effect-start 0.34.0 → 0.35.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.
- package/README.md +303 -36
- package/dist/Fetch.d.ts +1 -1
- package/dist/FileRouter.d.ts +1 -1
- package/dist/FileRouterCodegen.d.ts.map +1 -1
- package/dist/FileRouterCodegen.js +8 -2
- package/dist/FileRouterCodegen.js.map +1 -1
- package/dist/Job.d.ts +94 -0
- package/dist/Job.d.ts.map +1 -0
- package/dist/Job.js +157 -0
- package/dist/Job.js.map +1 -0
- package/dist/Password.d.ts +1 -1
- package/dist/Route.d.ts +20 -15
- package/dist/Route.d.ts.map +1 -1
- package/dist/Route.js +12 -0
- package/dist/Route.js.map +1 -1
- package/dist/RouteBody.d.ts +7 -7
- package/dist/RouteBody.d.ts.map +1 -1
- package/dist/RouteBody.js.map +1 -1
- package/dist/RouteHook.d.ts +1 -1
- package/dist/RouteHook.d.ts.map +1 -1
- package/dist/RouteHook.js.map +1 -1
- package/dist/RouteHttp.d.ts.map +1 -1
- package/dist/RouteHttp.js +10 -4
- package/dist/RouteHttp.js.map +1 -1
- package/dist/RouteLink.d.ts +16 -0
- package/dist/RouteLink.d.ts.map +1 -0
- package/dist/RouteLink.js +23 -0
- package/dist/RouteLink.js.map +1 -0
- package/dist/RouteMount.d.ts +29 -32
- package/dist/RouteMount.d.ts.map +1 -1
- package/dist/RouteMount.js.map +1 -1
- package/dist/RouteSchema.d.ts +81 -28
- package/dist/RouteSchema.d.ts.map +1 -1
- package/dist/RouteSchema.js +56 -101
- package/dist/RouteSchema.js.map +1 -1
- package/dist/RouteSse.d.ts +1 -1
- package/dist/RouteSse.d.ts.map +1 -1
- package/dist/RouteSse.js.map +1 -1
- package/dist/Socket.d.ts +1 -1
- package/dist/Start.js +1 -1
- package/dist/Start.js.map +1 -1
- package/dist/StaticFiles.d.ts +4 -10
- package/dist/StaticFiles.d.ts.map +1 -1
- package/dist/StaticFiles.js +3 -10
- package/dist/StaticFiles.js.map +1 -1
- package/dist/System.d.ts +1 -1
- package/dist/_Docker.d.ts +1 -1
- package/dist/_HtmlScanner.d.ts +42 -0
- package/dist/_HtmlScanner.d.ts.map +1 -0
- package/dist/_HtmlScanner.js +385 -0
- package/dist/_HtmlScanner.js.map +1 -0
- package/dist/_RouteLink.d.ts +16 -0
- package/dist/_RouteLink.d.ts.map +1 -0
- package/dist/_RouteLink.js +22 -0
- package/dist/_RouteLink.js.map +1 -0
- package/dist/bun/BunRoute.d.ts +4 -6
- package/dist/bun/BunRoute.d.ts.map +1 -1
- package/dist/bun/BunRoute.js +1 -1
- package/dist/bun/BunRoute.js.map +1 -1
- package/dist/bundler/Bundle.d.ts +1 -1
- package/dist/bundler/BundleRoute.d.ts +5 -6
- package/dist/bundler/BundleRoute.d.ts.map +1 -1
- package/dist/bundler/BundleRoute.js +5 -11
- package/dist/bundler/BundleRoute.js.map +1 -1
- package/dist/datastar/watchers/patchElements.js +1 -1
- package/dist/datastar/watchers/patchElements.js.map +1 -1
- package/dist/experimental/CsrfProtection.d.ts +67 -0
- package/dist/experimental/CsrfProtection.d.ts.map +1 -0
- package/dist/experimental/CsrfProtection.js +100 -0
- package/dist/experimental/CsrfProtection.js.map +1 -0
- package/dist/experimental/EncryptedCookies.d.ts +1 -1
- package/dist/experimental/KeyValueStore.d.ts +1 -1
- package/dist/lint/plugin.js +4 -0
- package/dist/lint/plugin.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +1 -1
- package/dist/studio/Studio.d.ts +1 -1
- package/dist/studio/Studio.d.ts.map +1 -1
- package/dist/studio/Studio.js +4 -10
- package/dist/studio/Studio.js.map +1 -1
- package/dist/studio/routes/errors/route.d.ts +3 -3
- package/dist/studio/routes/errors/route.d.ts.map +1 -1
- package/dist/studio/routes/errors/route.js +3 -2
- package/dist/studio/routes/errors/route.js.map +1 -1
- package/dist/studio/routes/fiberDetail.d.ts +3 -7
- package/dist/studio/routes/fiberDetail.d.ts.map +1 -1
- package/dist/studio/routes/fibers/route.d.ts +3 -3
- package/dist/studio/routes/layout.d.ts +3 -3
- package/dist/studio/routes/logs/route.d.ts +3 -3
- package/dist/studio/routes/logs/route.d.ts.map +1 -1
- package/dist/studio/routes/logs/route.js +3 -2
- package/dist/studio/routes/logs/route.js.map +1 -1
- package/dist/studio/routes/metrics/route.d.ts +3 -3
- package/dist/studio/routes/route.d.ts +2 -2
- package/dist/studio/routes/routes/route.d.ts +2 -2
- package/dist/studio/routes/services/route.d.ts +2 -2
- package/dist/studio/routes/system/route.d.ts +3 -3
- package/dist/studio/routes/traceDetail.d.ts +3 -7
- package/dist/studio/routes/traceDetail.d.ts.map +1 -1
- package/dist/studio/routes/traces/route.d.ts +3 -3
- package/dist/studio/routes/traces/route.d.ts.map +1 -1
- package/dist/studio/routes/traces/route.js +3 -2
- package/dist/studio/routes/traces/route.js.map +1 -1
- package/dist/studio/routes/tree.d.ts +43 -51
- package/dist/studio/routes/tree.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/FileRouterCodegen.ts +8 -2
- package/src/Route.ts +55 -34
- package/src/RouteBody.ts +15 -15
- package/src/RouteHook.ts +3 -3
- package/src/RouteHttp.ts +10 -4
- package/src/RouteLink.ts +56 -0
- package/src/RouteMount.ts +43 -48
- package/src/RouteSchema.ts +299 -166
- package/src/RouteSse.ts +3 -3
- package/src/Start.ts +1 -1
- package/src/StaticFiles.ts +10 -24
- package/src/_HtmlScanner.ts +415 -0
- package/src/bun/BunRoute.ts +11 -11
- package/src/bundler/BundleRoute.ts +8 -19
- package/src/datastar/watchers/patchElements.ts +1 -1
- package/src/dev.d.ts +3 -0
- package/src/experimental/CsrfProtection.ts +153 -0
- package/src/lint/plugin.js +2 -0
- package/src/studio/Studio.ts +4 -14
- package/src/studio/routes/errors/route.tsx +3 -2
- package/src/studio/routes/logs/route.tsx +3 -2
- package/src/studio/routes/traces/route.tsx +3 -2
package/src/RouteSchema.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as Effect from "effect/Effect"
|
|
|
2
2
|
import type * as ParseResult from "effect/ParseResult"
|
|
3
3
|
import * as Schema from "effect/Schema"
|
|
4
4
|
import type * as Scope from "effect/Scope"
|
|
5
|
+
import type * as Types from "effect/Types"
|
|
5
6
|
import * as Entity from "./Entity.ts"
|
|
6
7
|
import * as Http from "./_Http.ts"
|
|
7
8
|
import * as PathPattern from "./_PathPattern.ts"
|
|
@@ -26,50 +27,113 @@ export const File = Schema.TaggedStruct("File", {
|
|
|
26
27
|
content: Schema.Uint8ArrayFromSelf,
|
|
27
28
|
})
|
|
28
29
|
|
|
30
|
+
type SchemaOrFields = Schema.Schema.All | Schema.Struct.Fields
|
|
31
|
+
|
|
32
|
+
function toSchema(input: SchemaOrFields): Schema.Schema<any, any, any> {
|
|
33
|
+
return (Schema.isSchema(input) ? input : Schema.Struct(input as any)) as any
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function makeSchemaFilter(
|
|
37
|
+
handler: (ctx: any, decode: (input: unknown) => Effect.Effect<any, any, any>) => Effect.Effect<any, any, any>,
|
|
38
|
+
) {
|
|
39
|
+
return (fields: SchemaOrFields): any => {
|
|
40
|
+
const decode = Schema.decodeUnknown(toSchema(fields))
|
|
41
|
+
return RouteHook.filter((ctx: any) => handler(ctx, decode))
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function schemaHeaders<F extends Schema.Struct.Fields>(
|
|
46
|
+
fields: F,
|
|
47
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
48
|
+
self: Route.RouteSet<D, SB, P>,
|
|
49
|
+
) => Route.RouteSet<
|
|
50
|
+
D,
|
|
51
|
+
SB,
|
|
52
|
+
[
|
|
53
|
+
...P,
|
|
54
|
+
Route.Route<
|
|
55
|
+
{},
|
|
56
|
+
{ headers: Types.Simplify<Schema.Struct.Type<F>> },
|
|
57
|
+
unknown,
|
|
58
|
+
ParseResult.ParseError,
|
|
59
|
+
Schema.Struct.Context<F> | Route.Request
|
|
60
|
+
>,
|
|
61
|
+
]
|
|
62
|
+
>
|
|
29
63
|
export function schemaHeaders<A, I extends Readonly<Record<string, string | undefined>>, R>(
|
|
30
64
|
fields: Schema.Schema<A, I, R>,
|
|
31
65
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
32
|
-
self: Route.RouteSet
|
|
33
|
-
) => Route.RouteSet
|
|
66
|
+
self: Route.RouteSet<D, SB, P>,
|
|
67
|
+
) => Route.RouteSet<
|
|
34
68
|
D,
|
|
35
69
|
SB,
|
|
36
|
-
[...P, Route.Route
|
|
37
|
-
>
|
|
38
|
-
|
|
39
|
-
return
|
|
40
|
-
Effect.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
})),
|
|
48
|
-
)
|
|
70
|
+
[...P, Route.Route<{}, { headers: A }, unknown, ParseResult.ParseError, R | Route.Request>]
|
|
71
|
+
>
|
|
72
|
+
export function schemaHeaders(fields: SchemaOrFields) {
|
|
73
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
74
|
+
Effect.gen(function* () {
|
|
75
|
+
const request = yield* Route.Request
|
|
76
|
+
const parsed = yield* decode(Http.mapHeaders(request.headers))
|
|
77
|
+
return { context: { headers: { ...ctx.headers, ...parsed } } }
|
|
78
|
+
}),
|
|
79
|
+
)(fields)
|
|
49
80
|
}
|
|
50
81
|
|
|
82
|
+
export function schemaCookies<F extends Schema.Struct.Fields>(
|
|
83
|
+
fields: F,
|
|
84
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
85
|
+
self: Route.RouteSet<D, SB, P>,
|
|
86
|
+
) => Route.RouteSet<
|
|
87
|
+
D,
|
|
88
|
+
SB,
|
|
89
|
+
[
|
|
90
|
+
...P,
|
|
91
|
+
Route.Route<
|
|
92
|
+
{},
|
|
93
|
+
{ cookies: Types.Simplify<Schema.Struct.Type<F>> },
|
|
94
|
+
unknown,
|
|
95
|
+
ParseResult.ParseError,
|
|
96
|
+
Schema.Struct.Context<F> | Route.Request
|
|
97
|
+
>,
|
|
98
|
+
]
|
|
99
|
+
>
|
|
51
100
|
export function schemaCookies<A, I extends Readonly<Record<string, string | undefined>>, R>(
|
|
52
101
|
fields: Schema.Schema<A, I, R>,
|
|
53
102
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
54
|
-
self: Route.RouteSet
|
|
55
|
-
) => Route.RouteSet
|
|
103
|
+
self: Route.RouteSet<D, SB, P>,
|
|
104
|
+
) => Route.RouteSet<
|
|
56
105
|
D,
|
|
57
106
|
SB,
|
|
58
|
-
[...P, Route.Route
|
|
59
|
-
>
|
|
60
|
-
|
|
61
|
-
return
|
|
62
|
-
Effect.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
})),
|
|
70
|
-
)
|
|
107
|
+
[...P, Route.Route<{}, { cookies: A }, unknown, ParseResult.ParseError, R | Route.Request>]
|
|
108
|
+
>
|
|
109
|
+
export function schemaCookies(fields: SchemaOrFields) {
|
|
110
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
111
|
+
Effect.gen(function* () {
|
|
112
|
+
const request = yield* Route.Request
|
|
113
|
+
const parsed = yield* decode(Http.parseCookies(request.headers.get("cookie")))
|
|
114
|
+
return { context: { cookies: { ...ctx.cookies, ...parsed } } }
|
|
115
|
+
}),
|
|
116
|
+
)(fields)
|
|
71
117
|
}
|
|
72
118
|
|
|
119
|
+
export function schemaSearchParams<F extends Schema.Struct.Fields>(
|
|
120
|
+
fields: F,
|
|
121
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
122
|
+
self: Route.RouteSet<D, SB, P>,
|
|
123
|
+
) => Route.RouteSet<
|
|
124
|
+
D,
|
|
125
|
+
SB,
|
|
126
|
+
[
|
|
127
|
+
...P,
|
|
128
|
+
Route.Route<
|
|
129
|
+
{},
|
|
130
|
+
{ searchParams: Types.Simplify<Schema.Struct.Type<F>> },
|
|
131
|
+
unknown,
|
|
132
|
+
ParseResult.ParseError,
|
|
133
|
+
Schema.Struct.Context<F> | Route.Request
|
|
134
|
+
>,
|
|
135
|
+
]
|
|
136
|
+
>
|
|
73
137
|
export function schemaSearchParams<
|
|
74
138
|
A,
|
|
75
139
|
I extends Readonly<Record<string, string | ReadonlyArray<string> | undefined>>,
|
|
@@ -77,80 +141,122 @@ export function schemaSearchParams<
|
|
|
77
141
|
>(
|
|
78
142
|
fields: Schema.Schema<A, I, R>,
|
|
79
143
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
80
|
-
self: Route.RouteSet
|
|
81
|
-
) => Route.RouteSet
|
|
144
|
+
self: Route.RouteSet<D, SB, P>,
|
|
145
|
+
) => Route.RouteSet<
|
|
82
146
|
D,
|
|
83
147
|
SB,
|
|
84
|
-
[...P, Route.Route
|
|
85
|
-
>
|
|
86
|
-
|
|
87
|
-
return
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
},
|
|
96
|
-
}))
|
|
97
|
-
})
|
|
148
|
+
[...P, Route.Route<{}, { searchParams: A }, unknown, ParseResult.ParseError, R | Route.Request>]
|
|
149
|
+
>
|
|
150
|
+
export function schemaSearchParams(fields: SchemaOrFields) {
|
|
151
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
152
|
+
Effect.gen(function* () {
|
|
153
|
+
const request = yield* Route.Request
|
|
154
|
+
const url = new URL(request.url)
|
|
155
|
+
const parsed = yield* decode(Http.mapUrlSearchParams(url.searchParams))
|
|
156
|
+
return { context: { searchParams: { ...ctx.searchParams, ...parsed } } }
|
|
157
|
+
}),
|
|
158
|
+
)(fields)
|
|
98
159
|
}
|
|
99
160
|
|
|
161
|
+
export function schemaPathParams<F extends Schema.Struct.Fields>(
|
|
162
|
+
fields: F,
|
|
163
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
164
|
+
self: Route.RouteSet<D, SB, P>,
|
|
165
|
+
) => Route.RouteSet<
|
|
166
|
+
D,
|
|
167
|
+
SB,
|
|
168
|
+
[
|
|
169
|
+
...P,
|
|
170
|
+
Route.Route<
|
|
171
|
+
{},
|
|
172
|
+
{ pathParams: Types.Simplify<Schema.Struct.Type<F>> },
|
|
173
|
+
unknown,
|
|
174
|
+
ParseResult.ParseError,
|
|
175
|
+
Schema.Struct.Context<F> | Route.Request
|
|
176
|
+
>,
|
|
177
|
+
]
|
|
178
|
+
>
|
|
100
179
|
export function schemaPathParams<A, I extends Readonly<Record<string, string | undefined>>, R>(
|
|
101
180
|
fields: Schema.Schema<A, I, R>,
|
|
102
181
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
103
|
-
self: Route.RouteSet
|
|
104
|
-
) => Route.RouteSet
|
|
182
|
+
self: Route.RouteSet<D, SB, P>,
|
|
183
|
+
) => Route.RouteSet<
|
|
105
184
|
D,
|
|
106
185
|
SB,
|
|
107
|
-
[...P, Route.Route
|
|
108
|
-
>
|
|
109
|
-
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
},
|
|
121
|
-
}))
|
|
122
|
-
})
|
|
186
|
+
[...P, Route.Route<{}, { pathParams: A }, unknown, ParseResult.ParseError, R | Route.Request>]
|
|
187
|
+
>
|
|
188
|
+
export function schemaPathParams(fields: SchemaOrFields) {
|
|
189
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
190
|
+
Effect.gen(function* () {
|
|
191
|
+
const request = yield* Route.Request
|
|
192
|
+
const url = new URL(request.url)
|
|
193
|
+
const pattern = ctx.path ?? "/"
|
|
194
|
+
const params = PathPattern.match(pattern, url.pathname) ?? {}
|
|
195
|
+
const parsed = yield* decode(params)
|
|
196
|
+
return { context: { pathParams: { ...ctx.pathParams, ...parsed } } }
|
|
197
|
+
}),
|
|
198
|
+
)(fields)
|
|
123
199
|
}
|
|
124
200
|
|
|
201
|
+
export function schemaBodyJson<F extends Schema.Struct.Fields>(
|
|
202
|
+
fields: F,
|
|
203
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
204
|
+
self: Route.RouteSet<D, SB, P>,
|
|
205
|
+
) => Route.RouteSet<
|
|
206
|
+
D,
|
|
207
|
+
SB,
|
|
208
|
+
[
|
|
209
|
+
...P,
|
|
210
|
+
Route.Route<
|
|
211
|
+
{},
|
|
212
|
+
{ body: Types.Simplify<Schema.Struct.Type<F>> },
|
|
213
|
+
unknown,
|
|
214
|
+
RequestBodyError | ParseResult.ParseError,
|
|
215
|
+
Schema.Struct.Context<F> | Route.Request
|
|
216
|
+
>,
|
|
217
|
+
]
|
|
218
|
+
>
|
|
125
219
|
export function schemaBodyJson<A, I, R>(
|
|
126
220
|
fields: Schema.Schema<A, I, R>,
|
|
127
221
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
128
|
-
self: Route.RouteSet
|
|
129
|
-
) => Route.RouteSet
|
|
222
|
+
self: Route.RouteSet<D, SB, P>,
|
|
223
|
+
) => Route.RouteSet<
|
|
130
224
|
D,
|
|
131
225
|
SB,
|
|
132
|
-
[...P, Route.Route
|
|
133
|
-
>
|
|
134
|
-
|
|
135
|
-
return
|
|
226
|
+
[...P, Route.Route<{}, { body: A }, unknown, RequestBodyError | ParseResult.ParseError, R | Route.Request>]
|
|
227
|
+
>
|
|
228
|
+
export function schemaBodyJson(fields: SchemaOrFields) {
|
|
229
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
136
230
|
Effect.gen(function* () {
|
|
231
|
+
const request = yield* Route.Request
|
|
137
232
|
const json = yield* Effect.tryPromise({
|
|
138
|
-
try: () =>
|
|
233
|
+
try: () => request.json(),
|
|
139
234
|
catch: (error) => RequestBodyError("JsonError", error),
|
|
140
235
|
})
|
|
141
236
|
const parsed = yield* decode(json)
|
|
142
|
-
return {
|
|
143
|
-
context: {
|
|
144
|
-
body: {
|
|
145
|
-
...ctx.body,
|
|
146
|
-
...parsed,
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
}
|
|
237
|
+
return { context: { body: { ...ctx.body, ...parsed } } }
|
|
150
238
|
}),
|
|
151
|
-
)
|
|
239
|
+
)(fields)
|
|
152
240
|
}
|
|
153
241
|
|
|
242
|
+
export function schemaBodyUrlParams<F extends Schema.Struct.Fields>(
|
|
243
|
+
fields: F,
|
|
244
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
245
|
+
self: Route.RouteSet<D, SB, P>,
|
|
246
|
+
) => Route.RouteSet<
|
|
247
|
+
D,
|
|
248
|
+
SB,
|
|
249
|
+
[
|
|
250
|
+
...P,
|
|
251
|
+
Route.Route<
|
|
252
|
+
{},
|
|
253
|
+
{ body: Types.Simplify<Schema.Struct.Type<F>> },
|
|
254
|
+
unknown,
|
|
255
|
+
RequestBodyError | ParseResult.ParseError,
|
|
256
|
+
Schema.Struct.Context<F> | Route.Request
|
|
257
|
+
>,
|
|
258
|
+
]
|
|
259
|
+
>
|
|
154
260
|
export function schemaBodyUrlParams<
|
|
155
261
|
A,
|
|
156
262
|
I extends Readonly<Record<string, string | ReadonlyArray<string> | undefined>>,
|
|
@@ -158,33 +264,45 @@ export function schemaBodyUrlParams<
|
|
|
158
264
|
>(
|
|
159
265
|
fields: Schema.Schema<A, I, R>,
|
|
160
266
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
161
|
-
self: Route.RouteSet
|
|
162
|
-
) => Route.RouteSet
|
|
267
|
+
self: Route.RouteSet<D, SB, P>,
|
|
268
|
+
) => Route.RouteSet<
|
|
163
269
|
D,
|
|
164
270
|
SB,
|
|
165
|
-
[...P, Route.Route
|
|
166
|
-
>
|
|
167
|
-
|
|
168
|
-
return
|
|
271
|
+
[...P, Route.Route<{}, { body: A }, unknown, RequestBodyError | ParseResult.ParseError, R | Route.Request>]
|
|
272
|
+
>
|
|
273
|
+
export function schemaBodyUrlParams(fields: SchemaOrFields) {
|
|
274
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
169
275
|
Effect.gen(function* () {
|
|
276
|
+
const request = yield* Route.Request
|
|
170
277
|
const text = yield* Effect.tryPromise({
|
|
171
|
-
try: () =>
|
|
278
|
+
try: () => request.text(),
|
|
172
279
|
catch: (error) => RequestBodyError("UrlParamsError", error),
|
|
173
280
|
})
|
|
174
281
|
const params = new URLSearchParams(text)
|
|
175
282
|
const parsed = yield* decode(Http.mapUrlSearchParams(params))
|
|
176
|
-
return {
|
|
177
|
-
context: {
|
|
178
|
-
body: {
|
|
179
|
-
...ctx.body,
|
|
180
|
-
...parsed,
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
}
|
|
283
|
+
return { context: { body: { ...ctx.body, ...parsed } } }
|
|
184
284
|
}),
|
|
185
|
-
)
|
|
285
|
+
)(fields)
|
|
186
286
|
}
|
|
187
287
|
|
|
288
|
+
export function schemaBodyMultipart<F extends Schema.Struct.Fields>(
|
|
289
|
+
fields: F,
|
|
290
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
291
|
+
self: Route.RouteSet<D, SB, P>,
|
|
292
|
+
) => Route.RouteSet<
|
|
293
|
+
D,
|
|
294
|
+
SB,
|
|
295
|
+
[
|
|
296
|
+
...P,
|
|
297
|
+
Route.Route<
|
|
298
|
+
{},
|
|
299
|
+
{ body: Types.Simplify<Schema.Struct.Type<F>> },
|
|
300
|
+
unknown,
|
|
301
|
+
RequestBodyError | ParseResult.ParseError,
|
|
302
|
+
Schema.Struct.Context<F> | Route.Request | Scope.Scope
|
|
303
|
+
>,
|
|
304
|
+
]
|
|
305
|
+
>
|
|
188
306
|
export function schemaBodyMultipart<
|
|
189
307
|
A,
|
|
190
308
|
I extends Partial<Record<string, ReadonlyArray<Http.FilePart> | ReadonlyArray<string> | string>>,
|
|
@@ -192,41 +310,53 @@ export function schemaBodyMultipart<
|
|
|
192
310
|
>(
|
|
193
311
|
fields: Schema.Schema<A, I, R>,
|
|
194
312
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
195
|
-
self: Route.RouteSet
|
|
196
|
-
) => Route.RouteSet
|
|
313
|
+
self: Route.RouteSet<D, SB, P>,
|
|
314
|
+
) => Route.RouteSet<
|
|
197
315
|
D,
|
|
198
316
|
SB,
|
|
199
317
|
[
|
|
200
318
|
...P,
|
|
201
|
-
Route.Route
|
|
319
|
+
Route.Route<
|
|
202
320
|
{},
|
|
203
321
|
{ body: A },
|
|
204
322
|
unknown,
|
|
205
323
|
RequestBodyError | ParseResult.ParseError,
|
|
206
|
-
R | Scope.Scope
|
|
324
|
+
R | Route.Request | Scope.Scope
|
|
207
325
|
>,
|
|
208
326
|
]
|
|
209
|
-
>
|
|
210
|
-
|
|
211
|
-
return
|
|
327
|
+
>
|
|
328
|
+
export function schemaBodyMultipart(fields: SchemaOrFields) {
|
|
329
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
212
330
|
Effect.gen(function* () {
|
|
331
|
+
const request = yield* Route.Request
|
|
213
332
|
const record = yield* Effect.tryPromise({
|
|
214
|
-
try: () => Http.parseFormData(
|
|
333
|
+
try: () => Http.parseFormData(request),
|
|
215
334
|
catch: (error) => RequestBodyError("MultipartError", error),
|
|
216
335
|
})
|
|
217
336
|
const parsed = yield* decode(record)
|
|
218
|
-
return {
|
|
219
|
-
context: {
|
|
220
|
-
body: {
|
|
221
|
-
...ctx.body,
|
|
222
|
-
...parsed,
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
}
|
|
337
|
+
return { context: { body: { ...ctx.body, ...parsed } } }
|
|
226
338
|
}),
|
|
227
|
-
)
|
|
339
|
+
)(fields)
|
|
228
340
|
}
|
|
229
341
|
|
|
342
|
+
export function schemaBodyForm<F extends Schema.Struct.Fields>(
|
|
343
|
+
fields: F,
|
|
344
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
345
|
+
self: Route.RouteSet<D, SB, P>,
|
|
346
|
+
) => Route.RouteSet<
|
|
347
|
+
D,
|
|
348
|
+
SB,
|
|
349
|
+
[
|
|
350
|
+
...P,
|
|
351
|
+
Route.Route<
|
|
352
|
+
{},
|
|
353
|
+
{ body: Types.Simplify<Schema.Struct.Type<F>> },
|
|
354
|
+
unknown,
|
|
355
|
+
RequestBodyError | ParseResult.ParseError,
|
|
356
|
+
Schema.Struct.Context<F> | Route.Request | Scope.Scope
|
|
357
|
+
>,
|
|
358
|
+
]
|
|
359
|
+
>
|
|
230
360
|
export function schemaBodyForm<
|
|
231
361
|
A,
|
|
232
362
|
I extends Partial<Record<string, ReadonlyArray<Http.FilePart> | ReadonlyArray<string> | string>>,
|
|
@@ -234,59 +364,46 @@ export function schemaBodyForm<
|
|
|
234
364
|
>(
|
|
235
365
|
fields: Schema.Schema<A, I, R>,
|
|
236
366
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
237
|
-
self: Route.RouteSet
|
|
238
|
-
) => Route.RouteSet
|
|
367
|
+
self: Route.RouteSet<D, SB, P>,
|
|
368
|
+
) => Route.RouteSet<
|
|
239
369
|
D,
|
|
240
370
|
SB,
|
|
241
371
|
[
|
|
242
372
|
...P,
|
|
243
|
-
Route.Route
|
|
373
|
+
Route.Route<
|
|
244
374
|
{},
|
|
245
375
|
{ body: A },
|
|
246
376
|
unknown,
|
|
247
377
|
RequestBodyError | ParseResult.ParseError,
|
|
248
|
-
R | Scope.Scope
|
|
378
|
+
R | Route.Request | Scope.Scope
|
|
249
379
|
>,
|
|
250
380
|
]
|
|
251
|
-
>
|
|
252
|
-
|
|
253
|
-
return
|
|
381
|
+
>
|
|
382
|
+
export function schemaBodyForm(fields: SchemaOrFields) {
|
|
383
|
+
return makeSchemaFilter((ctx, decode) =>
|
|
254
384
|
Effect.gen(function* () {
|
|
255
|
-
const
|
|
385
|
+
const request = yield* Route.Request
|
|
386
|
+
const contentType = request.headers.get("content-type") ?? ""
|
|
256
387
|
|
|
257
388
|
if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
258
389
|
const text = yield* Effect.tryPromise({
|
|
259
|
-
try: () =>
|
|
390
|
+
try: () => request.text(),
|
|
260
391
|
catch: (error) => RequestBodyError("UrlParamsError", error),
|
|
261
392
|
})
|
|
262
393
|
const params = new URLSearchParams(text)
|
|
263
394
|
const record = Http.mapUrlSearchParams(params)
|
|
264
|
-
const parsed = yield* decode(record as
|
|
265
|
-
return {
|
|
266
|
-
context: {
|
|
267
|
-
body: {
|
|
268
|
-
...ctx.body,
|
|
269
|
-
...parsed,
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
}
|
|
395
|
+
const parsed = yield* decode(record as any)
|
|
396
|
+
return { context: { body: { ...ctx.body, ...parsed } } }
|
|
273
397
|
}
|
|
274
398
|
|
|
275
399
|
const record = yield* Effect.tryPromise({
|
|
276
|
-
try: () => Http.parseFormData(
|
|
400
|
+
try: () => Http.parseFormData(request),
|
|
277
401
|
catch: (error) => RequestBodyError("FormDataError", error),
|
|
278
402
|
})
|
|
279
|
-
const parsed = yield* decode(record as
|
|
280
|
-
return {
|
|
281
|
-
context: {
|
|
282
|
-
body: {
|
|
283
|
-
...ctx.body,
|
|
284
|
-
...parsed,
|
|
285
|
-
},
|
|
286
|
-
},
|
|
287
|
-
}
|
|
403
|
+
const parsed = yield* decode(record as any)
|
|
404
|
+
return { context: { body: { ...ctx.body, ...parsed } } }
|
|
288
405
|
}),
|
|
289
|
-
)
|
|
406
|
+
)(fields)
|
|
290
407
|
}
|
|
291
408
|
|
|
292
409
|
/**
|
|
@@ -303,20 +420,20 @@ export function schemaBodyForm<
|
|
|
303
420
|
export function schemaError<A, I, R>(
|
|
304
421
|
schema: Schema.Schema<A, I, R> & { readonly status: number },
|
|
305
422
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
306
|
-
self: Route.RouteSet
|
|
307
|
-
) => Route.RouteSet
|
|
423
|
+
self: Route.RouteSet<D, SB, P>,
|
|
424
|
+
) => Route.RouteSet<D, SB, [...P, Route.Route<{}, {}, unknown, never, R>]>
|
|
308
425
|
export function schemaError<A, I, R>(
|
|
309
426
|
schema: Schema.Schema<A, I, R>,
|
|
310
427
|
options: { readonly status: number },
|
|
311
428
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
312
|
-
self: Route.RouteSet
|
|
313
|
-
) => Route.RouteSet
|
|
429
|
+
self: Route.RouteSet<D, SB, P>,
|
|
430
|
+
) => Route.RouteSet<D, SB, [...P, Route.Route<{}, {}, unknown, never, R>]>
|
|
314
431
|
export function schemaError<A, I, R>(
|
|
315
432
|
schema: Schema.Schema<A, I, R> & { readonly status?: number },
|
|
316
433
|
options?: { readonly status: number },
|
|
317
434
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
318
|
-
self: Route.RouteSet
|
|
319
|
-
) => Route.RouteSet
|
|
435
|
+
self: Route.RouteSet<D, SB, P>,
|
|
436
|
+
) => Route.RouteSet<D, SB, [...P, Route.Route<{}, {}, unknown, never, R>]> {
|
|
320
437
|
const status = options?.status ?? (schema as any).status
|
|
321
438
|
if (typeof status !== "number") {
|
|
322
439
|
throw new Error(
|
|
@@ -326,8 +443,8 @@ export function schemaError<A, I, R>(
|
|
|
326
443
|
const encode = Schema.encode(schema)
|
|
327
444
|
const is = Schema.is(schema)
|
|
328
445
|
return function <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
329
|
-
self: Route.RouteSet
|
|
330
|
-
): Route.RouteSet
|
|
446
|
+
self: Route.RouteSet<D, SB, P>,
|
|
447
|
+
): Route.RouteSet<D, SB, [...P, Route.Route<{}, {}, unknown, never, R>]> {
|
|
331
448
|
const route = Route.make<{}, {}, unknown, never, R>((_context, next) =>
|
|
332
449
|
Entity.resolve(next()).pipe(
|
|
333
450
|
Effect.catchIf(is, (error) =>
|
|
@@ -336,7 +453,7 @@ export function schemaError<A, I, R>(
|
|
|
336
453
|
),
|
|
337
454
|
)
|
|
338
455
|
|
|
339
|
-
const items: [...P, Route.Route
|
|
456
|
+
const items: [...P, Route.Route<{}, {}, unknown, never, R>] = [
|
|
340
457
|
...Route.items(self),
|
|
341
458
|
route,
|
|
342
459
|
]
|
|
@@ -345,24 +462,40 @@ export function schemaError<A, I, R>(
|
|
|
345
462
|
}
|
|
346
463
|
}
|
|
347
464
|
|
|
465
|
+
export function schemaSuccess<F extends Schema.Struct.Fields>(
|
|
466
|
+
fields: F,
|
|
467
|
+
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
468
|
+
self: Route.RouteSet<D, SB, P>,
|
|
469
|
+
) => Route.RouteSet<
|
|
470
|
+
D,
|
|
471
|
+
SB,
|
|
472
|
+
[
|
|
473
|
+
...P,
|
|
474
|
+
Route.Route<
|
|
475
|
+
{},
|
|
476
|
+
{},
|
|
477
|
+
Types.Simplify<Schema.Struct.Encoded<F>>,
|
|
478
|
+
ParseResult.ParseError,
|
|
479
|
+
Schema.Struct.Context<F>
|
|
480
|
+
>,
|
|
481
|
+
]
|
|
482
|
+
>
|
|
348
483
|
export function schemaSuccess<A, I, R>(
|
|
349
484
|
schema: Schema.Schema<A, I, R>,
|
|
350
485
|
): <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
|
|
351
|
-
self: Route.RouteSet
|
|
352
|
-
) => Route.RouteSet
|
|
486
|
+
self: Route.RouteSet<D, SB, P>,
|
|
487
|
+
) => Route.RouteSet<
|
|
353
488
|
D,
|
|
354
489
|
SB,
|
|
355
|
-
[...P, Route.Route
|
|
356
|
-
>
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
> {
|
|
365
|
-
const route = Route.make<{}, {}, I, ParseResult.ParseError, R>((_context, next) =>
|
|
490
|
+
[...P, Route.Route<{}, {}, I, ParseResult.ParseError, R>]
|
|
491
|
+
>
|
|
492
|
+
export function schemaSuccess(
|
|
493
|
+
schema: SchemaOrFields,
|
|
494
|
+
): any {
|
|
495
|
+
const s = toSchema(schema)
|
|
496
|
+
const encode = Schema.encodeUnknown(s)
|
|
497
|
+
return function(self: Route.RouteSet<any, any, any>) {
|
|
498
|
+
const route = Route.make((_context: any, next: any) =>
|
|
366
499
|
Effect.flatMap(Entity.resolve(next()), (entity) =>
|
|
367
500
|
Effect.map(encode(entity.body), (encoded) =>
|
|
368
501
|
Entity.make(encoded, {
|
|
@@ -374,11 +507,11 @@ export function schemaSuccess<A, I, R>(
|
|
|
374
507
|
),
|
|
375
508
|
)
|
|
376
509
|
|
|
377
|
-
const items
|
|
510
|
+
const items = [
|
|
378
511
|
...Route.items(self),
|
|
379
512
|
route,
|
|
380
513
|
]
|
|
381
514
|
|
|
382
|
-
return Route.set(items, Route.descriptor(self))
|
|
515
|
+
return Route.set(items as any, Route.descriptor(self))
|
|
383
516
|
}
|
|
384
517
|
}
|
package/src/RouteSse.ts
CHANGED
|
@@ -65,7 +65,7 @@ export function sse<
|
|
|
65
65
|
E = never,
|
|
66
66
|
R = never,
|
|
67
67
|
>(handler: SseHandlerInput<NoInfer<D & B & Route.ExtractBindings<I> & { format: "sse" }>, E, R>) {
|
|
68
|
-
return function (self: Route.RouteSet
|
|
68
|
+
return function (self: Route.RouteSet<D, B, I>) {
|
|
69
69
|
const sseHandler: Route.Route.Handler<
|
|
70
70
|
D & B & Route.ExtractBindings<I> & { format: "sse" },
|
|
71
71
|
Stream.Stream<string, E, R>,
|
|
@@ -120,13 +120,13 @@ export function sse<
|
|
|
120
120
|
|
|
121
121
|
const items: [
|
|
122
122
|
...I,
|
|
123
|
-
Route.Route
|
|
123
|
+
Route.Route<{ format: "sse" }, {}, Stream.Stream<string, E, R>, E, R>,
|
|
124
124
|
] = [...Route.items(self), route]
|
|
125
125
|
|
|
126
126
|
return Route.set<
|
|
127
127
|
D,
|
|
128
128
|
B,
|
|
129
|
-
[...I, Route.Route
|
|
129
|
+
[...I, Route.Route<{ format: "sse" }, {}, Stream.Stream<string, E, R>, E, R>]
|
|
130
130
|
>(items, Route.descriptor(self))
|
|
131
131
|
}
|
|
132
132
|
}
|
package/src/Start.ts
CHANGED
|
@@ -141,7 +141,7 @@ export function build<const Layers extends readonly [Layer.Layer.Any, ...Array<L
|
|
|
141
141
|
map.delete(layer)
|
|
142
142
|
return map
|
|
143
143
|
})
|
|
144
|
-
if (Cause.
|
|
144
|
+
if (Cause.isInterruptedOnly(exit.cause)) {
|
|
145
145
|
return yield* exit
|
|
146
146
|
}
|
|
147
147
|
}
|