@effect/platform 0.79.3 → 0.80.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 (105) hide show
  1. package/ChannelSchema/package.json +6 -0
  2. package/MsgPack/package.json +6 -0
  3. package/Ndjson/package.json +6 -0
  4. package/SocketServer/package.json +6 -0
  5. package/dist/cjs/ChannelSchema.js +69 -0
  6. package/dist/cjs/ChannelSchema.js.map +1 -0
  7. package/dist/cjs/Headers.js +1 -1
  8. package/dist/cjs/Headers.js.map +1 -1
  9. package/dist/cjs/HttpApiClient.js +1 -1
  10. package/dist/cjs/HttpApiClient.js.map +1 -1
  11. package/dist/cjs/HttpApiEndpoint.js +11 -1
  12. package/dist/cjs/HttpApiEndpoint.js.map +1 -1
  13. package/dist/cjs/HttpBody.js.map +1 -1
  14. package/dist/cjs/HttpRouter.js.map +1 -1
  15. package/dist/cjs/MsgPack.js +148 -0
  16. package/dist/cjs/MsgPack.js.map +1 -0
  17. package/dist/cjs/Ndjson.js +152 -0
  18. package/dist/cjs/Ndjson.js.map +1 -0
  19. package/dist/cjs/SocketServer.js +43 -0
  20. package/dist/cjs/SocketServer.js.map +1 -0
  21. package/dist/cjs/Transferable.js +6 -5
  22. package/dist/cjs/Transferable.js.map +1 -1
  23. package/dist/cjs/Url.js.map +1 -1
  24. package/dist/cjs/UrlParams.js +19 -1
  25. package/dist/cjs/UrlParams.js.map +1 -1
  26. package/dist/cjs/WorkerRunner.js.map +1 -1
  27. package/dist/cjs/index.js +9 -1
  28. package/dist/cjs/internal/httpRouter.js +2 -0
  29. package/dist/cjs/internal/httpRouter.js.map +1 -1
  30. package/dist/cjs/internal/worker.js +1 -1
  31. package/dist/cjs/internal/worker.js.map +1 -1
  32. package/dist/dts/ChannelSchema.d.ts +69 -0
  33. package/dist/dts/ChannelSchema.d.ts.map +1 -0
  34. package/dist/dts/Headers.d.ts +1 -1
  35. package/dist/dts/Headers.d.ts.map +1 -1
  36. package/dist/dts/HttpApiClient.d.ts +3 -3
  37. package/dist/dts/HttpApiClient.d.ts.map +1 -1
  38. package/dist/dts/HttpApiEndpoint.d.ts +32 -0
  39. package/dist/dts/HttpApiEndpoint.d.ts.map +1 -1
  40. package/dist/dts/HttpBody.d.ts +1 -1
  41. package/dist/dts/HttpBody.d.ts.map +1 -1
  42. package/dist/dts/HttpRouter.d.ts +3 -0
  43. package/dist/dts/HttpRouter.d.ts.map +1 -1
  44. package/dist/dts/MsgPack.d.ts +103 -0
  45. package/dist/dts/MsgPack.d.ts.map +1 -0
  46. package/dist/dts/Ndjson.d.ts +169 -0
  47. package/dist/dts/Ndjson.d.ts.map +1 -0
  48. package/dist/dts/SocketServer.d.ts +70 -0
  49. package/dist/dts/SocketServer.d.ts.map +1 -0
  50. package/dist/dts/Transferable.d.ts +2 -2
  51. package/dist/dts/Transferable.d.ts.map +1 -1
  52. package/dist/dts/Url.d.ts +2 -2
  53. package/dist/dts/Url.d.ts.map +1 -1
  54. package/dist/dts/UrlParams.d.ts +8 -1
  55. package/dist/dts/UrlParams.d.ts.map +1 -1
  56. package/dist/dts/WorkerRunner.d.ts +3 -1
  57. package/dist/dts/WorkerRunner.d.ts.map +1 -1
  58. package/dist/dts/index.d.ts +16 -0
  59. package/dist/dts/index.d.ts.map +1 -1
  60. package/dist/dts/internal/httpRouter.d.ts.map +1 -1
  61. package/dist/esm/ChannelSchema.js +59 -0
  62. package/dist/esm/ChannelSchema.js.map +1 -0
  63. package/dist/esm/Headers.js +1 -1
  64. package/dist/esm/Headers.js.map +1 -1
  65. package/dist/esm/HttpApiClient.js +1 -1
  66. package/dist/esm/HttpApiClient.js.map +1 -1
  67. package/dist/esm/HttpApiEndpoint.js +10 -0
  68. package/dist/esm/HttpApiEndpoint.js.map +1 -1
  69. package/dist/esm/HttpBody.js.map +1 -1
  70. package/dist/esm/HttpRouter.js.map +1 -1
  71. package/dist/esm/MsgPack.js +137 -0
  72. package/dist/esm/MsgPack.js.map +1 -0
  73. package/dist/esm/Ndjson.js +134 -0
  74. package/dist/esm/Ndjson.js.map +1 -0
  75. package/dist/esm/SocketServer.js +32 -0
  76. package/dist/esm/SocketServer.js.map +1 -0
  77. package/dist/esm/Transferable.js +6 -5
  78. package/dist/esm/Transferable.js.map +1 -1
  79. package/dist/esm/Url.js.map +1 -1
  80. package/dist/esm/UrlParams.js +18 -0
  81. package/dist/esm/UrlParams.js.map +1 -1
  82. package/dist/esm/WorkerRunner.js.map +1 -1
  83. package/dist/esm/index.js +16 -0
  84. package/dist/esm/index.js.map +1 -1
  85. package/dist/esm/internal/httpRouter.js +2 -0
  86. package/dist/esm/internal/httpRouter.js.map +1 -1
  87. package/dist/esm/internal/worker.js +1 -1
  88. package/dist/esm/internal/worker.js.map +1 -1
  89. package/package.json +35 -2
  90. package/src/ChannelSchema.ts +267 -0
  91. package/src/Headers.ts +2 -2
  92. package/src/HttpApiClient.ts +9 -5
  93. package/src/HttpApiEndpoint.ts +36 -6
  94. package/src/HttpBody.ts +1 -1
  95. package/src/HttpRouter.ts +9 -0
  96. package/src/MsgPack.ts +372 -0
  97. package/src/Ndjson.ts +493 -0
  98. package/src/SocketServer.ts +79 -0
  99. package/src/Transferable.ts +9 -8
  100. package/src/Url.ts +5 -5
  101. package/src/UrlParams.ts +29 -2
  102. package/src/WorkerRunner.ts +3 -1
  103. package/src/index.ts +20 -0
  104. package/src/internal/httpRouter.ts +2 -0
  105. package/src/internal/worker.ts +1 -1
package/src/Ndjson.ts ADDED
@@ -0,0 +1,493 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import { TypeIdError } from "@effect/platform/Error"
5
+ import type * as Cause from "effect/Cause"
6
+ import * as Channel from "effect/Channel"
7
+ import * as Chunk from "effect/Chunk"
8
+ import * as Effect from "effect/Effect"
9
+ import { dual, identity } from "effect/Function"
10
+ import type { ParseError } from "effect/ParseResult"
11
+ import type * as Schema from "effect/Schema"
12
+ import * as ChannelSchema from "./ChannelSchema.js"
13
+
14
+ /**
15
+ * @since 1.0.0
16
+ * @category type ids
17
+ */
18
+ export const ErrorTypeId: unique symbol = Symbol.for("@effect/platform/Ndjson/NdjsonError")
19
+
20
+ /**
21
+ * @since 1.0.0
22
+ * @category type ids
23
+ */
24
+ export type NdjsonErrorTypeId = typeof ErrorTypeId
25
+
26
+ const encoder = new TextEncoder()
27
+
28
+ /**
29
+ * @since 1.0.0
30
+ * @category errors
31
+ */
32
+ export class NdjsonError extends TypeIdError(ErrorTypeId, "NdjsonError")<{
33
+ readonly reason: "Pack" | "Unpack"
34
+ readonly cause: unknown
35
+ }> {
36
+ get message() {
37
+ return this.reason
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Represents a set of options which can be used to control how the newline
43
+ * delimited JSON is handled.
44
+ *
45
+ * @since 1.0.0
46
+ * @category models
47
+ */
48
+ export interface NdjsonOptions {
49
+ /**
50
+ * Whether or not the newline delimited JSON parser should ignore empty lines.
51
+ *
52
+ * Defaults to `false`.
53
+ *
54
+ * From the [newline delimited JSON spec](https://github.com/ndjson/ndjson-spec):
55
+ * ```text
56
+ * The parser MAY silently ignore empty lines, e.g. \n\n. This behavior MUST
57
+ * be documented and SHOULD be configurable by the user of the parser.
58
+ * ```
59
+ *
60
+ * @since 1.0.0
61
+ */
62
+ readonly ignoreEmptyLines?: boolean
63
+ }
64
+
65
+ /**
66
+ * @since 1.0.0
67
+ * @category constructors
68
+ */
69
+ export const packString = <IE = never, Done = unknown>(): Channel.Channel<
70
+ Chunk.Chunk<string>,
71
+ Chunk.Chunk<unknown>,
72
+ IE | NdjsonError,
73
+ IE,
74
+ Done,
75
+ Done
76
+ > => {
77
+ const loop: Channel.Channel<
78
+ Chunk.Chunk<string>,
79
+ Chunk.Chunk<unknown>,
80
+ IE | NdjsonError,
81
+ IE,
82
+ Done,
83
+ Done
84
+ > = Channel.readWithCause({
85
+ onInput: (input: Chunk.Chunk<unknown>) =>
86
+ Channel.zipRight(
87
+ Channel.flatMap(
88
+ Effect.try({
89
+ try: () => Chunk.of(Chunk.toReadonlyArray(input).map((_) => JSON.stringify(_)).join("\n") + "\n"),
90
+ catch: (cause) => new NdjsonError({ reason: "Pack", cause })
91
+ }),
92
+ Channel.write
93
+ ),
94
+ loop
95
+ ),
96
+ onFailure: Channel.failCause,
97
+ onDone: Channel.succeed
98
+ })
99
+ return loop
100
+ }
101
+
102
+ /**
103
+ * @since 1.0.0
104
+ * @category constructors
105
+ */
106
+ export const pack = <IE = never, Done = unknown>(): Channel.Channel<
107
+ Chunk.Chunk<Uint8Array>,
108
+ Chunk.Chunk<unknown>,
109
+ IE | NdjsonError,
110
+ IE,
111
+ Done,
112
+ Done
113
+ > => Channel.mapOut(packString(), Chunk.map((_) => encoder.encode(_)))
114
+
115
+ /**
116
+ * @since 1.0.0
117
+ * @category constructors
118
+ */
119
+ export const packSchema = <A, I, R>(
120
+ schema: Schema.Schema<A, I, R>
121
+ ) =>
122
+ <IE = never, Done = unknown>(): Channel.Channel<
123
+ Chunk.Chunk<Uint8Array>,
124
+ Chunk.Chunk<A>,
125
+ IE | NdjsonError | ParseError,
126
+ IE,
127
+ Done,
128
+ Done,
129
+ R
130
+ > => Channel.pipeTo(ChannelSchema.encode(schema)(), pack())
131
+
132
+ /**
133
+ * @since 1.0.0
134
+ * @category constructors
135
+ */
136
+ export const packSchemaString = <A, I, R>(
137
+ schema: Schema.Schema<A, I, R>
138
+ ) =>
139
+ <IE = never, Done = unknown>(): Channel.Channel<
140
+ Chunk.Chunk<string>,
141
+ Chunk.Chunk<A>,
142
+ IE | NdjsonError | ParseError,
143
+ IE,
144
+ Done,
145
+ Done,
146
+ R
147
+ > => Channel.pipeTo(ChannelSchema.encode(schema)(), packString())
148
+
149
+ const filterEmpty = Chunk.filter<string>((line) => line.length > 0)
150
+ const filterEmptyChannel = <IE, Done>() => {
151
+ const loop: Channel.Channel<
152
+ Chunk.Chunk<string>,
153
+ Chunk.Chunk<string>,
154
+ IE,
155
+ IE,
156
+ Done,
157
+ Done,
158
+ never
159
+ > = Channel.readWithCause({
160
+ onInput(input: Chunk.Chunk<string>) {
161
+ const filtered = filterEmpty(input)
162
+ return Channel.zipRight(Chunk.isEmpty(filtered) ? Channel.void : Channel.write(filtered), loop)
163
+ },
164
+ onFailure(cause: Cause.Cause<IE>) {
165
+ return Channel.failCause(cause)
166
+ },
167
+ onDone(done: Done) {
168
+ return Channel.succeed(done)
169
+ }
170
+ })
171
+ return loop
172
+ }
173
+
174
+ /**
175
+ * @since 1.0.0
176
+ * @category constructors
177
+ */
178
+ export const unpackString = <IE = never, Done = unknown>(options?: NdjsonOptions): Channel.Channel<
179
+ Chunk.Chunk<unknown>,
180
+ Chunk.Chunk<string>,
181
+ IE | NdjsonError,
182
+ IE,
183
+ Done,
184
+ Done
185
+ > => {
186
+ const lines = Channel.splitLines<IE, Done>().pipe(
187
+ options?.ignoreEmptyLines === true ?
188
+ Channel.pipeTo(filterEmptyChannel()) :
189
+ identity
190
+ )
191
+ return Channel.mapOutEffect(lines, (chunk) =>
192
+ Effect.try({
193
+ try: () => Chunk.map(chunk, (_) => JSON.parse(_)),
194
+ catch: (cause) => new NdjsonError({ reason: "Unpack", cause })
195
+ }))
196
+ }
197
+
198
+ const decodeString = <IE, Done>() => {
199
+ const decoder = new TextDecoder()
200
+ const loop: Channel.Channel<
201
+ Chunk.Chunk<string>,
202
+ Chunk.Chunk<Uint8Array>,
203
+ IE,
204
+ IE,
205
+ Done,
206
+ Done,
207
+ never
208
+ > = Channel.readWithCause({
209
+ onInput: (input) =>
210
+ Channel.zipRight(
211
+ Channel.write(Chunk.map(input, (_) => decoder.decode(_))),
212
+ loop
213
+ ),
214
+ onFailure: Channel.failCause,
215
+ onDone: Channel.succeed
216
+ })
217
+ return loop
218
+ }
219
+
220
+ /**
221
+ * @since 1.0.0
222
+ * @category constructors
223
+ */
224
+ export const unpack = <IE = never, Done = unknown>(options?: NdjsonOptions): Channel.Channel<
225
+ Chunk.Chunk<unknown>,
226
+ Chunk.Chunk<Uint8Array>,
227
+ IE | NdjsonError,
228
+ IE,
229
+ Done,
230
+ Done
231
+ > => {
232
+ return Channel.pipeTo(decodeString(), unpackString(options))
233
+ }
234
+
235
+ /**
236
+ * @since 1.0.0
237
+ * @category constructors
238
+ */
239
+ export const unpackSchema = <A, I, R>(
240
+ schema: Schema.Schema<A, I, R>
241
+ ) =>
242
+ <IE = never, Done = unknown>(options?: NdjsonOptions): Channel.Channel<
243
+ Chunk.Chunk<A>,
244
+ Chunk.Chunk<Uint8Array>,
245
+ NdjsonError | ParseError | IE,
246
+ IE,
247
+ Done,
248
+ Done,
249
+ R
250
+ > => Channel.pipeTo(unpack(options), ChannelSchema.decodeUnknown(schema)())
251
+
252
+ /**
253
+ * @since 1.0.0
254
+ * @category constructors
255
+ */
256
+ export const unpackSchemaString = <A, I, R>(
257
+ schema: Schema.Schema<A, I, R>
258
+ ) =>
259
+ <IE = never, Done = unknown>(options?: NdjsonOptions): Channel.Channel<
260
+ Chunk.Chunk<A>,
261
+ Chunk.Chunk<string>,
262
+ NdjsonError | ParseError | IE,
263
+ IE,
264
+ Done,
265
+ Done,
266
+ R
267
+ > => Channel.pipeTo(unpackString(options), ChannelSchema.decodeUnknown(schema)())
268
+
269
+ /**
270
+ * @since 1.0.0
271
+ * @category combinators
272
+ */
273
+ export const duplex: {
274
+ /**
275
+ * @since 1.0.0
276
+ * @category combinators
277
+ */
278
+ (options?: NdjsonOptions): <R, IE, OE, OutDone, InDone>(
279
+ self: Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, OE, IE | NdjsonError, OutDone, InDone, R>
280
+ ) => Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R>
281
+ /**
282
+ * @since 1.0.0
283
+ * @category combinators
284
+ */
285
+ <R, IE, OE, OutDone, InDone>(
286
+ self: Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, OE, IE | NdjsonError, OutDone, InDone, R>,
287
+ options?: NdjsonOptions
288
+ ): Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R>
289
+ } = dual((args) => Channel.isChannel(args[0]), <R, IE, OE, OutDone, InDone>(
290
+ self: Channel.Channel<Chunk.Chunk<Uint8Array>, Chunk.Chunk<Uint8Array>, OE, IE | NdjsonError, OutDone, InDone, R>,
291
+ options?: NdjsonOptions
292
+ ): Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R> =>
293
+ Channel.pipeTo(
294
+ Channel.pipeTo(pack(), self),
295
+ unpack(options)
296
+ ))
297
+
298
+ /**
299
+ * @since 1.0.0
300
+ * @category combinators
301
+ */
302
+ export const duplexString: {
303
+ /**
304
+ * @since 1.0.0
305
+ * @category combinators
306
+ */
307
+ (options?: NdjsonOptions): <R, IE, OE, OutDone, InDone>(
308
+ self: Channel.Channel<Chunk.Chunk<string>, Chunk.Chunk<string>, OE, IE | NdjsonError, OutDone, InDone, R>
309
+ ) => Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R>
310
+ /**
311
+ * @since 1.0.0
312
+ * @category combinators
313
+ */
314
+ <R, IE, OE, OutDone, InDone>(
315
+ self: Channel.Channel<Chunk.Chunk<string>, Chunk.Chunk<string>, OE, IE | NdjsonError, OutDone, InDone, R>,
316
+ options?: NdjsonOptions
317
+ ): Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R>
318
+ } = dual((args) => Channel.isChannel(args[0]), <R, IE, OE, OutDone, InDone>(
319
+ self: Channel.Channel<Chunk.Chunk<string>, Chunk.Chunk<string>, OE, IE | NdjsonError, OutDone, InDone, R>,
320
+ options?: NdjsonOptions
321
+ ): Channel.Channel<Chunk.Chunk<unknown>, Chunk.Chunk<unknown>, NdjsonError | OE, IE, OutDone, InDone, R> =>
322
+ Channel.pipeTo(
323
+ Channel.pipeTo(packString(), self),
324
+ unpackString(options)
325
+ ))
326
+
327
+ /**
328
+ * @since 1.0.0
329
+ * @category combinators
330
+ */
331
+ export const duplexSchema: {
332
+ /**
333
+ * @since 1.0.0
334
+ * @category combinators
335
+ */
336
+ <IA, II, IR, OA, OI, OR>(
337
+ options: Partial<NdjsonOptions> & {
338
+ readonly inputSchema: Schema.Schema<IA, II, IR>
339
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
340
+ }
341
+ ): <R, InErr, OutErr, OutDone, InDone>(
342
+ self: Channel.Channel<
343
+ Chunk.Chunk<Uint8Array>,
344
+ Chunk.Chunk<Uint8Array>,
345
+ OutErr,
346
+ NdjsonError | ParseError | InErr,
347
+ OutDone,
348
+ InDone,
349
+ R
350
+ >
351
+ ) => Channel.Channel<
352
+ Chunk.Chunk<OA>,
353
+ Chunk.Chunk<IA>,
354
+ NdjsonError | ParseError | OutErr,
355
+ InErr,
356
+ OutDone,
357
+ InDone,
358
+ R | IR | OR
359
+ >
360
+ /**
361
+ * @since 1.0.0
362
+ * @category combinators
363
+ */
364
+ <R, InErr, OutErr, OutDone, InDone, IA, II, IR, OA, OI, OR>(
365
+ self: Channel.Channel<
366
+ Chunk.Chunk<Uint8Array>,
367
+ Chunk.Chunk<Uint8Array>,
368
+ OutErr,
369
+ NdjsonError | ParseError | InErr,
370
+ OutDone,
371
+ InDone,
372
+ R
373
+ >,
374
+ options: Partial<NdjsonOptions> & {
375
+ readonly inputSchema: Schema.Schema<IA, II, IR>
376
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
377
+ }
378
+ ): Channel.Channel<
379
+ Chunk.Chunk<OA>,
380
+ Chunk.Chunk<IA>,
381
+ NdjsonError | ParseError | OutErr,
382
+ InErr,
383
+ OutDone,
384
+ InDone,
385
+ R | IR | OR
386
+ >
387
+ } = dual(2, <R, InErr, OutErr, OutDone, InDone, IA, II, IR, OA, OI, OR>(
388
+ self: Channel.Channel<
389
+ Chunk.Chunk<Uint8Array>,
390
+ Chunk.Chunk<Uint8Array>,
391
+ OutErr,
392
+ NdjsonError | ParseError | InErr,
393
+ OutDone,
394
+ InDone,
395
+ R
396
+ >,
397
+ options: Partial<NdjsonOptions> & {
398
+ readonly inputSchema: Schema.Schema<IA, II, IR>
399
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
400
+ }
401
+ ): Channel.Channel<
402
+ Chunk.Chunk<OA>,
403
+ Chunk.Chunk<IA>,
404
+ NdjsonError | ParseError | OutErr,
405
+ InErr,
406
+ OutDone,
407
+ InDone,
408
+ R | IR | OR
409
+ > => ChannelSchema.duplexUnknown(duplex(self, options), options))
410
+
411
+ /**
412
+ * @since 1.0.0
413
+ * @category combinators
414
+ */
415
+ export const duplexSchemaString: {
416
+ /**
417
+ * @since 1.0.0
418
+ * @category combinators
419
+ */
420
+ <IA, II, IR, OA, OI, OR>(
421
+ options: Partial<NdjsonOptions> & {
422
+ readonly inputSchema: Schema.Schema<IA, II, IR>
423
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
424
+ }
425
+ ): <R, InErr, OutErr, OutDone, InDone>(
426
+ self: Channel.Channel<
427
+ Chunk.Chunk<string>,
428
+ Chunk.Chunk<string>,
429
+ OutErr,
430
+ NdjsonError | ParseError | InErr,
431
+ OutDone,
432
+ InDone,
433
+ R
434
+ >
435
+ ) => Channel.Channel<
436
+ Chunk.Chunk<OA>,
437
+ Chunk.Chunk<IA>,
438
+ NdjsonError | ParseError | OutErr,
439
+ InErr,
440
+ OutDone,
441
+ InDone,
442
+ R | IR | OR
443
+ >
444
+ /**
445
+ * @since 1.0.0
446
+ * @category combinators
447
+ */
448
+ <R, InErr, OutErr, OutDone, InDone, IA, II, IR, OA, OI, OR>(
449
+ self: Channel.Channel<
450
+ Chunk.Chunk<string>,
451
+ Chunk.Chunk<string>,
452
+ OutErr,
453
+ NdjsonError | ParseError | InErr,
454
+ OutDone,
455
+ InDone,
456
+ R
457
+ >,
458
+ options: Partial<NdjsonOptions> & {
459
+ readonly inputSchema: Schema.Schema<IA, II, IR>
460
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
461
+ }
462
+ ): Channel.Channel<
463
+ Chunk.Chunk<OA>,
464
+ Chunk.Chunk<IA>,
465
+ NdjsonError | ParseError | OutErr,
466
+ InErr,
467
+ OutDone,
468
+ InDone,
469
+ R | IR | OR
470
+ >
471
+ } = dual(2, <R, InErr, OutErr, OutDone, InDone, IA, II, IR, OA, OI, OR>(
472
+ self: Channel.Channel<
473
+ Chunk.Chunk<string>,
474
+ Chunk.Chunk<string>,
475
+ OutErr,
476
+ NdjsonError | ParseError | InErr,
477
+ OutDone,
478
+ InDone,
479
+ R
480
+ >,
481
+ options: Partial<NdjsonOptions> & {
482
+ readonly inputSchema: Schema.Schema<IA, II, IR>
483
+ readonly outputSchema: Schema.Schema<OA, OI, OR>
484
+ }
485
+ ): Channel.Channel<
486
+ Chunk.Chunk<OA>,
487
+ Chunk.Chunk<IA>,
488
+ NdjsonError | ParseError | OutErr,
489
+ InErr,
490
+ OutDone,
491
+ InDone,
492
+ R | IR | OR
493
+ > => ChannelSchema.duplexUnknown(duplexString(self, options), options))
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import * as Context from "effect/Context"
5
+ import * as Data from "effect/Data"
6
+ import type * as Effect from "effect/Effect"
7
+ import type * as Socket from "./Socket.js"
8
+
9
+ /**
10
+ * @since 1.0.0
11
+ * @category tags
12
+ */
13
+ export class SocketServer extends Context.Tag("@effect/platform/SocketServer")<
14
+ SocketServer,
15
+ {
16
+ readonly address: Address
17
+ readonly run: <R, E, _>(
18
+ handler: (socket: Socket.Socket) => Effect.Effect<_, E, R>
19
+ ) => Effect.Effect<never, SocketServerError, R>
20
+ }
21
+ >() {}
22
+
23
+ /**
24
+ * @since 1.0.0
25
+ * @category errors
26
+ */
27
+ export const ErrorTypeId: unique symbol = Symbol.for("@effect/platform/SocketServer/SocketServerError")
28
+
29
+ /**
30
+ * @since 1.0.0
31
+ * @category errors
32
+ */
33
+ export type ErrorTypeId = typeof ErrorTypeId
34
+
35
+ /**
36
+ * @since 1.0.0
37
+ * @category errors
38
+ */
39
+ export class SocketServerError extends Data.TaggedError("SocketServerError")<{
40
+ readonly reason: "Open" | "Unknown"
41
+ readonly cause: unknown
42
+ }> {
43
+ /**
44
+ * @since 1.0.0
45
+ */
46
+ readonly [ErrorTypeId]: ErrorTypeId = ErrorTypeId
47
+
48
+ /**
49
+ * @since 1.0.0
50
+ */
51
+ get message(): string {
52
+ return this.reason
53
+ }
54
+ }
55
+
56
+ /**
57
+ * @since 1.0.0
58
+ * @category models
59
+ */
60
+ export type Address = UnixAddress | TcpAddress
61
+
62
+ /**
63
+ * @since 1.0.0
64
+ * @category models
65
+ */
66
+ export interface TcpAddress {
67
+ readonly _tag: "TcpAddress"
68
+ readonly hostname: string
69
+ readonly port: number
70
+ }
71
+
72
+ /**
73
+ * @since 1.0.0
74
+ * @category models
75
+ */
76
+ export interface UnixAddress {
77
+ readonly _tag: "UnixAddress"
78
+ readonly path: string
79
+ }
@@ -17,8 +17,8 @@ export interface CollectorService {
17
17
  readonly unsafeAddAll: (_: Iterable<globalThis.Transferable>) => void
18
18
  readonly read: Effect.Effect<Array<globalThis.Transferable>>
19
19
  readonly unsafeRead: () => Array<globalThis.Transferable>
20
- readonly unsafeClear: () => void
21
- readonly clear: Effect.Effect<void>
20
+ readonly unsafeClear: () => Array<globalThis.Transferable>
21
+ readonly clear: Effect.Effect<Array<globalThis.Transferable>>
22
22
  }
23
23
 
24
24
  /**
@@ -35,15 +35,16 @@ export class Collector extends Context.Tag("@effect/platform/Transferable/Collec
35
35
  * @category constructors
36
36
  */
37
37
  export const unsafeMakeCollector = (): CollectorService => {
38
- const tranferables: Array<globalThis.Transferable> = []
38
+ let tranferables: Array<globalThis.Transferable> = []
39
39
  const unsafeAddAll = (transfers: Iterable<globalThis.Transferable>): void => {
40
- for (const transfer of transfers) {
41
- tranferables.push(transfer)
42
- }
40
+ // eslint-disable-next-line no-restricted-syntax
41
+ tranferables.push(...transfers)
43
42
  }
44
43
  const unsafeRead = (): Array<globalThis.Transferable> => tranferables
45
- const unsafeClear = (): void => {
46
- tranferables.length = 0
44
+ const unsafeClear = (): Array<globalThis.Transferable> => {
45
+ const prev = tranferables
46
+ tranferables = []
47
+ return prev
47
48
  }
48
49
  return Collector.of({
49
50
  unsafeAddAll,
package/src/Url.ts CHANGED
@@ -194,9 +194,9 @@ export const mutate: {
194
194
  })
195
195
 
196
196
  /** @internal */
197
- const immutableURLSetter = <P extends keyof URL>(property: P): {
198
- (value: URL[P]): (url: URL) => URL
199
- (url: URL, value: URL[P]): URL
197
+ const immutableURLSetter = <P extends keyof URL, A = never>(property: P): {
198
+ (value: URL[P] | A): (url: URL) => URL
199
+ (url: URL, value: URL[P] | A): URL
200
200
  } =>
201
201
  dual(2, (url: URL, value: URL[P]) =>
202
202
  mutate(url, (url) => {
@@ -354,14 +354,14 @@ export const setPort: {
354
354
  * @since 1.0.0
355
355
  * @category Setters
356
356
  */
357
- (port: string): (url: URL) => URL
357
+ (port: string | number): (url: URL) => URL
358
358
  /**
359
359
  * Updates the port of the URL.
360
360
  *
361
361
  * @since 1.0.0
362
362
  * @category Setters
363
363
  */
364
- (url: URL, port: string): URL
364
+ (url: URL, port: string | number): URL
365
365
  } = immutableURLSetter("port")
366
366
 
367
367
  /**
package/src/UrlParams.ts CHANGED
@@ -21,7 +21,7 @@ export interface UrlParams extends ReadonlyArray<readonly [string, string]> {}
21
21
  * @category models
22
22
  */
23
23
  export type Input =
24
- | Readonly<Record<string, Coercible | ReadonlyArray<Coercible>>>
24
+ | CoercibleRecord
25
25
  | Iterable<readonly [string, Coercible]>
26
26
  | URLSearchParams
27
27
 
@@ -31,13 +31,35 @@ export type Input =
31
31
  */
32
32
  export type Coercible = string | number | bigint | boolean | null | undefined
33
33
 
34
+ /**
35
+ * @since 1.0.0
36
+ * @category models
37
+ */
38
+ export interface CoercibleRecord {
39
+ readonly [key: string]: Coercible | ReadonlyArray<Coercible> | CoercibleRecord
40
+ }
41
+
34
42
  /**
35
43
  * @since 1.0.0
36
44
  * @category constructors
37
45
  */
38
46
  export const fromInput = (input: Input): UrlParams => {
47
+ const parsed = fromInputNested(input)
48
+ const out: Array<[string, string]> = []
49
+ for (let i = 0; i < parsed.length; i++) {
50
+ if (Array.isArray(parsed[i][0])) {
51
+ const [keys, value] = parsed[i] as [Array<string>, string]
52
+ out.push([`${keys[0]}[${keys.slice(1).join("][")}]`, value])
53
+ } else {
54
+ out.push(parsed[i] as [string, string])
55
+ }
56
+ }
57
+ return out
58
+ }
59
+
60
+ const fromInputNested = (input: Input): Array<[string | Array<string>, any]> => {
39
61
  const entries = Symbol.iterator in input ? Arr.fromIterable(input) : Object.entries(input)
40
- const out: Array<readonly [string, string]> = []
62
+ const out: Array<[string | Array<string>, string]> = []
41
63
  for (const [key, value] of entries) {
42
64
  if (Array.isArray(value)) {
43
65
  for (let i = 0; i < value.length; i++) {
@@ -45,6 +67,11 @@ export const fromInput = (input: Input): UrlParams => {
45
67
  out.push([key, String(value[i])])
46
68
  }
47
69
  }
70
+ } else if (typeof value === "object") {
71
+ const nested = fromInputNested(value as CoercibleRecord)
72
+ for (const [k, v] of nested) {
73
+ out.push([[key, ...(typeof k === "string" ? [k] : k)], v])
74
+ }
48
75
  } else if (value !== undefined) {
49
76
  out.push([key, String(value)])
50
77
  }