@effect/platform 0.13.2 → 0.13.4
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/Http/Body.d.ts +8 -1
- package/Http/Body.d.ts.map +1 -1
- package/Http/Body.js +7 -1
- package/Http/Body.js.map +1 -1
- package/Http/Client.d.ts +11 -0
- package/Http/Client.d.ts.map +1 -1
- package/Http/Client.js +7 -1
- package/Http/Client.js.map +1 -1
- package/Http/Etag.d.ts +56 -0
- package/Http/Etag.d.ts.map +1 -0
- package/Http/Etag.js +28 -0
- package/Http/Etag.js.map +1 -0
- package/Http/Middleware.d.ts +0 -8
- package/Http/Middleware.d.ts.map +1 -1
- package/Http/Middleware.js +2 -8
- package/Http/Middleware.js.map +1 -1
- package/Http/Router.d.ts +90 -0
- package/Http/Router.d.ts.map +1 -1
- package/Http/Router.js +43 -1
- package/Http/Router.js.map +1 -1
- package/Http/ServerResponse.d.ts +2 -1
- package/Http/ServerResponse.d.ts.map +1 -1
- package/Http/ServerResponse.js.map +1 -1
- package/internal/http/body.js +6 -2
- package/internal/http/body.js.map +1 -1
- package/internal/http/client.d.ts.map +1 -1
- package/internal/http/client.js +6 -2
- package/internal/http/client.js.map +1 -1
- package/internal/http/etag.d.ts +2 -0
- package/internal/http/etag.d.ts.map +1 -0
- package/internal/http/etag.js +26 -0
- package/internal/http/etag.js.map +1 -0
- package/internal/http/middleware.js +2 -5
- package/internal/http/middleware.js.map +1 -1
- package/internal/http/router.d.ts +3 -1
- package/internal/http/router.d.ts.map +1 -1
- package/internal/http/router.js +22 -2
- package/internal/http/router.js.map +1 -1
- package/internal/http/server.js +1 -1
- package/internal/http/server.js.map +1 -1
- package/internal/http/serverResponse.js +20 -1
- package/internal/http/serverResponse.js.map +1 -1
- package/mjs/Http/Body.mjs +5 -0
- package/mjs/Http/Body.mjs.map +1 -1
- package/mjs/Http/Client.mjs +5 -0
- package/mjs/Http/Client.mjs.map +1 -1
- package/mjs/Http/Etag.mjs +17 -0
- package/mjs/Http/Etag.mjs.map +1 -0
- package/mjs/Http/Middleware.mjs +0 -5
- package/mjs/Http/Middleware.mjs.map +1 -1
- package/mjs/Http/Router.mjs +35 -0
- package/mjs/Http/Router.mjs.map +1 -1
- package/mjs/Http/ServerResponse.mjs.map +1 -1
- package/mjs/internal/http/body.mjs +4 -1
- package/mjs/internal/http/body.mjs.map +1 -1
- package/mjs/internal/http/client.mjs +4 -1
- package/mjs/internal/http/client.mjs.map +1 -1
- package/mjs/internal/http/etag.mjs +15 -0
- package/mjs/internal/http/etag.mjs.map +1 -0
- package/mjs/internal/http/middleware.mjs +2 -4
- package/mjs/internal/http/middleware.mjs.map +1 -1
- package/mjs/internal/http/router.mjs +14 -1
- package/mjs/internal/http/router.mjs.map +1 -1
- package/mjs/internal/http/server.mjs +1 -1
- package/mjs/internal/http/server.mjs.map +1 -1
- package/mjs/internal/http/serverResponse.mjs +20 -1
- package/mjs/internal/http/serverResponse.mjs.map +1 -1
- package/package.json +2 -1
- package/src/Http/Body.ts +16 -1
- package/src/Http/Client.ts +13 -0
- package/src/Http/Etag.ts +64 -0
- package/src/Http/Middleware.ts +0 -14
- package/src/Http/Router.ts +148 -0
- package/src/Http/ServerResponse.ts +2 -1
- package/src/internal/http/body.ts +22 -3
- package/src/internal/http/client.ts +5 -1
- package/src/internal/http/etag.ts +20 -0
- package/src/internal/http/middleware.ts +2 -16
- package/src/internal/http/router.ts +129 -1
- package/src/internal/http/server.ts +1 -1
- package/src/internal/http/serverResponse.ts +32 -10
package/src/Http/Router.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type * as Chunk from "@effect/data/Chunk"
|
|
5
5
|
import type * as Context from "@effect/data/Context"
|
|
6
6
|
import type * as Option from "@effect/data/Option"
|
|
7
|
+
import type * as Cause from "@effect/io/Cause"
|
|
7
8
|
import type * as Effect from "@effect/io/Effect"
|
|
8
9
|
import type * as App from "@effect/platform/Http/App"
|
|
9
10
|
import type * as Method from "@effect/platform/Http/Method"
|
|
@@ -340,3 +341,150 @@ export const options: {
|
|
|
340
341
|
handler: Route.Handler<R1, E1>
|
|
341
342
|
): Router<R | Exclude<R1, RouteContext>, E | E1>
|
|
342
343
|
} = internal.options
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @since 1.0.0
|
|
347
|
+
* @category combinators
|
|
348
|
+
*/
|
|
349
|
+
export const use = internal.use
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @since 1.0.0
|
|
353
|
+
* @category combinators
|
|
354
|
+
*/
|
|
355
|
+
export const catchAll: {
|
|
356
|
+
<E, R2, E2>(f: (e: E) => Route.Handler<R2, E2>): <R>(
|
|
357
|
+
self: Router<R, E>
|
|
358
|
+
) => Router<R2 | R, E2>
|
|
359
|
+
<R, E, R2, E2>(
|
|
360
|
+
self: Router<R, E>,
|
|
361
|
+
f: (e: E) => Route.Handler<R2, E2>
|
|
362
|
+
): Router<R | R2, E2>
|
|
363
|
+
} = internal.catchAll
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @since 1.0.0
|
|
367
|
+
* @category combinators
|
|
368
|
+
*/
|
|
369
|
+
export const catchAllCause: {
|
|
370
|
+
<E, R2, E2>(f: (e: Cause.Cause<E>) => Route.Handler<R2, E2>): <R>(
|
|
371
|
+
self: Router<R, E>
|
|
372
|
+
) => Router<R2 | R, E2>
|
|
373
|
+
<R, E, R2, E2>(
|
|
374
|
+
self: Router<R, E>,
|
|
375
|
+
f: (e: Cause.Cause<E>) => Route.Handler<R2, E2>
|
|
376
|
+
): Router<R | R2, E2>
|
|
377
|
+
} = internal.catchAllCause
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* @since 1.0.0
|
|
381
|
+
* @category combinators
|
|
382
|
+
*/
|
|
383
|
+
export const catchTag: {
|
|
384
|
+
<K extends E extends { _tag: string } ? E["_tag"] : never, E, R1, E1>(
|
|
385
|
+
k: K,
|
|
386
|
+
f: (e: Extract<E, { _tag: K }>) => Route.Handler<R1, E1>
|
|
387
|
+
): <R>(self: Router<R, E>) => Router<R1 | R, E1 | Exclude<E, { _tag: K }>>
|
|
388
|
+
<R, E, K extends E extends { _tag: string } ? E["_tag"] : never, R1, E1>(
|
|
389
|
+
self: Router<R, E>,
|
|
390
|
+
k: K,
|
|
391
|
+
f: (e: Extract<E, { _tag: K }>) => Route.Handler<R1, E1>
|
|
392
|
+
): Router<R | R1, E1 | Exclude<E, { _tag: K }>>
|
|
393
|
+
} = internal.catchTag
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* @since 1.0.0
|
|
397
|
+
* @category combinators
|
|
398
|
+
*/
|
|
399
|
+
export const catchTags: {
|
|
400
|
+
<
|
|
401
|
+
E,
|
|
402
|
+
Cases extends E extends { _tag: string } ? {
|
|
403
|
+
[K in E["_tag"]]+?:
|
|
404
|
+
| ((error: Extract<E, { _tag: K }>) => Route.Handler<any, any>)
|
|
405
|
+
| undefined
|
|
406
|
+
}
|
|
407
|
+
: {}
|
|
408
|
+
>(
|
|
409
|
+
cases: Cases
|
|
410
|
+
): <R>(self: Router<R, E>) => Router<
|
|
411
|
+
| R
|
|
412
|
+
| {
|
|
413
|
+
[K in keyof Cases]: Cases[K] extends (
|
|
414
|
+
...args: Array<any>
|
|
415
|
+
) => Effect.Effect<infer R, any, any> ? R
|
|
416
|
+
: never
|
|
417
|
+
}[keyof Cases],
|
|
418
|
+
| Exclude<E, { _tag: keyof Cases }>
|
|
419
|
+
| {
|
|
420
|
+
[K in keyof Cases]: Cases[K] extends (
|
|
421
|
+
...args: Array<any>
|
|
422
|
+
) => Effect.Effect<any, infer E, any> ? E
|
|
423
|
+
: never
|
|
424
|
+
}[keyof Cases]
|
|
425
|
+
>
|
|
426
|
+
<
|
|
427
|
+
R,
|
|
428
|
+
E,
|
|
429
|
+
Cases extends E extends { _tag: string } ? {
|
|
430
|
+
[K in E["_tag"]]+?:
|
|
431
|
+
| ((error: Extract<E, { _tag: K }>) => Route.Handler<any, any>)
|
|
432
|
+
| undefined
|
|
433
|
+
}
|
|
434
|
+
: {}
|
|
435
|
+
>(
|
|
436
|
+
self: Router<R, E>,
|
|
437
|
+
cases: Cases
|
|
438
|
+
): Router<
|
|
439
|
+
| R
|
|
440
|
+
| {
|
|
441
|
+
[K in keyof Cases]: Cases[K] extends (
|
|
442
|
+
...args: Array<any>
|
|
443
|
+
) => Effect.Effect<infer R, any, any> ? R
|
|
444
|
+
: never
|
|
445
|
+
}[keyof Cases],
|
|
446
|
+
| Exclude<E, { _tag: keyof Cases }>
|
|
447
|
+
| {
|
|
448
|
+
[K in keyof Cases]: Cases[K] extends (
|
|
449
|
+
...args: Array<any>
|
|
450
|
+
) => Effect.Effect<any, infer E, any> ? E
|
|
451
|
+
: never
|
|
452
|
+
}[keyof Cases]
|
|
453
|
+
>
|
|
454
|
+
} = internal.catchTags
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* @since 1.0.0
|
|
458
|
+
* @category combinators
|
|
459
|
+
*/
|
|
460
|
+
export const provideService: {
|
|
461
|
+
<T extends Context.Tag<any, any>>(tag: T, service: Context.Tag.Service<T>): <
|
|
462
|
+
R,
|
|
463
|
+
E
|
|
464
|
+
>(
|
|
465
|
+
self: Router<R, E>
|
|
466
|
+
) => Router<Exclude<R, Context.Tag.Identifier<T>>, E>
|
|
467
|
+
<R, E, T extends Context.Tag<any, any>>(
|
|
468
|
+
self: Router<R, E>,
|
|
469
|
+
tag: T,
|
|
470
|
+
service: Context.Tag.Service<T>
|
|
471
|
+
): Router<Exclude<R, Context.Tag.Identifier<T>>, E>
|
|
472
|
+
} = internal.provideService
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @since 1.0.0
|
|
476
|
+
* @category combinators
|
|
477
|
+
*/
|
|
478
|
+
export const provideServiceEffect: {
|
|
479
|
+
<T extends Context.Tag<any, any>, R1, E1>(
|
|
480
|
+
tag: T,
|
|
481
|
+
effect: Effect.Effect<R1, E1, Context.Tag.Service<T>>
|
|
482
|
+
): <R, E>(
|
|
483
|
+
self: Router<R, E>
|
|
484
|
+
) => Router<R1 | Exclude<R, Context.Tag.Identifier<T>>, E1 | E>
|
|
485
|
+
<R, E, T extends Context.Tag<any, any>, R1, E1>(
|
|
486
|
+
self: Router<R, E>,
|
|
487
|
+
tag: T,
|
|
488
|
+
effect: Effect.Effect<R1, E1, Context.Tag.Service<T>>
|
|
489
|
+
): Router<R1 | Exclude<R, Context.Tag.Identifier<T>>, E | E1>
|
|
490
|
+
} = internal.provideServiceEffect
|
|
@@ -6,6 +6,7 @@ import type * as Effect from "@effect/io/Effect"
|
|
|
6
6
|
import type * as PlatformError from "@effect/platform/Error"
|
|
7
7
|
import type * as FileSystem from "@effect/platform/FileSystem"
|
|
8
8
|
import type * as Body from "@effect/platform/Http/Body"
|
|
9
|
+
import type * as Etag from "@effect/platform/Http/Etag"
|
|
9
10
|
import type * as Headers from "@effect/platform/Http/Headers"
|
|
10
11
|
import type * as Error from "@effect/platform/Http/ServerError"
|
|
11
12
|
import type * as ServerRequest from "@effect/platform/Http/ServerRequest"
|
|
@@ -172,7 +173,7 @@ export const stream: (body: Stream.Stream<never, unknown, Uint8Array>, options?:
|
|
|
172
173
|
export const file: (
|
|
173
174
|
path: string,
|
|
174
175
|
options?: Options & FileSystem.StreamOptions
|
|
175
|
-
) => Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, ServerResponse> = internal.file
|
|
176
|
+
) => Effect.Effect<FileSystem.FileSystem | Etag.Generator, PlatformError.PlatformError, ServerResponse> = internal.file
|
|
176
177
|
|
|
177
178
|
/**
|
|
178
179
|
* @since 1.0.0
|
|
@@ -4,6 +4,7 @@ import * as FileSystem from "@effect/platform/FileSystem"
|
|
|
4
4
|
import type * as Body from "@effect/platform/Http/Body"
|
|
5
5
|
import * as Schema from "@effect/schema/Schema"
|
|
6
6
|
import type * as Stream_ from "@effect/stream/Stream"
|
|
7
|
+
import * as Mime from "mime/lite"
|
|
7
8
|
|
|
8
9
|
/** @internal */
|
|
9
10
|
export const TypeId: Body.TypeId = Symbol.for(
|
|
@@ -100,9 +101,27 @@ export const file = (
|
|
|
100
101
|
Effect.flatMap(
|
|
101
102
|
FileSystem.FileSystem,
|
|
102
103
|
(fs) =>
|
|
103
|
-
Effect.map(
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
Effect.map(fs.stat(path), (info) =>
|
|
105
|
+
stream(
|
|
106
|
+
fs.stream(path, options),
|
|
107
|
+
options?.contentType ?? Mime.getType(path) ?? undefined,
|
|
108
|
+
Number(info.size)
|
|
109
|
+
))
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
/** @internal */
|
|
113
|
+
export const fileInfo = (
|
|
114
|
+
path: string,
|
|
115
|
+
info: FileSystem.File.Info,
|
|
116
|
+
options?: FileSystem.StreamOptions & { readonly contentType?: string }
|
|
117
|
+
): Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, Body.Stream> =>
|
|
118
|
+
Effect.map(
|
|
119
|
+
FileSystem.FileSystem,
|
|
120
|
+
(fs) =>
|
|
121
|
+
stream(
|
|
122
|
+
fs.stream(path, options),
|
|
123
|
+
options?.contentType ?? Mime.getType(path) ?? undefined,
|
|
124
|
+
Number(info.size)
|
|
106
125
|
)
|
|
107
126
|
)
|
|
108
127
|
|
|
@@ -21,9 +21,13 @@ import * as Schema from "@effect/schema/Schema"
|
|
|
21
21
|
import * as Stream from "@effect/stream/Stream"
|
|
22
22
|
|
|
23
23
|
/** @internal */
|
|
24
|
-
export const
|
|
24
|
+
export const TypeId: Client.TypeId = Symbol.for("@effect/platform/Http/Client") as Client.TypeId
|
|
25
|
+
|
|
26
|
+
/** @internal */
|
|
27
|
+
export const tag = Context.Tag<Client.Client.Default>(TypeId)
|
|
25
28
|
|
|
26
29
|
const clientProto = {
|
|
30
|
+
[TypeId]: TypeId,
|
|
27
31
|
pipe() {
|
|
28
32
|
return pipeArguments(this, arguments)
|
|
29
33
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Context from "@effect/data/Context"
|
|
2
|
+
import type * as Etag from "@effect/platform/Http/Etag"
|
|
3
|
+
|
|
4
|
+
/** @internal */
|
|
5
|
+
export const GeneratorTypeId: Etag.GeneratorTypeId = Symbol.for(
|
|
6
|
+
"@effect/platform/Http/Etag/Generator"
|
|
7
|
+
) as Etag.GeneratorTypeId
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
export const tag = Context.Tag<Etag.Generator>(GeneratorTypeId)
|
|
11
|
+
|
|
12
|
+
/** @internal */
|
|
13
|
+
export const toString = (self: Etag.Etag): string => {
|
|
14
|
+
switch (self._tag) {
|
|
15
|
+
case "Weak":
|
|
16
|
+
return `W/"${self.value}"`
|
|
17
|
+
case "Strong":
|
|
18
|
+
return `"${self.value}"`
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { flow } from "@effect/data/Function"
|
|
2
2
|
import * as Effect from "@effect/io/Effect"
|
|
3
|
-
import type * as App from "@effect/platform/Http/App"
|
|
4
3
|
import * as Headers from "@effect/platform/Http/Headers"
|
|
5
4
|
import type * as Middleware from "@effect/platform/Http/Middleware"
|
|
6
5
|
import * as ServerRequest from "@effect/platform/Http/ServerRequest"
|
|
@@ -62,17 +61,4 @@ export const xForwardedHeaders = make((httpApp) =>
|
|
|
62
61
|
)
|
|
63
62
|
|
|
64
63
|
/** @internal */
|
|
65
|
-
export const
|
|
66
|
-
<B extends App.Default<any, any>, C extends App.Default<any, any>>(
|
|
67
|
-
that: (b: B) => C
|
|
68
|
-
) => <A extends App.Default<any, any>>(
|
|
69
|
-
self: (a: A) => B
|
|
70
|
-
) => (a: A) => C,
|
|
71
|
-
<A extends App.Default<any, any>, B extends App.Default<any, any>, C extends App.Default<any, any>>(
|
|
72
|
-
self: (a: A) => B,
|
|
73
|
-
that: (b: B) => C
|
|
74
|
-
) => (a: A) => C
|
|
75
|
-
>(2, (self, that) => (inApp) => that(self(inApp)))
|
|
76
|
-
|
|
77
|
-
/** @internal */
|
|
78
|
-
export const loggerTracer = compose(tracer, logger)
|
|
64
|
+
export const loggerTracer = flow(tracer, logger)
|
|
@@ -5,6 +5,7 @@ import { dual } from "@effect/data/Function"
|
|
|
5
5
|
import * as Hash from "@effect/data/Hash"
|
|
6
6
|
import * as Option from "@effect/data/Option"
|
|
7
7
|
import { pipeArguments } from "@effect/data/Pipeable"
|
|
8
|
+
import type * as Cause from "@effect/io/Cause"
|
|
8
9
|
import * as Effect from "@effect/io/Effect"
|
|
9
10
|
import type * as App from "@effect/platform/Http/App"
|
|
10
11
|
import type * as Method from "@effect/platform/Http/Method"
|
|
@@ -98,7 +99,7 @@ const toHttpApp = <R, E>(
|
|
|
98
99
|
const mounts = Chunk.toReadonlyArray(self.mounts)
|
|
99
100
|
const mountsLen = mounts.length
|
|
100
101
|
Chunk.forEach(self.routes, (route) => {
|
|
101
|
-
function fn(
|
|
102
|
+
function fn() {
|
|
102
103
|
return route
|
|
103
104
|
}
|
|
104
105
|
if (route.method === "*") {
|
|
@@ -302,3 +303,130 @@ export const head = route("HEAD")
|
|
|
302
303
|
|
|
303
304
|
/** @internal */
|
|
304
305
|
export const options = route("OPTIONS")
|
|
306
|
+
|
|
307
|
+
/** @internal */
|
|
308
|
+
export const use = dual<
|
|
309
|
+
<R, E, R1, E1>(
|
|
310
|
+
f: (self: Router.Route.Handler<R, E>) => Router.Route.Handler<R1, E1>
|
|
311
|
+
) => (self: Router.Router<R, E>) => Router.Router<R1, E1>,
|
|
312
|
+
<R, E, R1, E1>(
|
|
313
|
+
self: Router.Router<R, E>,
|
|
314
|
+
f: (self: Router.Route.Handler<R, E>) => Router.Route.Handler<R1, E1>
|
|
315
|
+
) => Router.Router<R1, E1>
|
|
316
|
+
>(2, (self, f) =>
|
|
317
|
+
new RouterImpl(
|
|
318
|
+
Chunk.map(
|
|
319
|
+
self.routes,
|
|
320
|
+
(route) => new RouteImpl(route.method, route.path, f(route.handler), route.prefix)
|
|
321
|
+
),
|
|
322
|
+
Chunk.map(
|
|
323
|
+
self.mounts,
|
|
324
|
+
([path, app]) => [path, f(app as any)]
|
|
325
|
+
)
|
|
326
|
+
))
|
|
327
|
+
|
|
328
|
+
/** @internal */
|
|
329
|
+
export const catchAll = dual<
|
|
330
|
+
<E, R2, E2>(
|
|
331
|
+
f: (e: E) => Router.Route.Handler<R2, E2>
|
|
332
|
+
) => <R>(self: Router.Router<R, E>) => Router.Router<R2 | R, E2>,
|
|
333
|
+
<R, E, R2, E2>(
|
|
334
|
+
self: Router.Router<R, E>,
|
|
335
|
+
f: (e: E) => Router.Route.Handler<R2, E2>
|
|
336
|
+
) => Router.Router<R2 | R, E2>
|
|
337
|
+
>(2, (self, f) => use(self, Effect.catchAll(f)))
|
|
338
|
+
|
|
339
|
+
/** @internal */
|
|
340
|
+
export const catchAllCause = dual<
|
|
341
|
+
<E, R2, E2>(
|
|
342
|
+
f: (e: Cause.Cause<E>) => Router.Route.Handler<R2, E2>
|
|
343
|
+
) => <R>(self: Router.Router<R, E>) => Router.Router<R2 | R, E2>,
|
|
344
|
+
<R, E, R2, E2>(
|
|
345
|
+
self: Router.Router<R, E>,
|
|
346
|
+
f: (e: Cause.Cause<E>) => Router.Route.Handler<R2, E2>
|
|
347
|
+
) => Router.Router<R2 | R, E2>
|
|
348
|
+
>(2, (self, f) => use(self, Effect.catchAllCause(f)))
|
|
349
|
+
|
|
350
|
+
/** @internal */
|
|
351
|
+
export const catchTag = dual<
|
|
352
|
+
<K extends (E extends { _tag: string } ? E["_tag"] : never), E, R1, E1>(
|
|
353
|
+
k: K,
|
|
354
|
+
f: (e: Extract<E, { _tag: K }>) => Router.Route.Handler<R1, E1>
|
|
355
|
+
) => <R>(self: Router.Router<R, E>) => Router.Router<R | R1, Exclude<E, { _tag: K }> | E1>,
|
|
356
|
+
<R, E, K extends (E extends { _tag: string } ? E["_tag"] : never), R1, E1>(
|
|
357
|
+
self: Router.Router<R, E>,
|
|
358
|
+
k: K,
|
|
359
|
+
f: (e: Extract<E, { _tag: K }>) => Router.Route.Handler<R1, E1>
|
|
360
|
+
) => Router.Router<R | R1, Exclude<E, { _tag: K }> | E1>
|
|
361
|
+
>(3, (self, k, f) => use(self, Effect.catchTag(k, f)))
|
|
362
|
+
|
|
363
|
+
/** @internal */
|
|
364
|
+
export const catchTags: {
|
|
365
|
+
<
|
|
366
|
+
E,
|
|
367
|
+
Cases extends (E extends { _tag: string } ? {
|
|
368
|
+
[K in E["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Router.Route.Handler<any, any>
|
|
369
|
+
} :
|
|
370
|
+
{})
|
|
371
|
+
>(
|
|
372
|
+
cases: Cases
|
|
373
|
+
): <R>(self: Router.Router<R, E>) => Router.Router<
|
|
374
|
+
| R
|
|
375
|
+
| {
|
|
376
|
+
[K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Effect.Effect<infer R, any, any>) ? R : never
|
|
377
|
+
}[keyof Cases],
|
|
378
|
+
| Exclude<E, { _tag: keyof Cases }>
|
|
379
|
+
| {
|
|
380
|
+
[K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Effect.Effect<any, infer E, any>) ? E : never
|
|
381
|
+
}[keyof Cases]
|
|
382
|
+
>
|
|
383
|
+
<
|
|
384
|
+
R,
|
|
385
|
+
E,
|
|
386
|
+
Cases extends (E extends { _tag: string } ? {
|
|
387
|
+
[K in E["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Router.Route.Handler<any, any>
|
|
388
|
+
} :
|
|
389
|
+
{})
|
|
390
|
+
>(
|
|
391
|
+
self: Router.Router<R, E>,
|
|
392
|
+
cases: Cases
|
|
393
|
+
): Router.Router<
|
|
394
|
+
| R
|
|
395
|
+
| {
|
|
396
|
+
[K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Effect.Effect<infer R, any, any>) ? R : never
|
|
397
|
+
}[keyof Cases],
|
|
398
|
+
| Exclude<E, { _tag: keyof Cases }>
|
|
399
|
+
| {
|
|
400
|
+
[K in keyof Cases]: Cases[K] extends ((...args: Array<any>) => Effect.Effect<any, infer E, any>) ? E : never
|
|
401
|
+
}[keyof Cases]
|
|
402
|
+
>
|
|
403
|
+
} = dual(2, (self: Router.Router<any, any>, cases: {}) => use(self, Effect.catchTags(cases)))
|
|
404
|
+
|
|
405
|
+
export const provideService = dual<
|
|
406
|
+
<T extends Context.Tag<any, any>>(
|
|
407
|
+
tag: T,
|
|
408
|
+
service: Context.Tag.Service<T>
|
|
409
|
+
) => <R, E>(self: Router.Router<R, E>) => Router.Router<Exclude<R, Context.Tag.Identifier<T>>, E>,
|
|
410
|
+
<R, E, T extends Context.Tag<any, any>>(
|
|
411
|
+
self: Router.Router<R, E>,
|
|
412
|
+
tag: T,
|
|
413
|
+
service: Context.Tag.Service<T>
|
|
414
|
+
) => Router.Router<Exclude<R, Context.Tag.Identifier<T>>, E>
|
|
415
|
+
>(3, (self, tag, service) => use(self, Effect.provideService(tag, service)))
|
|
416
|
+
|
|
417
|
+
/* @internal */
|
|
418
|
+
export const provideServiceEffect = dual<
|
|
419
|
+
<T extends Context.Tag<any, any>, R1, E1>(
|
|
420
|
+
tag: T,
|
|
421
|
+
effect: Effect.Effect<R1, E1, Context.Tag.Service<T>>
|
|
422
|
+
) => <R, E>(self: Router.Router<R, E>) => Router.Router<R1 | Exclude<R, Context.Tag.Identifier<T>>, E | E1>,
|
|
423
|
+
<R, E, T extends Context.Tag<any, any>, R1, E1>(
|
|
424
|
+
self: Router.Router<R, E>,
|
|
425
|
+
tag: T,
|
|
426
|
+
effect: Effect.Effect<R1, E1, Context.Tag.Service<T>>
|
|
427
|
+
) => Router.Router<R1 | Exclude<R, Context.Tag.Identifier<T>>, E | E1>
|
|
428
|
+
>(3, <R, E, T extends Context.Tag<any, any>, R1, E1>(
|
|
429
|
+
self: Router.Router<R, E>,
|
|
430
|
+
tag: T,
|
|
431
|
+
effect: Effect.Effect<R1, E1, Context.Tag.Service<T>>
|
|
432
|
+
) => use(self, Effect.provideServiceEffect(tag, effect)))
|
|
@@ -12,7 +12,7 @@ import type * as ServerRequest from "@effect/platform/Http/ServerRequest"
|
|
|
12
12
|
export const TypeId: Server.TypeId = Symbol.for("@effect/platform/Http/Server") as Server.TypeId
|
|
13
13
|
|
|
14
14
|
/** @internal */
|
|
15
|
-
export const serverTag = Context.Tag<Server.Server>(
|
|
15
|
+
export const serverTag = Context.Tag<Server.Server>(TypeId)
|
|
16
16
|
|
|
17
17
|
const serverProto = {
|
|
18
18
|
[TypeId]: TypeId
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { dual } from "@effect/data/Function"
|
|
1
|
+
import { dual, pipe } from "@effect/data/Function"
|
|
2
2
|
import { pipeArguments } from "@effect/data/Pipeable"
|
|
3
3
|
import * as Effect from "@effect/io/Effect"
|
|
4
4
|
import type * as PlatformError from "@effect/platform/Error"
|
|
5
|
-
import
|
|
5
|
+
import * as FileSystem from "@effect/platform/FileSystem"
|
|
6
6
|
import type * as Body from "@effect/platform/Http/Body"
|
|
7
|
+
import * as Etag from "@effect/platform/Http/Etag"
|
|
7
8
|
import * as Headers from "@effect/platform/Http/Headers"
|
|
8
9
|
import type * as Error from "@effect/platform/Http/ServerError"
|
|
9
10
|
import * as ServerRequest from "@effect/platform/Http/ServerRequest"
|
|
@@ -141,14 +142,35 @@ export const schemaJson = <I, A>(
|
|
|
141
142
|
export const file = (
|
|
142
143
|
path: string,
|
|
143
144
|
options?: ServerResponse.Options & FileSystem.StreamOptions
|
|
144
|
-
): Effect.Effect<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
145
|
+
): Effect.Effect<
|
|
146
|
+
FileSystem.FileSystem | Etag.Generator,
|
|
147
|
+
PlatformError.PlatformError,
|
|
148
|
+
ServerResponse.ServerResponse
|
|
149
|
+
> =>
|
|
150
|
+
pipe(
|
|
151
|
+
Effect.bindTo(Effect.flatMap(FileSystem.FileSystem, (fs) => fs.stat(path)), "info"),
|
|
152
|
+
Effect.bind("etag", ({ info }) =>
|
|
153
|
+
Effect.flatMap(
|
|
154
|
+
Etag.Generator,
|
|
155
|
+
(generator) => generator.fromFileInfo(info)
|
|
156
|
+
)),
|
|
157
|
+
Effect.bind("body", ({ info }) => internalBody.fileInfo(path, info, options)),
|
|
158
|
+
Effect.map(({ body, etag, info }) => {
|
|
159
|
+
const headers: Record<string, string> = {
|
|
160
|
+
...(options?.headers ?? {}),
|
|
161
|
+
etag: Etag.toString(etag)
|
|
162
|
+
}
|
|
163
|
+
if (info.mtime._tag === "Some") {
|
|
164
|
+
headers["last-modified"] = info.mtime.value.toUTCString()
|
|
165
|
+
}
|
|
166
|
+
return new ServerResponseImpl(
|
|
167
|
+
options?.status ?? 200,
|
|
168
|
+
options?.statusText,
|
|
169
|
+
headers,
|
|
170
|
+
body
|
|
171
|
+
)
|
|
172
|
+
})
|
|
173
|
+
)
|
|
152
174
|
|
|
153
175
|
/** @internal */
|
|
154
176
|
export const urlParams = (
|