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.
Files changed (127) hide show
  1. package/README.md +303 -36
  2. package/dist/Fetch.d.ts +1 -1
  3. package/dist/FileRouter.d.ts +1 -1
  4. package/dist/FileRouterCodegen.d.ts.map +1 -1
  5. package/dist/FileRouterCodegen.js +8 -2
  6. package/dist/FileRouterCodegen.js.map +1 -1
  7. package/dist/Job.d.ts +94 -0
  8. package/dist/Job.d.ts.map +1 -0
  9. package/dist/Job.js +157 -0
  10. package/dist/Job.js.map +1 -0
  11. package/dist/Password.d.ts +1 -1
  12. package/dist/Route.d.ts +20 -15
  13. package/dist/Route.d.ts.map +1 -1
  14. package/dist/Route.js +12 -0
  15. package/dist/Route.js.map +1 -1
  16. package/dist/RouteBody.d.ts +7 -7
  17. package/dist/RouteBody.d.ts.map +1 -1
  18. package/dist/RouteBody.js.map +1 -1
  19. package/dist/RouteHook.d.ts +1 -1
  20. package/dist/RouteHook.d.ts.map +1 -1
  21. package/dist/RouteHook.js.map +1 -1
  22. package/dist/RouteHttp.d.ts.map +1 -1
  23. package/dist/RouteHttp.js +10 -4
  24. package/dist/RouteHttp.js.map +1 -1
  25. package/dist/RouteLink.d.ts +16 -0
  26. package/dist/RouteLink.d.ts.map +1 -0
  27. package/dist/RouteLink.js +23 -0
  28. package/dist/RouteLink.js.map +1 -0
  29. package/dist/RouteMount.d.ts +29 -32
  30. package/dist/RouteMount.d.ts.map +1 -1
  31. package/dist/RouteMount.js.map +1 -1
  32. package/dist/RouteSchema.d.ts +81 -28
  33. package/dist/RouteSchema.d.ts.map +1 -1
  34. package/dist/RouteSchema.js +56 -101
  35. package/dist/RouteSchema.js.map +1 -1
  36. package/dist/RouteSse.d.ts +1 -1
  37. package/dist/RouteSse.d.ts.map +1 -1
  38. package/dist/RouteSse.js.map +1 -1
  39. package/dist/Socket.d.ts +1 -1
  40. package/dist/Start.js +1 -1
  41. package/dist/Start.js.map +1 -1
  42. package/dist/StaticFiles.d.ts +4 -10
  43. package/dist/StaticFiles.d.ts.map +1 -1
  44. package/dist/StaticFiles.js +3 -10
  45. package/dist/StaticFiles.js.map +1 -1
  46. package/dist/System.d.ts +1 -1
  47. package/dist/_Docker.d.ts +1 -1
  48. package/dist/_HtmlScanner.d.ts +42 -0
  49. package/dist/_HtmlScanner.d.ts.map +1 -0
  50. package/dist/_HtmlScanner.js +385 -0
  51. package/dist/_HtmlScanner.js.map +1 -0
  52. package/dist/_RouteLink.d.ts +16 -0
  53. package/dist/_RouteLink.d.ts.map +1 -0
  54. package/dist/_RouteLink.js +22 -0
  55. package/dist/_RouteLink.js.map +1 -0
  56. package/dist/bun/BunRoute.d.ts +4 -6
  57. package/dist/bun/BunRoute.d.ts.map +1 -1
  58. package/dist/bun/BunRoute.js +1 -1
  59. package/dist/bun/BunRoute.js.map +1 -1
  60. package/dist/bundler/Bundle.d.ts +1 -1
  61. package/dist/bundler/BundleRoute.d.ts +5 -6
  62. package/dist/bundler/BundleRoute.d.ts.map +1 -1
  63. package/dist/bundler/BundleRoute.js +5 -11
  64. package/dist/bundler/BundleRoute.js.map +1 -1
  65. package/dist/datastar/watchers/patchElements.js +1 -1
  66. package/dist/datastar/watchers/patchElements.js.map +1 -1
  67. package/dist/experimental/CsrfProtection.d.ts +67 -0
  68. package/dist/experimental/CsrfProtection.d.ts.map +1 -0
  69. package/dist/experimental/CsrfProtection.js +100 -0
  70. package/dist/experimental/CsrfProtection.js.map +1 -0
  71. package/dist/experimental/EncryptedCookies.d.ts +1 -1
  72. package/dist/experimental/KeyValueStore.d.ts +1 -1
  73. package/dist/lint/plugin.js +4 -0
  74. package/dist/lint/plugin.js.map +1 -1
  75. package/dist/sql/SqlClient.d.ts +1 -1
  76. package/dist/studio/Studio.d.ts +1 -1
  77. package/dist/studio/Studio.d.ts.map +1 -1
  78. package/dist/studio/Studio.js +4 -10
  79. package/dist/studio/Studio.js.map +1 -1
  80. package/dist/studio/routes/errors/route.d.ts +3 -3
  81. package/dist/studio/routes/errors/route.d.ts.map +1 -1
  82. package/dist/studio/routes/errors/route.js +3 -2
  83. package/dist/studio/routes/errors/route.js.map +1 -1
  84. package/dist/studio/routes/fiberDetail.d.ts +3 -7
  85. package/dist/studio/routes/fiberDetail.d.ts.map +1 -1
  86. package/dist/studio/routes/fibers/route.d.ts +3 -3
  87. package/dist/studio/routes/layout.d.ts +3 -3
  88. package/dist/studio/routes/logs/route.d.ts +3 -3
  89. package/dist/studio/routes/logs/route.d.ts.map +1 -1
  90. package/dist/studio/routes/logs/route.js +3 -2
  91. package/dist/studio/routes/logs/route.js.map +1 -1
  92. package/dist/studio/routes/metrics/route.d.ts +3 -3
  93. package/dist/studio/routes/route.d.ts +2 -2
  94. package/dist/studio/routes/routes/route.d.ts +2 -2
  95. package/dist/studio/routes/services/route.d.ts +2 -2
  96. package/dist/studio/routes/system/route.d.ts +3 -3
  97. package/dist/studio/routes/traceDetail.d.ts +3 -7
  98. package/dist/studio/routes/traceDetail.d.ts.map +1 -1
  99. package/dist/studio/routes/traces/route.d.ts +3 -3
  100. package/dist/studio/routes/traces/route.d.ts.map +1 -1
  101. package/dist/studio/routes/traces/route.js +3 -2
  102. package/dist/studio/routes/traces/route.js.map +1 -1
  103. package/dist/studio/routes/tree.d.ts +43 -51
  104. package/dist/studio/routes/tree.d.ts.map +1 -1
  105. package/package.json +4 -3
  106. package/src/FileRouterCodegen.ts +8 -2
  107. package/src/Route.ts +55 -34
  108. package/src/RouteBody.ts +15 -15
  109. package/src/RouteHook.ts +3 -3
  110. package/src/RouteHttp.ts +10 -4
  111. package/src/RouteLink.ts +56 -0
  112. package/src/RouteMount.ts +43 -48
  113. package/src/RouteSchema.ts +299 -166
  114. package/src/RouteSse.ts +3 -3
  115. package/src/Start.ts +1 -1
  116. package/src/StaticFiles.ts +10 -24
  117. package/src/_HtmlScanner.ts +415 -0
  118. package/src/bun/BunRoute.ts +11 -11
  119. package/src/bundler/BundleRoute.ts +8 -19
  120. package/src/datastar/watchers/patchElements.ts +1 -1
  121. package/src/dev.d.ts +3 -0
  122. package/src/experimental/CsrfProtection.ts +153 -0
  123. package/src/lint/plugin.js +2 -0
  124. package/src/studio/Studio.ts +4 -14
  125. package/src/studio/routes/errors/route.tsx +3 -2
  126. package/src/studio/routes/logs/route.tsx +3 -2
  127. package/src/studio/routes/traces/route.tsx +3 -2
@@ -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.RouteSet<D, SB, P>,
33
- ) => Route.RouteSet.RouteSet<
66
+ self: Route.RouteSet<D, SB, P>,
67
+ ) => Route.RouteSet<
34
68
  D,
35
69
  SB,
36
- [...P, Route.Route.Route<{}, { headers: A }, unknown, ParseResult.ParseError, R>]
37
- > {
38
- const decode = Schema.decodeUnknown(fields)
39
- return RouteHook.filter((ctx: { request: Request; headers?: {} }) =>
40
- Effect.map(decode(Http.mapHeaders(ctx.request.headers)), (parsed) => ({
41
- context: {
42
- headers: {
43
- ...ctx.headers,
44
- ...parsed,
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.RouteSet<D, SB, P>,
55
- ) => Route.RouteSet.RouteSet<
103
+ self: Route.RouteSet<D, SB, P>,
104
+ ) => Route.RouteSet<
56
105
  D,
57
106
  SB,
58
- [...P, Route.Route.Route<{}, { cookies: A }, unknown, ParseResult.ParseError, R>]
59
- > {
60
- const decode = Schema.decodeUnknown(fields)
61
- return RouteHook.filter((ctx: { request: Request; cookies?: {} }) =>
62
- Effect.map(decode(Http.parseCookies(ctx.request.headers.get("cookie"))), (parsed) => ({
63
- context: {
64
- cookies: {
65
- ...ctx.cookies,
66
- ...parsed,
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.RouteSet<D, SB, P>,
81
- ) => Route.RouteSet.RouteSet<
144
+ self: Route.RouteSet<D, SB, P>,
145
+ ) => Route.RouteSet<
82
146
  D,
83
147
  SB,
84
- [...P, Route.Route.Route<{}, { searchParams: A }, unknown, ParseResult.ParseError, R>]
85
- > {
86
- const decode = Schema.decodeUnknown(fields)
87
- return RouteHook.filter((ctx: { request: Request; searchParams?: {} }) => {
88
- const url = new URL(ctx.request.url)
89
- return Effect.map(decode(Http.mapUrlSearchParams(url.searchParams)), (parsed) => ({
90
- context: {
91
- searchParams: {
92
- ...ctx.searchParams,
93
- ...parsed,
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.RouteSet<D, SB, P>,
104
- ) => Route.RouteSet.RouteSet<
182
+ self: Route.RouteSet<D, SB, P>,
183
+ ) => Route.RouteSet<
105
184
  D,
106
185
  SB,
107
- [...P, Route.Route.Route<{}, { pathParams: A }, unknown, ParseResult.ParseError, R>]
108
- > {
109
- const decode = Schema.decodeUnknown(fields)
110
- return RouteHook.filter((ctx: { request: Request; path?: string; pathParams?: {} }) => {
111
- const url = new URL(ctx.request.url)
112
- const pattern = ctx.path ?? "/"
113
- const params = PathPattern.match(pattern, url.pathname) ?? {}
114
- return Effect.map(decode(params), (parsed) => ({
115
- context: {
116
- pathParams: {
117
- ...ctx.pathParams,
118
- ...parsed,
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.RouteSet<D, SB, P>,
129
- ) => Route.RouteSet.RouteSet<
222
+ self: Route.RouteSet<D, SB, P>,
223
+ ) => Route.RouteSet<
130
224
  D,
131
225
  SB,
132
- [...P, Route.Route.Route<{}, { body: A }, unknown, RequestBodyError | ParseResult.ParseError, R>]
133
- > {
134
- const decode = Schema.decodeUnknown(fields)
135
- return RouteHook.filter((ctx: { request: Request; body?: {} }) =>
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: () => ctx.request.json(),
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.RouteSet<D, SB, P>,
162
- ) => Route.RouteSet.RouteSet<
267
+ self: Route.RouteSet<D, SB, P>,
268
+ ) => Route.RouteSet<
163
269
  D,
164
270
  SB,
165
- [...P, Route.Route.Route<{}, { body: A }, unknown, RequestBodyError | ParseResult.ParseError, R>]
166
- > {
167
- const decode = Schema.decodeUnknown(fields)
168
- return RouteHook.filter((ctx: { request: Request; body?: {} }) =>
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: () => ctx.request.text(),
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.RouteSet<D, SB, P>,
196
- ) => Route.RouteSet.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.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
- const decode = Schema.decodeUnknown(fields)
211
- return RouteHook.filter((ctx: { request: Request; body?: {} }) =>
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(ctx.request),
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.RouteSet<D, SB, P>,
238
- ) => Route.RouteSet.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.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
- const decode = Schema.decodeUnknown(fields)
253
- return RouteHook.filter((ctx: { request: Request; body?: {} }) =>
381
+ >
382
+ export function schemaBodyForm(fields: SchemaOrFields) {
383
+ return makeSchemaFilter((ctx, decode) =>
254
384
  Effect.gen(function* () {
255
- const contentType = ctx.request.headers.get("content-type") ?? ""
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: () => ctx.request.text(),
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 I)
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(ctx.request),
400
+ try: () => Http.parseFormData(request),
277
401
  catch: (error) => RequestBodyError("FormDataError", error),
278
402
  })
279
- const parsed = yield* decode(record as I)
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.RouteSet<D, SB, P>,
307
- ) => Route.RouteSet.RouteSet<D, SB, [...P, Route.Route.Route<{}, {}, unknown, never, R>]>
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.RouteSet<D, SB, P>,
313
- ) => Route.RouteSet.RouteSet<D, SB, [...P, Route.Route.Route<{}, {}, unknown, never, R>]>
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.RouteSet<D, SB, P>,
319
- ) => Route.RouteSet.RouteSet<D, SB, [...P, Route.Route.Route<{}, {}, unknown, never, R>]> {
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.RouteSet<D, SB, P>,
330
- ): Route.RouteSet.RouteSet<D, SB, [...P, Route.Route.Route<{}, {}, unknown, never, R>]> {
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.Route<{}, {}, unknown, never, R>] = [
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.RouteSet<D, SB, P>,
352
- ) => Route.RouteSet.RouteSet<
486
+ self: Route.RouteSet<D, SB, P>,
487
+ ) => Route.RouteSet<
353
488
  D,
354
489
  SB,
355
- [...P, Route.Route.Route<{}, {}, I, ParseResult.ParseError, R>]
356
- > {
357
- const encode = Schema.encodeUnknown(schema)
358
- return function <D extends Route.RouteDescriptor.Any, SB extends {}, P extends Route.Route.Tuple>(
359
- self: Route.RouteSet.RouteSet<D, SB, P>,
360
- ): Route.RouteSet.RouteSet<
361
- D,
362
- SB,
363
- [...P, Route.Route.Route<{}, {}, I, ParseResult.ParseError, R>]
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: [...P, Route.Route.Route<{}, {}, I, ParseResult.ParseError, R>] = [
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.RouteSet<D, B, I>) {
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.Route<{ format: "sse" }, {}, Stream.Stream<string, E, R>, E, R>,
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.Route<{ format: "sse" }, {}, Stream.Stream<string, E, R>, E, R>]
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.isDie(exit.cause) || Cause.isInterruptedOnly(exit.cause)) {
144
+ if (Cause.isInterruptedOnly(exit.cause)) {
145
145
  return yield* exit
146
146
  }
147
147
  }