@effect/platform 0.46.3 → 0.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/PlatformLogger/package.json +6 -0
  2. package/Socket/package.json +6 -0
  3. package/dist/cjs/Error.js +40 -4
  4. package/dist/cjs/Error.js.map +1 -1
  5. package/dist/cjs/Http/Body.js +8 -1
  6. package/dist/cjs/Http/Body.js.map +1 -1
  7. package/dist/cjs/Http/ClientError.js +21 -2
  8. package/dist/cjs/Http/ClientError.js.map +1 -1
  9. package/dist/cjs/Http/Headers.js +22 -1
  10. package/dist/cjs/Http/Headers.js.map +1 -1
  11. package/dist/cjs/Http/ServerError.js +30 -7
  12. package/dist/cjs/Http/ServerError.js.map +1 -1
  13. package/dist/cjs/Http/ServerRequest.js +11 -1
  14. package/dist/cjs/Http/ServerRequest.js.map +1 -1
  15. package/dist/cjs/Http/UrlParams.js +7 -2
  16. package/dist/cjs/Http/UrlParams.js.map +1 -1
  17. package/dist/cjs/PlatformLogger.js +57 -0
  18. package/dist/cjs/PlatformLogger.js.map +1 -0
  19. package/dist/cjs/Socket.js +212 -0
  20. package/dist/cjs/Socket.js.map +1 -0
  21. package/dist/cjs/index.js +5 -1
  22. package/dist/cjs/internal/http/body.js +1 -1
  23. package/dist/cjs/internal/http/body.js.map +1 -1
  24. package/dist/cjs/internal/http/client.js +5 -5
  25. package/dist/cjs/internal/http/client.js.map +1 -1
  26. package/dist/cjs/internal/http/clientError.js +1 -36
  27. package/dist/cjs/internal/http/clientError.js.map +1 -1
  28. package/dist/cjs/internal/http/clientResponse.js +8 -8
  29. package/dist/cjs/internal/http/clientResponse.js.map +1 -1
  30. package/dist/cjs/internal/http/multiplex.js +1 -1
  31. package/dist/cjs/internal/http/multiplex.js.map +1 -1
  32. package/dist/cjs/internal/http/router.js +1 -1
  33. package/dist/cjs/internal/http/router.js.map +1 -1
  34. package/dist/cjs/internal/http/serverError.js +1 -15
  35. package/dist/cjs/internal/http/serverError.js.map +1 -1
  36. package/dist/cjs/internal/http/serverRequest.js +22 -8
  37. package/dist/cjs/internal/http/serverRequest.js.map +1 -1
  38. package/dist/cjs/internal/platformLogger.js +46 -0
  39. package/dist/cjs/internal/platformLogger.js.map +1 -0
  40. package/dist/cjs/internal/worker.js.map +1 -1
  41. package/dist/dts/Error.d.ts +22 -0
  42. package/dist/dts/Error.d.ts.map +1 -1
  43. package/dist/dts/Http/Body.d.ts +9 -1
  44. package/dist/dts/Http/Body.d.ts.map +1 -1
  45. package/dist/dts/Http/ClientError.d.ts +21 -33
  46. package/dist/dts/Http/ClientError.d.ts.map +1 -1
  47. package/dist/dts/Http/Headers.d.ts +19 -0
  48. package/dist/dts/Http/Headers.d.ts.map +1 -1
  49. package/dist/dts/Http/ServerError.d.ts +33 -47
  50. package/dist/dts/Http/ServerError.d.ts.map +1 -1
  51. package/dist/dts/Http/ServerRequest.d.ts +14 -0
  52. package/dist/dts/Http/ServerRequest.d.ts.map +1 -1
  53. package/dist/dts/Http/UrlParams.d.ts +5 -0
  54. package/dist/dts/Http/UrlParams.d.ts.map +1 -1
  55. package/dist/dts/PlatformLogger.d.ts +41 -0
  56. package/dist/dts/PlatformLogger.d.ts.map +1 -0
  57. package/dist/dts/Socket.d.ts +111 -0
  58. package/dist/dts/Socket.d.ts.map +1 -0
  59. package/dist/dts/index.d.ts +8 -0
  60. package/dist/dts/index.d.ts.map +1 -1
  61. package/dist/dts/internal/platformLogger.d.ts +2 -0
  62. package/dist/dts/internal/platformLogger.d.ts.map +1 -0
  63. package/dist/esm/Error.js +38 -3
  64. package/dist/esm/Error.js.map +1 -1
  65. package/dist/esm/Http/Body.js +6 -0
  66. package/dist/esm/Http/Body.js.map +1 -1
  67. package/dist/esm/Http/ClientError.js +19 -2
  68. package/dist/esm/Http/ClientError.js.map +1 -1
  69. package/dist/esm/Http/Headers.js +21 -1
  70. package/dist/esm/Http/Headers.js.map +1 -1
  71. package/dist/esm/Http/ServerError.js +26 -7
  72. package/dist/esm/Http/ServerError.js.map +1 -1
  73. package/dist/esm/Http/ServerRequest.js +10 -0
  74. package/dist/esm/Http/ServerRequest.js.map +1 -1
  75. package/dist/esm/Http/UrlParams.js +5 -0
  76. package/dist/esm/Http/UrlParams.js.map +1 -1
  77. package/dist/esm/PlatformLogger.js +26 -0
  78. package/dist/esm/PlatformLogger.js.map +1 -0
  79. package/dist/esm/Socket.js +166 -0
  80. package/dist/esm/Socket.js.map +1 -0
  81. package/dist/esm/index.js +8 -0
  82. package/dist/esm/index.js.map +1 -1
  83. package/dist/esm/internal/http/body.js +1 -1
  84. package/dist/esm/internal/http/body.js.map +1 -1
  85. package/dist/esm/internal/http/client.js +5 -5
  86. package/dist/esm/internal/http/client.js.map +1 -1
  87. package/dist/esm/internal/http/clientError.js +0 -10
  88. package/dist/esm/internal/http/clientError.js.map +1 -1
  89. package/dist/esm/internal/http/clientResponse.js +8 -8
  90. package/dist/esm/internal/http/clientResponse.js.map +1 -1
  91. package/dist/esm/internal/http/multiplex.js +1 -1
  92. package/dist/esm/internal/http/multiplex.js.map +1 -1
  93. package/dist/esm/internal/http/router.js +1 -1
  94. package/dist/esm/internal/http/router.js.map +1 -1
  95. package/dist/esm/internal/http/serverError.js +0 -14
  96. package/dist/esm/internal/http/serverError.js.map +1 -1
  97. package/dist/esm/internal/http/serverRequest.js +20 -7
  98. package/dist/esm/internal/http/serverRequest.js.map +1 -1
  99. package/dist/esm/internal/platformLogger.js +15 -0
  100. package/dist/esm/internal/platformLogger.js.map +1 -0
  101. package/dist/esm/internal/worker.js.map +1 -1
  102. package/package.json +20 -3
  103. package/src/Error.ts +61 -0
  104. package/src/Http/Body.ts +14 -1
  105. package/src/Http/ClientError.ts +21 -38
  106. package/src/Http/Headers.ts +29 -1
  107. package/src/Http/ServerError.ts +25 -56
  108. package/src/Http/ServerRequest.ts +25 -0
  109. package/src/Http/UrlParams.ts +10 -0
  110. package/src/PlatformLogger.ts +59 -0
  111. package/src/Socket.ts +291 -0
  112. package/src/index.ts +10 -0
  113. package/src/internal/http/body.ts +4 -2
  114. package/src/internal/http/client.ts +5 -6
  115. package/src/internal/http/clientError.ts +0 -14
  116. package/src/internal/http/clientResponse.ts +15 -14
  117. package/src/internal/http/multiplex.ts +1 -1
  118. package/src/internal/http/router.ts +1 -1
  119. package/src/internal/http/serverError.ts +0 -20
  120. package/src/internal/http/serverRequest.ts +31 -11
  121. package/src/internal/platformLogger.ts +42 -0
  122. package/src/internal/worker.ts +5 -1
package/src/Socket.ts ADDED
@@ -0,0 +1,291 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import * as Cause from "effect/Cause"
5
+ import * as Channel from "effect/Channel"
6
+ import * as Chunk from "effect/Chunk"
7
+ import * as Context from "effect/Context"
8
+ import * as Data from "effect/Data"
9
+ import * as Effect from "effect/Effect"
10
+ import * as Exit from "effect/Exit"
11
+ import * as FiberSet from "effect/FiberSet"
12
+ import * as Layer from "effect/Layer"
13
+ import * as Queue from "effect/Queue"
14
+ import * as Scope from "effect/Scope"
15
+ import type * as AsyncProducer from "effect/SingleProducerAsyncInput"
16
+ import IsoWebSocket from "isomorphic-ws"
17
+
18
+ /**
19
+ * @since 1.0.0
20
+ * @category type ids
21
+ */
22
+ export const SocketTypeId = Symbol.for("@effect/platform/Socket")
23
+
24
+ /**
25
+ * @since 1.0.0
26
+ * @category type ids
27
+ */
28
+ export type SocketTypeId = typeof SocketTypeId
29
+
30
+ /**
31
+ * @since 1.0.0
32
+ * @category tags
33
+ */
34
+ export const Socket: Context.Tag<Socket, Socket> = Context.GenericTag<Socket>(
35
+ "@effect/platform/Socket"
36
+ )
37
+
38
+ /**
39
+ * @since 1.0.0
40
+ * @category models
41
+ */
42
+ export interface Socket {
43
+ readonly [SocketTypeId]: SocketTypeId
44
+ readonly run: <R, E, _>(
45
+ handler: (_: Uint8Array) => Effect.Effect<_, E, R>
46
+ ) => Effect.Effect<void, SocketError | E, R>
47
+ readonly writer: Effect.Effect<(chunk: Uint8Array) => Effect.Effect<void>, never, Scope.Scope>
48
+ }
49
+
50
+ /**
51
+ * @since 1.0.0
52
+ * @category errors
53
+ */
54
+ export class SocketError extends Data.TaggedError("SocketError")<{
55
+ readonly reason: "Write" | "Read" | "Open" | "Close"
56
+ readonly error: unknown
57
+ }> {
58
+ /**
59
+ * @since 1.0.0
60
+ */
61
+ toString(): string {
62
+ return `SocketError: ${this.reason} - ${this.error}`
63
+ }
64
+ }
65
+
66
+ /**
67
+ * @since 1.0.0
68
+ * @category combinators
69
+ */
70
+ export const toChannel = <IE>(
71
+ self: Socket
72
+ ): Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, SocketError | IE, IE, void, unknown> =>
73
+ Channel.unwrap(
74
+ Effect.gen(function*(_) {
75
+ const writeScope = yield* _(Scope.make())
76
+ const write = yield* _(Scope.extend(self.writer, writeScope))
77
+ const exitQueue = yield* _(Queue.unbounded<Exit.Exit<Chunk.Chunk<Uint8Array>, SocketError | IE>>())
78
+
79
+ const input: AsyncProducer.AsyncInputProducer<IE, Chunk.Chunk<Uint8Array>, unknown> = {
80
+ awaitRead: () => Effect.unit,
81
+ emit(chunk) {
82
+ return Effect.catchAllCause(
83
+ Effect.forEach(chunk, write, { discard: true }),
84
+ (cause) => Queue.offer(exitQueue, Exit.failCause(cause))
85
+ )
86
+ },
87
+ error(error) {
88
+ return Effect.zipRight(
89
+ Scope.close(writeScope, Exit.unit),
90
+ Queue.offer(exitQueue, Exit.failCause(error))
91
+ )
92
+ },
93
+ done() {
94
+ return Scope.close(writeScope, Exit.unit)
95
+ }
96
+ }
97
+
98
+ yield* _(
99
+ self.run((data) => Queue.offer(exitQueue, Exit.succeed(Chunk.of(data)))),
100
+ Effect.zipRight(Effect.failCause(Cause.empty)),
101
+ Effect.exit,
102
+ Effect.tap((exit) => Queue.offer(exitQueue, exit)),
103
+ Effect.fork
104
+ )
105
+
106
+ const loop: Channel.Channel<Chunk.Chunk<Uint8Array>, unknown, SocketError | IE, unknown, void, unknown> = Channel
107
+ .flatMap(
108
+ Queue.take(exitQueue),
109
+ Exit.match({
110
+ onFailure: (cause) => Cause.isEmptyType(cause) ? Channel.unit : Channel.failCause(cause),
111
+ onSuccess: (chunk) => Channel.zipRight(Channel.write(chunk), loop)
112
+ })
113
+ )
114
+
115
+ return Channel.embedInput(loop, input)
116
+ })
117
+ )
118
+
119
+ /**
120
+ * @since 1.0.0
121
+ * @category combinators
122
+ */
123
+ export const toChannelWith = <IE = never>() =>
124
+ (
125
+ self: Socket
126
+ ): Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, SocketError | IE, IE, void, unknown> =>
127
+ toChannel(self)
128
+
129
+ /**
130
+ * @since 1.0.0
131
+ * @category constructors
132
+ */
133
+ export const makeChannel = <IE = never>(): Channel.Channel<
134
+ Chunk.Chunk<Uint8Array>,
135
+ Chunk.Chunk<Uint8Array>,
136
+ SocketError | IE,
137
+ IE,
138
+ void,
139
+ unknown,
140
+ Socket
141
+ > => Channel.unwrap(Effect.map(Socket, toChannelWith<IE>()))
142
+
143
+ /**
144
+ * @since 1.0.0
145
+ */
146
+ export const defaultCloseCodeIsError = (code: number) => code !== 1000 && code !== 1006
147
+
148
+ /**
149
+ * @since 1.0.0
150
+ * @category tags
151
+ */
152
+ export interface WebSocket {
153
+ readonly _: unique symbol
154
+ }
155
+
156
+ /**
157
+ * @since 1.0.0
158
+ * @category tags
159
+ */
160
+ export const WebSocket: Context.Tag<WebSocket, globalThis.WebSocket> = Context.GenericTag(
161
+ "@effect/platform/Socket/WebSocket"
162
+ )
163
+
164
+ /**
165
+ * @since 1.0.0
166
+ * @category constructors
167
+ */
168
+ export const makeWebSocket = (url: string | Effect.Effect<string>, options?: {
169
+ readonly closeCodeIsError?: (code: number) => boolean
170
+ }): Effect.Effect<Socket> =>
171
+ fromWebSocket(
172
+ Effect.acquireRelease(
173
+ Effect.map(
174
+ typeof url === "string" ? Effect.succeed(url) : url,
175
+ (url) => {
176
+ const WS = "WebSocket" in globalThis ? globalThis.WebSocket : IsoWebSocket
177
+ return new WS(url) as globalThis.WebSocket
178
+ }
179
+ ),
180
+ (ws) => Effect.sync(() => ws.close())
181
+ ),
182
+ options
183
+ )
184
+
185
+ /**
186
+ * @since 1.0.0
187
+ * @category constructors
188
+ */
189
+ export const fromWebSocket = (
190
+ acquire: Effect.Effect<globalThis.WebSocket, SocketError, Scope.Scope>,
191
+ options?: {
192
+ readonly closeCodeIsError?: (code: number) => boolean
193
+ }
194
+ ): Effect.Effect<Socket> =>
195
+ Effect.gen(function*(_) {
196
+ const closeCodeIsError = options?.closeCodeIsError ?? defaultCloseCodeIsError
197
+ const sendQueue = yield* _(Queue.unbounded<Uint8Array>())
198
+
199
+ const run = <R, E, _>(handler: (_: Uint8Array) => Effect.Effect<_, E, R>) =>
200
+ Effect.gen(function*(_) {
201
+ const ws = yield* _(acquire)
202
+ const encoder = new TextEncoder()
203
+ const fiberSet = yield* _(FiberSet.make<any, E | SocketError>())
204
+ const run = yield* _(
205
+ FiberSet.runtime(fiberSet)<R>(),
206
+ Effect.provideService(WebSocket, ws)
207
+ )
208
+
209
+ ws.onmessage = (event) => {
210
+ run(
211
+ handler(
212
+ event.data instanceof Uint8Array
213
+ ? event.data
214
+ : typeof event.data === "string"
215
+ ? encoder.encode(event.data)
216
+ : new Uint8Array(event.data)
217
+ )
218
+ )
219
+ }
220
+
221
+ if (ws.readyState !== IsoWebSocket.OPEN) {
222
+ yield* _(Effect.async<void, SocketError, never>((resume) => {
223
+ ws.onopen = () => {
224
+ resume(Effect.unit)
225
+ }
226
+ ws.onerror = (error_) => {
227
+ resume(Effect.fail(new SocketError({ reason: "Open", error: (error_ as any).message })))
228
+ }
229
+ }))
230
+ }
231
+
232
+ yield* _(
233
+ Queue.take(sendQueue),
234
+ Effect.tap((chunk) =>
235
+ Effect.try({
236
+ try: () => ws.send(chunk),
237
+ catch: (error) => Effect.fail(new SocketError({ reason: "Write", error: (error as any).message }))
238
+ })
239
+ ),
240
+ Effect.forever,
241
+ Effect.fork
242
+ )
243
+
244
+ yield* _(
245
+ Effect.async<void, SocketError, never>((resume) => {
246
+ ws.onclose = (event) => {
247
+ if (closeCodeIsError(event.code)) {
248
+ resume(Effect.fail(new SocketError({ reason: "Close", error: event })))
249
+ } else {
250
+ resume(Effect.unit)
251
+ }
252
+ }
253
+ ws.onerror = (error) => {
254
+ resume(Effect.fail(new SocketError({ reason: "Read", error: (error as any).message })))
255
+ }
256
+ }),
257
+ Effect.raceFirst(FiberSet.join(fiberSet))
258
+ )
259
+ }).pipe(Effect.scoped)
260
+
261
+ const write = (chunk: Uint8Array) => Queue.offer(sendQueue, chunk)
262
+ const writer = Effect.succeed(write)
263
+
264
+ return Socket.of({
265
+ [SocketTypeId]: SocketTypeId,
266
+ run,
267
+ writer
268
+ })
269
+ })
270
+
271
+ /**
272
+ * @since 1.0.0
273
+ * @category constructors
274
+ */
275
+ export const makeWebSocketChannel = <IE = never>(
276
+ url: string,
277
+ options?: {
278
+ readonly closeCodeIsError?: (code: number) => boolean
279
+ }
280
+ ): Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, SocketError | IE, IE, void, unknown> =>
281
+ Channel.unwrapScoped(
282
+ Effect.map(makeWebSocket(url, options), toChannelWith<IE>())
283
+ )
284
+
285
+ /**
286
+ * @since 1.0.0
287
+ * @category layers
288
+ */
289
+ export const layerWebSocket = (url: string, options?: {
290
+ readonly closeCodeIsError?: (code: number) => boolean
291
+ }): Layer.Layer<Socket> => Layer.scoped(Socket, makeWebSocket(url, options))
package/src/index.ts CHANGED
@@ -43,11 +43,21 @@ export * as KeyValueStore from "./KeyValueStore.js"
43
43
  */
44
44
  export * as Path from "./Path.js"
45
45
 
46
+ /**
47
+ * @since 1.0.0
48
+ */
49
+ export * as PlatformLogger from "./PlatformLogger.js"
50
+
46
51
  /**
47
52
  * @since 1.0.0
48
53
  */
49
54
  export * as Runtime from "./Runtime.js"
50
55
 
56
+ /**
57
+ * @since 1.0.0
58
+ */
59
+ export * as Socket from "./Socket.js"
60
+
51
61
  /**
52
62
  * @since 1.0.0
53
63
  */
@@ -48,8 +48,10 @@ class RawImpl implements Body.Raw {
48
48
  }
49
49
 
50
50
  /** @internal */
51
- export const raw = (body: unknown, contentType?: string, contentLength?: number): Body.Raw =>
52
- new RawImpl(body, contentType, contentLength)
51
+ export const raw = (body: unknown, options?: {
52
+ readonly contentType?: string
53
+ readonly contentLength?: number
54
+ }): Body.Raw => new RawImpl(body, options?.contentType, options?.contentLength)
53
55
 
54
56
  class Uint8ArrayImpl implements Body.Uint8Array {
55
57
  readonly [TypeId]: Body.TypeId
@@ -11,13 +11,12 @@ import type * as Scope from "effect/Scope"
11
11
  import * as Stream from "effect/Stream"
12
12
  import type * as Body from "../../Http/Body.js"
13
13
  import type * as Client from "../../Http/Client.js"
14
- import type * as Error from "../../Http/ClientError.js"
14
+ import * as Error from "../../Http/ClientError.js"
15
15
  import type * as ClientRequest from "../../Http/ClientRequest.js"
16
16
  import type * as ClientResponse from "../../Http/ClientResponse.js"
17
17
  import * as Method from "../../Http/Method.js"
18
18
  import * as UrlParams from "../../Http/UrlParams.js"
19
19
  import * as internalBody from "./body.js"
20
- import * as internalError from "./clientError.js"
21
20
  import * as internalRequest from "./clientRequest.js"
22
21
  import * as internalResponse from "./clientResponse.js"
23
22
 
@@ -82,7 +81,7 @@ export const fetch = (options?: RequestInit): Client.Client.Default =>
82
81
  makeDefault((request) =>
83
82
  Effect.flatMap(
84
83
  UrlParams.makeUrl(request.url, request.urlParams, (_) =>
85
- internalError.requestError({
84
+ new Error.RequestError({
86
85
  request,
87
86
  reason: "InvalidUrl",
88
87
  error: _
@@ -109,7 +108,7 @@ export const fetch = (options?: RequestInit): Client.Client.Default =>
109
108
  signal: controller.signal
110
109
  } as any),
111
110
  catch: (_) =>
112
- internalError.requestError({
111
+ new Error.RequestError({
113
112
  request,
114
113
  reason: "Transport",
115
114
  error: _
@@ -419,7 +418,7 @@ export const filterStatus = dual<
419
418
  effect,
420
419
  (response) => f(response.status),
421
420
  (response) =>
422
- internalError.responseError({
421
+ new Error.ResponseError({
423
422
  request,
424
423
  response,
425
424
  reason: "StatusCode",
@@ -571,7 +570,7 @@ export const schemaFunction = dual<
571
570
  Effect.tryMap(encode(a), {
572
571
  try: (body) => new TextEncoder().encode(JSON.stringify(body)),
573
572
  catch: (error) =>
574
- internalError.requestError({
573
+ new Error.RequestError({
575
574
  request,
576
575
  reason: "Encode",
577
576
  error
@@ -1,20 +1,6 @@
1
- import * as Data from "effect/Data"
2
1
  import type * as Error from "../../Http/ClientError.js"
3
2
 
4
3
  /** @internal */
5
4
  export const TypeId: Error.TypeId = Symbol.for(
6
5
  "@effect/platform/Http/Error"
7
6
  ) as Error.TypeId
8
-
9
- const make = <A extends Error.HttpClientError>(tag: A["_tag"]) => (props: Omit<A, Error.HttpError.ProvidedFields>): A =>
10
- Data.struct({
11
- [TypeId]: TypeId,
12
- _tag: tag,
13
- ...props
14
- } as A)
15
-
16
- /** @internal */
17
- export const requestError = make<Error.RequestError>("RequestError")
18
-
19
- /** @internal */
20
- export const responseError = make<Error.ResponseError>("ResponseError")
@@ -3,13 +3,12 @@ import * as Schema from "@effect/schema/Schema"
3
3
  import * as Effect from "effect/Effect"
4
4
  import * as Option from "effect/Option"
5
5
  import * as Stream from "effect/Stream"
6
- import type * as Error from "../../Http/ClientError.js"
6
+ import * as Error from "../../Http/ClientError.js"
7
7
  import type * as ClientRequest from "../../Http/ClientRequest.js"
8
8
  import type * as ClientResponse from "../../Http/ClientResponse.js"
9
9
  import * as Headers from "../../Http/Headers.js"
10
10
  import * as IncomingMessage from "../../Http/IncomingMessage.js"
11
11
  import * as UrlParams from "../../Http/UrlParams.js"
12
- import * as internalError from "./clientError.js"
13
12
 
14
13
  /** @internal */
15
14
  export const TypeId: ClientResponse.TypeId = Symbol.for("@effect/platform/Http/ClientResponse") as ClientResponse.TypeId
@@ -47,25 +46,27 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
47
46
  get stream(): Stream.Stream<Uint8Array, Error.ResponseError> {
48
47
  return this.source.body
49
48
  ? Stream.fromReadableStream(() => this.source.body!, (_) =>
50
- internalError.responseError({
49
+ new Error.ResponseError({
51
50
  request: this.request,
52
51
  response: this,
53
52
  reason: "Decode",
54
53
  error: _
55
54
  }))
56
- : Stream.fail(internalError.responseError({
57
- request: this.request,
58
- response: this,
59
- reason: "EmptyBody",
60
- error: "can not create stream from empty body"
61
- }))
55
+ : Stream.fail(
56
+ new Error.ResponseError({
57
+ request: this.request,
58
+ response: this,
59
+ reason: "EmptyBody",
60
+ error: "can not create stream from empty body"
61
+ })
62
+ )
62
63
  }
63
64
 
64
65
  get json(): Effect.Effect<unknown, Error.ResponseError> {
65
66
  return Effect.tryMap(this.text, {
66
67
  try: (text) => text === "" ? null : JSON.parse(text) as unknown,
67
68
  catch: (_) =>
68
- internalError.responseError({
69
+ new Error.ResponseError({
69
70
  request: this.request,
70
71
  response: this,
71
72
  reason: "Decode",
@@ -79,7 +80,7 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
79
80
  return this.textBody ??= Effect.tryPromise({
80
81
  try: () => this.source.text(),
81
82
  catch: (_) =>
82
- internalError.responseError({
83
+ new Error.ResponseError({
83
84
  request: this.request,
84
85
  response: this,
85
86
  reason: "Decode",
@@ -93,7 +94,7 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
93
94
  Effect.try({
94
95
  try: () => UrlParams.fromInput(new URLSearchParams(_)),
95
96
  catch: (_) =>
96
- internalError.responseError({
97
+ new Error.ResponseError({
97
98
  request: this.request,
98
99
  response: this,
99
100
  reason: "Decode",
@@ -107,7 +108,7 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
107
108
  return this.formDataBody ??= Effect.tryPromise({
108
109
  try: () => this.source.formData(),
109
110
  catch: (_) =>
110
- internalError.responseError({
111
+ new Error.ResponseError({
111
112
  request: this.request,
112
113
  response: this,
113
114
  reason: "Decode",
@@ -121,7 +122,7 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
121
122
  return this.arrayBufferBody ??= Effect.tryPromise({
122
123
  try: () => this.source.arrayBuffer(),
123
124
  catch: (_) =>
124
- internalError.responseError({
125
+ new Error.ResponseError({
125
126
  request: this.request,
126
127
  response: this,
127
128
  reason: "Decode",
@@ -29,7 +29,7 @@ class MultiplexImpl<R, E>
29
29
  this[TypeId] = TypeId
30
30
 
31
31
  let execute: (request: ServerRequest.ServerRequest) => App.Default<R, E | Error.RouteNotFound> = (request) =>
32
- Effect.fail(Error.RouteNotFound({ request }))
32
+ Effect.fail(new Error.RouteNotFound({ request }))
33
33
 
34
34
  for (let i = apps.length - 1; i >= 0; i--) {
35
35
  const [predicate, app] = apps[i]
@@ -151,7 +151,7 @@ const toHttpApp = <R, E>(
151
151
  result = router.find("GET", request.url)
152
152
  }
153
153
  if (result === undefined) {
154
- return Effect.fail(Error.RouteNotFound({ request }))
154
+ return Effect.fail(new Error.RouteNotFound({ request }))
155
155
  }
156
156
  const route = result.handler
157
157
  if (route.prefix._tag === "Some") {
@@ -1,5 +1,4 @@
1
1
  import * as Cause from "effect/Cause"
2
- import * as Data from "effect/Data"
3
2
  import * as FiberId from "effect/FiberId"
4
3
  import { globalValue } from "effect/GlobalValue"
5
4
  import * as Option from "effect/Option"
@@ -11,28 +10,9 @@ export const TypeId: Error.TypeId = Symbol.for(
11
10
  "@effect/platform/Http/Error"
12
11
  ) as Error.TypeId
13
12
 
14
- const make = <A extends Error.HttpServerError>(tag: A["_tag"]) => (props: Omit<A, Error.HttpError.ProvidedFields>): A =>
15
- Data.struct({
16
- [TypeId]: TypeId,
17
- _tag: tag,
18
- ...props
19
- } as A)
20
-
21
13
  /** @internal */
22
14
  export const isServerError = (u: unknown): u is Error.HttpServerError => Predicate.hasProperty(u, TypeId)
23
15
 
24
- /** @internal */
25
- export const requestError = make<Error.RequestError>("RequestError")
26
-
27
- /** @internal */
28
- export const responseError = make<Error.ResponseError>("ResponseError")
29
-
30
- /** @internal */
31
- export const routeNotFound = make<Error.RouteNotFound>("RouteNotFound")
32
-
33
- /** @internal */
34
- export const serveError = make<Error.ServeError>("ServeError")
35
-
36
16
  /** @internal */
37
17
  export const clientAbortFiberId = globalValue(
38
18
  "@effect/platform/Http/ServerError/clientAbortFiberId",
@@ -1,5 +1,6 @@
1
1
  import type * as ParseResult from "@effect/schema/ParseResult"
2
2
  import type * as Schema from "@effect/schema/Schema"
3
+ import * as Channel from "effect/Channel"
3
4
  import * as Context from "effect/Context"
4
5
  import * as Effect from "effect/Effect"
5
6
  import * as Option from "effect/Option"
@@ -14,6 +15,7 @@ import * as Error from "../../Http/ServerError.js"
14
15
  import type * as ServerRequest from "../../Http/ServerRequest.js"
15
16
  import * as UrlParams from "../../Http/UrlParams.js"
16
17
  import type * as Path from "../../Path.js"
18
+ import * as Socket from "../../Socket.js"
17
19
 
18
20
  /** @internal */
19
21
  export const TypeId: ServerRequest.TypeId = Symbol.for("@effect/platform/Http/ServerRequest") as ServerRequest.TypeId
@@ -21,6 +23,12 @@ export const TypeId: ServerRequest.TypeId = Symbol.for("@effect/platform/Http/Se
21
23
  /** @internal */
22
24
  export const serverRequestTag = Context.GenericTag<ServerRequest.ServerRequest>("@effect/platform/Http/ServerRequest")
23
25
 
26
+ /** @internal */
27
+ export const upgrade = Effect.flatMap(serverRequestTag, (request) => request.upgrade)
28
+
29
+ /** @internal */
30
+ export const upgradeChannel = <IE = never>() => Channel.unwrap(Effect.map(upgrade, Socket.toChannelWith<IE>()))
31
+
24
32
  /** @internal */
25
33
  export const multipartPersisted = Effect.flatMap(serverRequestTag, (request) => request.multipart)
26
34
 
@@ -90,7 +98,7 @@ export const schemaBodyFormJson = <A, I, R>(schema: Schema.Schema<A, I, R>) => {
90
98
  if (isMultipart(request)) {
91
99
  return Effect.flatMap(
92
100
  Effect.mapError(request.multipart, (error) =>
93
- Error.RequestError({
101
+ new Error.RequestError({
94
102
  request,
95
103
  reason: "Decode",
96
104
  error
@@ -150,16 +158,18 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
150
158
  get stream(): Stream.Stream<Uint8Array, Error.RequestError> {
151
159
  return this.source.body
152
160
  ? Stream.fromReadableStream(() => this.source.body as any, (_) =>
153
- Error.RequestError({
161
+ new Error.RequestError({
154
162
  request: this,
155
163
  reason: "Decode",
156
164
  error: _
157
165
  }))
158
- : Stream.fail(Error.RequestError({
159
- request: this,
160
- reason: "Decode",
161
- error: "can not create stream from empty body"
162
- }))
166
+ : Stream.fail(
167
+ new Error.RequestError({
168
+ request: this,
169
+ reason: "Decode",
170
+ error: "can not create stream from empty body"
171
+ })
172
+ )
163
173
  }
164
174
 
165
175
  private textEffect: Effect.Effect<string, Error.RequestError> | undefined
@@ -171,7 +181,7 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
171
181
  Effect.tryPromise({
172
182
  try: () => this.source.text(),
173
183
  catch: (error) =>
174
- Error.RequestError({
184
+ new Error.RequestError({
175
185
  request: this,
176
186
  reason: "Decode",
177
187
  error
@@ -185,7 +195,7 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
185
195
  return Effect.tryMap(this.text, {
186
196
  try: (_) => JSON.parse(_) as unknown,
187
197
  catch: (error) =>
188
- Error.RequestError({
198
+ new Error.RequestError({
189
199
  request: this,
190
200
  reason: "Decode",
191
201
  error
@@ -198,7 +208,7 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
198
208
  Effect.try({
199
209
  try: () => UrlParams.fromInput(new URLSearchParams(_)),
200
210
  catch: (error) =>
201
- Error.RequestError({
211
+ new Error.RequestError({
202
212
  request: this,
203
213
  reason: "Decode",
204
214
  error
@@ -243,7 +253,7 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
243
253
  Effect.tryPromise({
244
254
  try: () => this.source.arrayBuffer(),
245
255
  catch: (error) =>
246
- Error.RequestError({
256
+ new Error.RequestError({
247
257
  request: this,
248
258
  reason: "Decode",
249
259
  error
@@ -252,4 +262,14 @@ class ServerRequestImpl implements ServerRequest.ServerRequest {
252
262
  ))
253
263
  return this.arrayBufferEffect
254
264
  }
265
+
266
+ get upgrade(): Effect.Effect<Socket.Socket, Error.RequestError> {
267
+ return Effect.fail(
268
+ new Error.RequestError({
269
+ request: this,
270
+ reason: "Decode",
271
+ error: "Not an upgradeable ServerRequest"
272
+ })
273
+ )
274
+ }
255
275
  }