@effect/platform 0.48.14 → 0.48.16

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 (248) hide show
  1. package/Http/Cookies/package.json +6 -0
  2. package/README.md +235 -46
  3. package/dist/cjs/Command.js +1 -1
  4. package/dist/cjs/Command.js.map +1 -1
  5. package/dist/cjs/CommandExecutor.js +1 -1
  6. package/dist/cjs/CommandExecutor.js.map +1 -1
  7. package/dist/cjs/Effectify.js +1 -1
  8. package/dist/cjs/Effectify.js.map +1 -1
  9. package/dist/cjs/Error.js +1 -1
  10. package/dist/cjs/Error.js.map +1 -1
  11. package/dist/cjs/FileSystem.js +1 -1
  12. package/dist/cjs/FileSystem.js.map +1 -1
  13. package/dist/cjs/Http/App.js +1 -1
  14. package/dist/cjs/Http/App.js.map +1 -1
  15. package/dist/cjs/Http/Body.js +1 -1
  16. package/dist/cjs/Http/Body.js.map +1 -1
  17. package/dist/cjs/Http/Client.js +7 -2
  18. package/dist/cjs/Http/Client.js.map +1 -1
  19. package/dist/cjs/Http/ClientError.js +1 -1
  20. package/dist/cjs/Http/ClientError.js.map +1 -1
  21. package/dist/cjs/Http/ClientRequest.js +1 -1
  22. package/dist/cjs/Http/ClientRequest.js.map +1 -1
  23. package/dist/cjs/Http/ClientResponse.js +1 -1
  24. package/dist/cjs/Http/ClientResponse.js.map +1 -1
  25. package/dist/cjs/Http/Cookies.js +543 -0
  26. package/dist/cjs/Http/Cookies.js.map +1 -0
  27. package/dist/cjs/Http/Etag.js +1 -1
  28. package/dist/cjs/Http/Etag.js.map +1 -1
  29. package/dist/cjs/Http/Headers.js +3 -3
  30. package/dist/cjs/Http/Headers.js.map +1 -1
  31. package/dist/cjs/Http/IncomingMessage.js +1 -1
  32. package/dist/cjs/Http/IncomingMessage.js.map +1 -1
  33. package/dist/cjs/Http/Method.js.map +1 -1
  34. package/dist/cjs/Http/Middleware.js +1 -1
  35. package/dist/cjs/Http/Middleware.js.map +1 -1
  36. package/dist/cjs/Http/Multipart.js +1 -1
  37. package/dist/cjs/Http/Multipart.js.map +1 -1
  38. package/dist/cjs/Http/Multiplex.js +1 -1
  39. package/dist/cjs/Http/Multiplex.js.map +1 -1
  40. package/dist/cjs/Http/Platform.js +1 -1
  41. package/dist/cjs/Http/Platform.js.map +1 -1
  42. package/dist/cjs/Http/Router.js +1 -1
  43. package/dist/cjs/Http/Router.js.map +1 -1
  44. package/dist/cjs/Http/Server.js +1 -1
  45. package/dist/cjs/Http/Server.js.map +1 -1
  46. package/dist/cjs/Http/ServerError.js +1 -1
  47. package/dist/cjs/Http/ServerError.js.map +1 -1
  48. package/dist/cjs/Http/ServerRequest.js +1 -1
  49. package/dist/cjs/Http/ServerRequest.js.map +1 -1
  50. package/dist/cjs/Http/ServerResponse.js +37 -2
  51. package/dist/cjs/Http/ServerResponse.js.map +1 -1
  52. package/dist/cjs/Http/UrlParams.js +1 -1
  53. package/dist/cjs/Http/UrlParams.js.map +1 -1
  54. package/dist/cjs/HttpClient.js +4 -2
  55. package/dist/cjs/HttpClient.js.map +1 -1
  56. package/dist/cjs/HttpServer.js +4 -2
  57. package/dist/cjs/HttpServer.js.map +1 -1
  58. package/dist/cjs/KeyValueStore.js +1 -1
  59. package/dist/cjs/KeyValueStore.js.map +1 -1
  60. package/dist/cjs/Path.js +1 -1
  61. package/dist/cjs/Path.js.map +1 -1
  62. package/dist/cjs/PlatformLogger.js +1 -1
  63. package/dist/cjs/PlatformLogger.js.map +1 -1
  64. package/dist/cjs/Runtime.js +1 -1
  65. package/dist/cjs/Runtime.js.map +1 -1
  66. package/dist/cjs/Socket.js +1 -1
  67. package/dist/cjs/Socket.js.map +1 -1
  68. package/dist/cjs/Template.js +1 -1
  69. package/dist/cjs/Template.js.map +1 -1
  70. package/dist/cjs/Terminal.js +1 -1
  71. package/dist/cjs/Terminal.js.map +1 -1
  72. package/dist/cjs/Transferable.js +1 -1
  73. package/dist/cjs/Transferable.js.map +1 -1
  74. package/dist/cjs/Worker.js +1 -1
  75. package/dist/cjs/Worker.js.map +1 -1
  76. package/dist/cjs/WorkerError.js +1 -1
  77. package/dist/cjs/WorkerError.js.map +1 -1
  78. package/dist/cjs/WorkerRunner.js +1 -1
  79. package/dist/cjs/WorkerRunner.js.map +1 -1
  80. package/dist/cjs/index.js +1 -1
  81. package/dist/cjs/index.js.map +1 -1
  82. package/dist/cjs/internal/command.js +1 -1
  83. package/dist/cjs/internal/command.js.map +1 -1
  84. package/dist/cjs/internal/commandExecutor.js +1 -1
  85. package/dist/cjs/internal/commandExecutor.js.map +1 -1
  86. package/dist/cjs/internal/effectify.js +1 -1
  87. package/dist/cjs/internal/effectify.js.map +1 -1
  88. package/dist/cjs/internal/error.js +1 -1
  89. package/dist/cjs/internal/error.js.map +1 -1
  90. package/dist/cjs/internal/fileSystem.js +1 -1
  91. package/dist/cjs/internal/fileSystem.js.map +1 -1
  92. package/dist/cjs/internal/http/body.js +1 -1
  93. package/dist/cjs/internal/http/body.js.map +1 -1
  94. package/dist/cjs/internal/http/client.js +6 -2
  95. package/dist/cjs/internal/http/client.js.map +1 -1
  96. package/dist/cjs/internal/http/clientError.js.map +1 -1
  97. package/dist/cjs/internal/http/clientRequest.js +1 -1
  98. package/dist/cjs/internal/http/clientRequest.js.map +1 -1
  99. package/dist/cjs/internal/http/clientResponse.js +9 -1
  100. package/dist/cjs/internal/http/clientResponse.js.map +1 -1
  101. package/dist/cjs/internal/http/etag.js +1 -1
  102. package/dist/cjs/internal/http/etag.js.map +1 -1
  103. package/dist/cjs/internal/http/middleware.js +1 -1
  104. package/dist/cjs/internal/http/middleware.js.map +1 -1
  105. package/dist/cjs/internal/http/multipart.js +1 -1
  106. package/dist/cjs/internal/http/multipart.js.map +1 -1
  107. package/dist/cjs/internal/http/multiplex.js +1 -1
  108. package/dist/cjs/internal/http/multiplex.js.map +1 -1
  109. package/dist/cjs/internal/http/platform.js +1 -1
  110. package/dist/cjs/internal/http/platform.js.map +1 -1
  111. package/dist/cjs/internal/http/router.js +1 -1
  112. package/dist/cjs/internal/http/router.js.map +1 -1
  113. package/dist/cjs/internal/http/server.js +1 -1
  114. package/dist/cjs/internal/http/server.js.map +1 -1
  115. package/dist/cjs/internal/http/serverError.js +1 -1
  116. package/dist/cjs/internal/http/serverError.js.map +1 -1
  117. package/dist/cjs/internal/http/serverRequest.js +9 -1
  118. package/dist/cjs/internal/http/serverRequest.js.map +1 -1
  119. package/dist/cjs/internal/http/serverResponse.js +34 -17
  120. package/dist/cjs/internal/http/serverResponse.js.map +1 -1
  121. package/dist/cjs/internal/keyValueStore.js +1 -1
  122. package/dist/cjs/internal/keyValueStore.js.map +1 -1
  123. package/dist/cjs/internal/path.js +1 -1
  124. package/dist/cjs/internal/path.js.map +1 -1
  125. package/dist/cjs/internal/platformLogger.js +1 -1
  126. package/dist/cjs/internal/platformLogger.js.map +1 -1
  127. package/dist/cjs/internal/terminal.js.map +1 -1
  128. package/dist/cjs/internal/worker.js +1 -1
  129. package/dist/cjs/internal/worker.js.map +1 -1
  130. package/dist/cjs/internal/workerError.js.map +1 -1
  131. package/dist/cjs/internal/workerRunner.js +1 -1
  132. package/dist/cjs/internal/workerRunner.js.map +1 -1
  133. package/dist/dts/Error.d.ts.map +1 -1
  134. package/dist/dts/Http/App.d.ts +1 -1
  135. package/dist/dts/Http/App.d.ts.map +1 -1
  136. package/dist/dts/Http/Client.d.ts +10 -0
  137. package/dist/dts/Http/Client.d.ts.map +1 -1
  138. package/dist/dts/Http/ClientResponse.d.ts +2 -0
  139. package/dist/dts/Http/ClientResponse.d.ts.map +1 -1
  140. package/dist/dts/Http/Cookies.d.ts +245 -0
  141. package/dist/dts/Http/Cookies.d.ts.map +1 -0
  142. package/dist/dts/Http/Headers.d.ts +2 -2
  143. package/dist/dts/Http/Headers.d.ts.map +1 -1
  144. package/dist/dts/Http/IncomingMessage.d.ts +2 -2
  145. package/dist/dts/Http/IncomingMessage.d.ts.map +1 -1
  146. package/dist/dts/Http/ServerRequest.d.ts +2 -0
  147. package/dist/dts/Http/ServerRequest.d.ts.map +1 -1
  148. package/dist/dts/Http/ServerResponse.d.ts +75 -0
  149. package/dist/dts/Http/ServerResponse.d.ts.map +1 -1
  150. package/dist/dts/Http/UrlParams.d.ts +1 -1
  151. package/dist/dts/Http/UrlParams.d.ts.map +1 -1
  152. package/dist/dts/HttpClient.d.ts +8 -0
  153. package/dist/dts/HttpClient.d.ts.map +1 -1
  154. package/dist/dts/HttpServer.d.ts +8 -0
  155. package/dist/dts/HttpServer.d.ts.map +1 -1
  156. package/dist/dts/Socket.d.ts +3 -3
  157. package/dist/dts/Socket.d.ts.map +1 -1
  158. package/dist/dts/internal/http/router.d.ts.map +1 -1
  159. package/dist/esm/Command.js.map +1 -1
  160. package/dist/esm/CommandExecutor.js.map +1 -1
  161. package/dist/esm/Effectify.js.map +1 -1
  162. package/dist/esm/Error.js.map +1 -1
  163. package/dist/esm/FileSystem.js.map +1 -1
  164. package/dist/esm/Http/App.js.map +1 -1
  165. package/dist/esm/Http/Body.js.map +1 -1
  166. package/dist/esm/Http/Client.js +5 -0
  167. package/dist/esm/Http/Client.js.map +1 -1
  168. package/dist/esm/Http/ClientError.js.map +1 -1
  169. package/dist/esm/Http/ClientRequest.js.map +1 -1
  170. package/dist/esm/Http/ClientResponse.js.map +1 -1
  171. package/dist/esm/Http/Cookies.js +496 -0
  172. package/dist/esm/Http/Cookies.js.map +1 -0
  173. package/dist/esm/Http/Etag.js.map +1 -1
  174. package/dist/esm/Http/Headers.js +2 -2
  175. package/dist/esm/Http/Headers.js.map +1 -1
  176. package/dist/esm/Http/IncomingMessage.js.map +1 -1
  177. package/dist/esm/Http/Method.js.map +1 -1
  178. package/dist/esm/Http/Middleware.js.map +1 -1
  179. package/dist/esm/Http/Multipart.js.map +1 -1
  180. package/dist/esm/Http/Multiplex.js.map +1 -1
  181. package/dist/esm/Http/Platform.js.map +1 -1
  182. package/dist/esm/Http/Router.js.map +1 -1
  183. package/dist/esm/Http/Server.js.map +1 -1
  184. package/dist/esm/Http/ServerError.js.map +1 -1
  185. package/dist/esm/Http/ServerRequest.js.map +1 -1
  186. package/dist/esm/Http/ServerResponse.js +35 -0
  187. package/dist/esm/Http/ServerResponse.js.map +1 -1
  188. package/dist/esm/Http/UrlParams.js.map +1 -1
  189. package/dist/esm/HttpClient.js +8 -0
  190. package/dist/esm/HttpClient.js.map +1 -1
  191. package/dist/esm/HttpServer.js +8 -0
  192. package/dist/esm/HttpServer.js.map +1 -1
  193. package/dist/esm/KeyValueStore.js.map +1 -1
  194. package/dist/esm/Path.js.map +1 -1
  195. package/dist/esm/PlatformLogger.js.map +1 -1
  196. package/dist/esm/Runtime.js.map +1 -1
  197. package/dist/esm/Socket.js.map +1 -1
  198. package/dist/esm/Template.js.map +1 -1
  199. package/dist/esm/Terminal.js.map +1 -1
  200. package/dist/esm/Transferable.js.map +1 -1
  201. package/dist/esm/Worker.js.map +1 -1
  202. package/dist/esm/WorkerError.js.map +1 -1
  203. package/dist/esm/WorkerRunner.js.map +1 -1
  204. package/dist/esm/index.js.map +1 -1
  205. package/dist/esm/internal/command.js.map +1 -1
  206. package/dist/esm/internal/commandExecutor.js.map +1 -1
  207. package/dist/esm/internal/effectify.js.map +1 -1
  208. package/dist/esm/internal/error.js.map +1 -1
  209. package/dist/esm/internal/fileSystem.js.map +1 -1
  210. package/dist/esm/internal/http/body.js.map +1 -1
  211. package/dist/esm/internal/http/client.js +4 -0
  212. package/dist/esm/internal/http/client.js.map +1 -1
  213. package/dist/esm/internal/http/clientError.js.map +1 -1
  214. package/dist/esm/internal/http/clientRequest.js.map +1 -1
  215. package/dist/esm/internal/http/clientResponse.js +8 -0
  216. package/dist/esm/internal/http/clientResponse.js.map +1 -1
  217. package/dist/esm/internal/http/etag.js.map +1 -1
  218. package/dist/esm/internal/http/middleware.js.map +1 -1
  219. package/dist/esm/internal/http/multipart.js.map +1 -1
  220. package/dist/esm/internal/http/multiplex.js.map +1 -1
  221. package/dist/esm/internal/http/platform.js.map +1 -1
  222. package/dist/esm/internal/http/router.js.map +1 -1
  223. package/dist/esm/internal/http/server.js.map +1 -1
  224. package/dist/esm/internal/http/serverError.js.map +1 -1
  225. package/dist/esm/internal/http/serverRequest.js +8 -0
  226. package/dist/esm/internal/http/serverRequest.js.map +1 -1
  227. package/dist/esm/internal/http/serverResponse.js +32 -15
  228. package/dist/esm/internal/http/serverResponse.js.map +1 -1
  229. package/dist/esm/internal/keyValueStore.js.map +1 -1
  230. package/dist/esm/internal/path.js.map +1 -1
  231. package/dist/esm/internal/platformLogger.js.map +1 -1
  232. package/dist/esm/internal/terminal.js.map +1 -1
  233. package/dist/esm/internal/worker.js.map +1 -1
  234. package/dist/esm/internal/workerError.js.map +1 -1
  235. package/dist/esm/internal/workerRunner.js.map +1 -1
  236. package/package.json +12 -4
  237. package/src/Http/Client.ts +11 -0
  238. package/src/Http/ClientResponse.ts +2 -0
  239. package/src/Http/Cookies.ts +695 -0
  240. package/src/Http/Headers.ts +16 -8
  241. package/src/Http/ServerRequest.ts +2 -0
  242. package/src/Http/ServerResponse.ts +126 -0
  243. package/src/HttpClient.ts +8 -0
  244. package/src/HttpServer.ts +8 -0
  245. package/src/internal/http/client.ts +35 -0
  246. package/src/internal/http/clientResponse.ts +9 -0
  247. package/src/internal/http/serverRequest.ts +10 -0
  248. package/src/internal/http/serverResponse.ts +162 -0
@@ -50,18 +50,21 @@ export const schemaFromSelf: Schema.Schema<Headers> = Schema.declare(isHeaders,
50
50
  * @since 1.0.0
51
51
  * @category schemas
52
52
  */
53
- export const schema: Schema.Schema<Headers, ReadonlyRecord.ReadonlyRecord<string, string>> = Schema.transform(
54
- Schema.record(Schema.string, Schema.string),
55
- schemaFromSelf,
56
- (record) => fromInput(record),
57
- identity
58
- )
53
+ export const schema: Schema.Schema<Headers, ReadonlyRecord.ReadonlyRecord<string, string | ReadonlyArray<string>>> =
54
+ Schema.transform(
55
+ Schema.record(Schema.string, Schema.union(Schema.string, Schema.array(Schema.string))),
56
+ schemaFromSelf,
57
+ (record) => fromInput(record),
58
+ identity
59
+ )
59
60
 
60
61
  /**
61
62
  * @since 1.0.0
62
63
  * @category models
63
64
  */
64
- export type Input = ReadonlyRecord.ReadonlyRecord<string, string> | Iterable<readonly [string, string]>
65
+ export type Input =
66
+ | ReadonlyRecord.ReadonlyRecord<string, string | ReadonlyArray<string>>
67
+ | Iterable<readonly [string, string]>
65
68
 
66
69
  /**
67
70
  * @since 1.0.0
@@ -83,7 +86,12 @@ export const fromInput: (input?: Input) => Headers = (input) => {
83
86
  )) as Headers
84
87
  }
85
88
  return ReadonlyRecord.fromEntries(
86
- Object.entries(input).map(([k, v]) => [k.toLowerCase(), v])
89
+ Object.entries(input).map(([k, v]) =>
90
+ [
91
+ k.toLowerCase(),
92
+ Array.isArray(v) ? v.join(", ") : v
93
+ ] as const
94
+ )
87
95
  ) as Headers
88
96
  }
89
97
 
@@ -7,6 +7,7 @@ import type { Channel } from "effect/Channel"
7
7
  import type { Chunk } from "effect/Chunk"
8
8
  import type * as Context from "effect/Context"
9
9
  import type * as Effect from "effect/Effect"
10
+ import type { ReadonlyRecord } from "effect/ReadonlyRecord"
10
11
  import type * as Scope from "effect/Scope"
11
12
  import type * as Stream from "effect/Stream"
12
13
  import type * as FileSystem from "../FileSystem.js"
@@ -49,6 +50,7 @@ export interface ServerRequest extends IncomingMessage.IncomingMessage<Error.Req
49
50
  readonly url: string
50
51
  readonly originalUrl: string
51
52
  readonly method: Method
53
+ readonly cookies: ReadonlyRecord<string, string>
52
54
 
53
55
  readonly multipart: Effect.Effect<
54
56
  Multipart.Persisted,
@@ -10,6 +10,7 @@ import type * as FileSystem from "../FileSystem.js"
10
10
  import * as internal from "../internal/http/serverResponse.js"
11
11
  import type * as Template from "../Template.js"
12
12
  import type * as Body from "./Body.js"
13
+ import type { Cookie, Cookies, CookiesError } from "./Cookies.js"
13
14
  import type * as Headers from "./Headers.js"
14
15
  import type * as Platform from "./Platform.js"
15
16
  import type * as UrlParams from "./UrlParams.js"
@@ -35,6 +36,7 @@ export interface ServerResponse extends Effect.Effect<ServerResponse>, Inspectab
35
36
  readonly status: number
36
37
  readonly statusText?: string | undefined
37
38
  readonly headers: Headers.Headers
39
+ readonly cookies: Cookies
38
40
  readonly body: Body.Body
39
41
  }
40
42
 
@@ -46,6 +48,7 @@ export interface Options {
46
48
  readonly status?: number | undefined
47
49
  readonly statusText?: string | undefined
48
50
  readonly headers?: Headers.Headers | undefined
51
+ readonly cookies?: Cookies | undefined
49
52
  readonly contentType?: string | undefined
50
53
  readonly contentLength?: number | undefined
51
54
  }
@@ -195,6 +198,129 @@ export const setHeaders: {
195
198
  (self: ServerResponse, input: Headers.Input): ServerResponse
196
199
  } = internal.setHeaders
197
200
 
201
+ /**
202
+ * @since 1.0.0
203
+ * @category combinators
204
+ */
205
+ export const removeCookie: {
206
+ (name: string): (self: ServerResponse) => ServerResponse
207
+ (self: ServerResponse, name: string): ServerResponse
208
+ } = internal.removeCookie
209
+
210
+ /**
211
+ * @since 1.0.0
212
+ * @category combinators
213
+ */
214
+ export const replaceCookies: {
215
+ (cookies: Cookies): (self: ServerResponse) => ServerResponse
216
+ (self: ServerResponse, cookies: Cookies): ServerResponse
217
+ } = internal.replaceCookies
218
+
219
+ /**
220
+ * @since 1.0.0
221
+ * @category combinators
222
+ */
223
+ export const setCookie: {
224
+ (
225
+ name: string,
226
+ value: string,
227
+ options?: Cookie["options"]
228
+ ): (
229
+ self: ServerResponse
230
+ ) => Effect.Effect<
231
+ ServerResponse,
232
+ CookiesError
233
+ >
234
+ (
235
+ self: ServerResponse,
236
+ name: string,
237
+ value: string,
238
+ options?: Cookie["options"]
239
+ ): Effect.Effect<
240
+ ServerResponse,
241
+ CookiesError
242
+ >
243
+ } = internal.setCookie
244
+
245
+ /**
246
+ * @since 1.0.0
247
+ * @category combinators
248
+ */
249
+ export const unsafeSetCookie: {
250
+ (
251
+ name: string,
252
+ value: string,
253
+ options?: Cookie["options"]
254
+ ): (self: ServerResponse) => ServerResponse
255
+ (
256
+ self: ServerResponse,
257
+ name: string,
258
+ value: string,
259
+ options?: Cookie["options"]
260
+ ): ServerResponse
261
+ } = internal.unsafeSetCookie
262
+
263
+ /**
264
+ * @since 1.0.0
265
+ * @category combinators
266
+ */
267
+ export const updateCookies: {
268
+ (f: (cookies: Cookies) => Cookies): (self: ServerResponse) => ServerResponse
269
+ (self: ServerResponse, f: (cookies: Cookies) => Cookies): ServerResponse
270
+ } = internal.updateCookies
271
+
272
+ /**
273
+ * @since 1.0.0
274
+ * @category combinators
275
+ */
276
+ export const setCookies: {
277
+ (
278
+ cookies: Iterable<
279
+ readonly [
280
+ name: string,
281
+ value: string,
282
+ options?: Cookie["options"]
283
+ ]
284
+ >
285
+ ): (self: ServerResponse) => Effect.Effect<ServerResponse, CookiesError, never>
286
+ (
287
+ self: ServerResponse,
288
+ cookies: Iterable<
289
+ readonly [
290
+ name: string,
291
+ value: string,
292
+ options?: Cookie["options"]
293
+ ]
294
+ >
295
+ ): Effect.Effect<ServerResponse, CookiesError, never>
296
+ } = internal.setCookies
297
+
298
+ /**
299
+ * @since 1.0.0
300
+ * @category combinators
301
+ */
302
+ export const unsafeSetCookies: {
303
+ (
304
+ cookies: Iterable<
305
+ readonly [
306
+ name: string,
307
+ value: string,
308
+ options?: Cookie["options"]
309
+ ]
310
+ >
311
+ ): (self: ServerResponse) => ServerResponse
312
+ (
313
+ self: ServerResponse,
314
+ cookies: Iterable<
315
+ readonly [
316
+ name: string,
317
+ value: string,
318
+ options?: Cookie["options"]
319
+ ]
320
+ >
321
+ ): ServerResponse
322
+ } = internal.unsafeSetCookies
323
+
198
324
  /**
199
325
  * @since 1.0.0
200
326
  * @category combinators
package/src/HttpClient.ts CHANGED
@@ -6,6 +6,7 @@ import * as client from "./Http/Client.js"
6
6
  import * as error from "./Http/ClientError.js"
7
7
  import * as request from "./Http/ClientRequest.js"
8
8
  import * as response from "./Http/ClientResponse.js"
9
+ import * as cookies from "./Http/Cookies.js"
9
10
  import * as headers from "./Http/Headers.js"
10
11
  import * as urlParams from "./Http/UrlParams.js"
11
12
 
@@ -24,6 +25,13 @@ export {
24
25
  * - Module: `@effect/platform/Http/Client`
25
26
  */
26
27
  client,
28
+ /**
29
+ * @since 1.0.0
30
+ *
31
+ * - Docs: [Http/Cookies](https://effect-ts.github.io/effect/platform/Http/Cookies.ts.html)
32
+ * - Module: `@effect/platform/Http/Cookies`
33
+ */
34
+ cookies,
27
35
  /**
28
36
  * @since 1.0.0
29
37
  *
package/src/HttpServer.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import * as app from "./Http/App.js"
5
5
  import * as body from "./Http/Body.js"
6
+ import * as cookies from "./Http/Cookies.js"
6
7
  import * as etag from "./Http/Etag.js"
7
8
  import * as headers from "./Http/Headers.js"
8
9
  import * as middleware from "./Http/Middleware.js"
@@ -31,6 +32,13 @@ export {
31
32
  * - Module: `@effect/platform/Http/Body`
32
33
  */
33
34
  body,
35
+ /**
36
+ * @since 1.0.0
37
+ *
38
+ * - Docs: [Http/Cookies](https://effect-ts.github.io/effect/platform/Http/Cookies.ts.html)
39
+ * - Module: `@effect/platform/Http/Cookies`
40
+ */
41
+ cookies,
34
42
  /**
35
43
  * @since 1.0.0
36
44
  *
@@ -6,6 +6,7 @@ import { dual, pipe } from "effect/Function"
6
6
  import * as Layer from "effect/Layer"
7
7
  import { pipeArguments } from "effect/Pipeable"
8
8
  import type * as Predicate from "effect/Predicate"
9
+ import * as Ref from "effect/Ref"
9
10
  import type * as Schedule from "effect/Schedule"
10
11
  import type * as Scope from "effect/Scope"
11
12
  import * as Stream from "effect/Stream"
@@ -14,6 +15,7 @@ import type * as Client from "../../Http/Client.js"
14
15
  import * as Error from "../../Http/ClientError.js"
15
16
  import type * as ClientRequest from "../../Http/ClientRequest.js"
16
17
  import type * as ClientResponse from "../../Http/ClientResponse.js"
18
+ import * as Cookies from "../../Http/Cookies.js"
17
19
  import * as Method from "../../Http/Method.js"
18
20
  import * as UrlParams from "../../Http/UrlParams.js"
19
21
  import * as internalBody from "./body.js"
@@ -609,3 +611,36 @@ export const tapRequest = dual<
609
611
  f: (a: ClientRequest.ClientRequest) => Effect.Effect<_, E2, R2>
610
612
  ) => Client.Client<R | R2, E | E2, A>
611
613
  >(2, (self, f) => make(self.execute as any, (request) => Effect.tap(self.preprocess(request), f)))
614
+
615
+ /** @internal */
616
+ export const withCookiesRef = dual<
617
+ (
618
+ ref: Ref.Ref<Cookies.Cookies>
619
+ ) => <R, E>(self: Client.Client.WithResponse<R, E>) => Client.Client.WithResponse<R, E>,
620
+ <R, E>(
621
+ self: Client.Client.WithResponse<R, E>,
622
+ ref: Ref.Ref<Cookies.Cookies>
623
+ ) => Client.Client.WithResponse<R, E>
624
+ >(
625
+ 2,
626
+ <R, E>(
627
+ self: Client.Client.WithResponse<R, E>,
628
+ ref: Ref.Ref<Cookies.Cookies>
629
+ ): Client.Client.WithResponse<R, E> =>
630
+ make(
631
+ (request: Effect.Effect<ClientRequest.ClientRequest, E, R>) =>
632
+ Effect.tap(
633
+ self.execute(request),
634
+ (response) => Ref.update(ref, (cookies) => Cookies.merge(cookies, response.cookies))
635
+ ),
636
+ (request) =>
637
+ Effect.flatMap(self.preprocess(request), (request) =>
638
+ Effect.map(
639
+ Ref.get(ref),
640
+ (cookies) =>
641
+ Cookies.isEmpty(cookies)
642
+ ? request
643
+ : internalRequest.setHeader(request, "cookie", Cookies.toCookieHeader(cookies))
644
+ ))
645
+ )
646
+ )
@@ -7,6 +7,7 @@ import * as Stream from "effect/Stream"
7
7
  import * as Error from "../../Http/ClientError.js"
8
8
  import type * as ClientRequest from "../../Http/ClientRequest.js"
9
9
  import type * as ClientResponse from "../../Http/ClientResponse.js"
10
+ import * as Cookies from "../../Http/Cookies.js"
10
11
  import * as Headers from "../../Http/Headers.js"
11
12
  import * as IncomingMessage from "../../Http/IncomingMessage.js"
12
13
  import * as UrlParams from "../../Http/UrlParams.js"
@@ -49,6 +50,14 @@ class ClientResponseImpl extends Inspectable.Class implements ClientResponse.Cli
49
50
  return Headers.fromInput(this.source.headers)
50
51
  }
51
52
 
53
+ cachedCookies?: Cookies.Cookies
54
+ get cookies(): Cookies.Cookies {
55
+ if (this.cachedCookies) {
56
+ return this.cachedCookies
57
+ }
58
+ return this.cachedCookies = Cookies.fromSetCookie(this.source.headers.getSetCookie())
59
+ }
60
+
52
61
  get remoteAddress(): Option.Option<string> {
53
62
  return Option.none()
54
63
  }
@@ -5,9 +5,11 @@ import * as Context from "effect/Context"
5
5
  import * as Effect from "effect/Effect"
6
6
  import * as Inspectable from "effect/Inspectable"
7
7
  import * as Option from "effect/Option"
8
+ import type { ReadonlyRecord } from "effect/ReadonlyRecord"
8
9
  import type * as Scope from "effect/Scope"
9
10
  import * as Stream from "effect/Stream"
10
11
  import type * as FileSystem from "../../FileSystem.js"
12
+ import * as Cookies from "../../Http/Cookies.js"
11
13
  import * as Headers from "../../Http/Headers.js"
12
14
  import * as IncomingMessage from "../../Http/IncomingMessage.js"
13
15
  import type { Method } from "../../Http/Method.js"
@@ -164,6 +166,14 @@ class ServerRequestImpl extends Inspectable.Class implements ServerRequest.Serve
164
166
  return this.headersOverride
165
167
  }
166
168
 
169
+ private cachedCookies: ReadonlyRecord<string, string> | undefined
170
+ get cookies() {
171
+ if (this.cachedCookies) {
172
+ return this.cachedCookies
173
+ }
174
+ return this.cachedCookies = Cookies.parseHeader(this.headers.cookie ?? "")
175
+ }
176
+
167
177
  get stream(): Stream.Stream<Uint8Array, Error.RequestError> {
168
178
  return this.source.body
169
179
  ? Stream.fromReadableStream(() => this.source.body as any, (_) =>
@@ -7,6 +7,7 @@ import * as Stream from "effect/Stream"
7
7
  import type * as PlatformError from "../../Error.js"
8
8
  import type * as FileSystem from "../../FileSystem.js"
9
9
  import type * as Body from "../../Http/Body.js"
10
+ import * as Cookies from "../../Http/Cookies.js"
10
11
  import * as Headers from "../../Http/Headers.js"
11
12
  import * as Platform from "../../Http/Platform.js"
12
13
  import type * as ServerResponse from "../../Http/ServerResponse.js"
@@ -26,6 +27,7 @@ class ServerResponseImpl extends Effectable.StructuralClass<ServerResponse.Serve
26
27
  readonly status: number,
27
28
  readonly statusText: string | undefined,
28
29
  headers: Headers.Headers,
30
+ readonly cookies: Cookies.Cookies,
29
31
  readonly body: Body.Body
30
32
  ) {
31
33
  super()
@@ -77,6 +79,7 @@ export const empty = (options?: ServerResponse.Options.WithContent): ServerRespo
77
79
  options?.status ?? 204,
78
80
  options?.statusText,
79
81
  options?.headers ?? Headers.empty,
82
+ options?.cookies ?? Cookies.empty,
80
83
  internalBody.empty
81
84
  )
82
85
 
@@ -89,6 +92,7 @@ export const uint8Array = (
89
92
  options?.status ?? 200,
90
93
  options?.statusText,
91
94
  options?.headers ?? Headers.empty,
95
+ options?.cookies ?? Cookies.empty,
92
96
  internalBody.uint8Array(body, getContentType(options))
93
97
  )
94
98
 
@@ -98,6 +102,7 @@ export const text = (body: string, options?: ServerResponse.Options.WithContentT
98
102
  options?.status ?? 200,
99
103
  options?.statusText,
100
104
  options?.headers ?? Headers.empty,
105
+ options?.cookies ?? Cookies.empty,
101
106
  internalBody.text(body, getContentType(options))
102
107
  )
103
108
 
@@ -157,6 +162,7 @@ export const json = (
157
162
  options?.status ?? 200,
158
163
  options?.statusText,
159
164
  options?.headers ?? Headers.empty,
165
+ options?.cookies ?? Cookies.empty,
160
166
  body
161
167
  ))
162
168
 
@@ -169,6 +175,7 @@ export const unsafeJson = (
169
175
  options?.status ?? 200,
170
176
  options?.statusText,
171
177
  options?.headers ?? Headers.empty,
178
+ options?.cookies ?? Cookies.empty,
172
179
  internalBody.unsafeJson(body)
173
180
  )
174
181
 
@@ -186,6 +193,7 @@ export const schemaJson = <A, I, R>(
186
193
  options?.status ?? 200,
187
194
  options?.statusText,
188
195
  options?.headers ?? Headers.empty,
196
+ options?.cookies ?? Cookies.empty,
189
197
  body
190
198
  ))
191
199
  }
@@ -219,6 +227,7 @@ export const urlParams = (
219
227
  options?.status ?? 200,
220
228
  options?.statusText,
221
229
  options?.headers ?? Headers.empty,
230
+ options?.cookies ?? Cookies.empty,
222
231
  internalBody.text(UrlParams.toString(UrlParams.fromInput(body)), "application/x-www-form-urlencoded")
223
232
  )
224
233
 
@@ -228,6 +237,7 @@ export const raw = (body: unknown, options?: ServerResponse.Options): ServerResp
228
237
  options?.status ?? 200,
229
238
  options?.statusText,
230
239
  options?.headers ?? Headers.empty,
240
+ options?.cookies ?? Cookies.empty,
231
241
  internalBody.raw(body)
232
242
  )
233
243
 
@@ -240,6 +250,7 @@ export const formData = (
240
250
  options?.status ?? 200,
241
251
  options?.statusText,
242
252
  options?.headers ?? Headers.empty,
253
+ options?.cookies ?? Cookies.empty,
243
254
  internalBody.formData(body)
244
255
  )
245
256
 
@@ -252,6 +263,7 @@ export const stream = (
252
263
  options?.status ?? 200,
253
264
  options?.statusText,
254
265
  options?.headers ?? Headers.empty,
266
+ options?.cookies ?? Cookies.empty,
255
267
  internalBody.stream(body, getContentType(options), options?.contentLength)
256
268
  )
257
269
 
@@ -275,9 +287,156 @@ export const setHeader = dual<
275
287
  self.status,
276
288
  self.statusText,
277
289
  Headers.set(self.headers, key, value),
290
+ self.cookies,
278
291
  self.body
279
292
  ))
280
293
 
294
+ /** @internal */
295
+ export const replaceCookies = dual<
296
+ (cookies: Cookies.Cookies) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
297
+ (self: ServerResponse.ServerResponse, cookies: Cookies.Cookies) => ServerResponse.ServerResponse
298
+ >(2, (self, cookies) =>
299
+ new ServerResponseImpl(
300
+ self.status,
301
+ self.statusText,
302
+ self.headers,
303
+ cookies,
304
+ self.body
305
+ ))
306
+
307
+ /** @internal */
308
+ export const setCookie = dual<
309
+ (
310
+ name: string,
311
+ value: string,
312
+ options?: Cookies.Cookie["options"]
313
+ ) => (self: ServerResponse.ServerResponse) => Effect.Effect<ServerResponse.ServerResponse, Cookies.CookiesError>,
314
+ (
315
+ self: ServerResponse.ServerResponse,
316
+ name: string,
317
+ value: string,
318
+ options?: Cookies.Cookie["options"]
319
+ ) => Effect.Effect<ServerResponse.ServerResponse, Cookies.CookiesError>
320
+ >(
321
+ (args) => Cookies.isCookies(args[0]),
322
+ (self, name, value, options) =>
323
+ Effect.map(Cookies.add(self.cookies, name, value, options), (cookies) =>
324
+ new ServerResponseImpl(
325
+ self.status,
326
+ self.statusText,
327
+ self.headers,
328
+ cookies,
329
+ self.body
330
+ ))
331
+ )
332
+
333
+ /** @internal */
334
+ export const unsafeSetCookie = dual<
335
+ (
336
+ name: string,
337
+ value: string,
338
+ options?: Cookies.Cookie["options"]
339
+ ) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
340
+ (
341
+ self: ServerResponse.ServerResponse,
342
+ name: string,
343
+ value: string,
344
+ options?: Cookies.Cookie["options"]
345
+ ) => ServerResponse.ServerResponse
346
+ >(
347
+ (args) => Cookies.isCookies(args[0]),
348
+ (self, name, value, options) =>
349
+ new ServerResponseImpl(
350
+ self.status,
351
+ self.statusText,
352
+ self.headers,
353
+ Cookies.unsafeAdd(self.cookies, name, value, options),
354
+ self.body
355
+ )
356
+ )
357
+
358
+ /** @internal */
359
+ export const updateCookies = dual<
360
+ (
361
+ f: (cookies: Cookies.Cookies) => Cookies.Cookies
362
+ ) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
363
+ (
364
+ self: ServerResponse.ServerResponse,
365
+ f: (cookies: Cookies.Cookies) => Cookies.Cookies
366
+ ) => ServerResponse.ServerResponse
367
+ >(2, (self, f) =>
368
+ new ServerResponseImpl(
369
+ self.status,
370
+ self.statusText,
371
+ self.headers,
372
+ f(self.cookies),
373
+ self.body
374
+ ))
375
+
376
+ /** @internal */
377
+ export const setCookies = dual<
378
+ (
379
+ cookies: Iterable<readonly [name: string, value: string, options?: Cookies.Cookie["options"]]>
380
+ ) => (self: ServerResponse.ServerResponse) => Effect.Effect<ServerResponse.ServerResponse, Cookies.CookiesError>,
381
+ (
382
+ self: ServerResponse.ServerResponse,
383
+ cookies: Iterable<readonly [name: string, value: string, options?: Cookies.Cookie["options"]]>
384
+ ) => Effect.Effect<ServerResponse.ServerResponse, Cookies.CookiesError>
385
+ >(
386
+ 2,
387
+ (self, cookies) =>
388
+ Effect.map(Cookies.addAll(self.cookies, cookies), (cookies) =>
389
+ new ServerResponseImpl(
390
+ self.status,
391
+ self.statusText,
392
+ self.headers,
393
+ cookies,
394
+ self.body
395
+ ))
396
+ )
397
+
398
+ /** @internal */
399
+ export const unsafeSetCookies = dual<
400
+ (
401
+ cookies: Iterable<readonly [name: string, value: string, options?: Cookies.Cookie["options"]]>
402
+ ) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
403
+ (
404
+ self: ServerResponse.ServerResponse,
405
+ cookies: Iterable<readonly [name: string, value: string, options?: Cookies.Cookie["options"]]>
406
+ ) => ServerResponse.ServerResponse
407
+ >(
408
+ 2,
409
+ (self, cookies) =>
410
+ new ServerResponseImpl(
411
+ self.status,
412
+ self.statusText,
413
+ self.headers,
414
+ Cookies.unsafeAddAll(self.cookies, cookies),
415
+ self.body
416
+ )
417
+ )
418
+
419
+ /** @internal */
420
+ export const removeCookie = dual<
421
+ (
422
+ name: string
423
+ ) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
424
+ (
425
+ self: ServerResponse.ServerResponse,
426
+ name: string
427
+ ) => ServerResponse.ServerResponse
428
+ >(
429
+ 2,
430
+ (self, name) =>
431
+ new ServerResponseImpl(
432
+ self.status,
433
+ self.statusText,
434
+ self.headers,
435
+ Cookies.remove(self.cookies, name),
436
+ self.body
437
+ )
438
+ )
439
+
281
440
  /** @internal */
282
441
  export const setHeaders = dual<
283
442
  (input: Headers.Input) => (self: ServerResponse.ServerResponse) => ServerResponse.ServerResponse,
@@ -287,6 +446,7 @@ export const setHeaders = dual<
287
446
  self.status,
288
447
  self.statusText,
289
448
  Headers.setAll(self.headers, input),
449
+ self.cookies,
290
450
  self.body
291
451
  ))
292
452
 
@@ -299,6 +459,7 @@ export const setStatus = dual<
299
459
  status,
300
460
  statusText,
301
461
  self.headers,
462
+ self.cookies,
302
463
  self.body
303
464
  ))
304
465
 
@@ -315,6 +476,7 @@ export const setBody = dual<
315
476
  self.status,
316
477
  self.statusText,
317
478
  headers,
479
+ self.cookies,
318
480
  body
319
481
  )
320
482
  })