effect 4.0.0-beta.29 → 4.0.0-beta.30

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 (63) hide show
  1. package/dist/Effect.d.ts +18 -5
  2. package/dist/Effect.d.ts.map +1 -1
  3. package/dist/Effect.js +12 -5
  4. package/dist/Effect.js.map +1 -1
  5. package/dist/Option.d.ts +1 -1
  6. package/dist/Option.d.ts.map +1 -1
  7. package/dist/Option.js +1 -2
  8. package/dist/Option.js.map +1 -1
  9. package/dist/Result.d.ts +1 -1
  10. package/dist/Result.d.ts.map +1 -1
  11. package/dist/Result.js +1 -2
  12. package/dist/Result.js.map +1 -1
  13. package/dist/Schema.d.ts +7 -6
  14. package/dist/Schema.d.ts.map +1 -1
  15. package/dist/Schema.js.map +1 -1
  16. package/dist/ServiceMap.d.ts +1 -1
  17. package/dist/ServiceMap.d.ts.map +1 -1
  18. package/dist/ServiceMap.js.map +1 -1
  19. package/dist/Utils.d.ts +137 -65
  20. package/dist/Utils.d.ts.map +1 -1
  21. package/dist/Utils.js +38 -66
  22. package/dist/Utils.js.map +1 -1
  23. package/dist/index.d.ts +56 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +56 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal/effect.js +4 -4
  28. package/dist/internal/effect.js.map +1 -1
  29. package/dist/testing/TestSchema.d.ts +258 -24
  30. package/dist/testing/TestSchema.d.ts.map +1 -1
  31. package/dist/testing/TestSchema.js +296 -23
  32. package/dist/testing/TestSchema.js.map +1 -1
  33. package/dist/testing/index.d.ts +64 -1
  34. package/dist/testing/index.d.ts.map +1 -1
  35. package/dist/testing/index.js +64 -1
  36. package/dist/testing/index.js.map +1 -1
  37. package/dist/unstable/cli/Command.d.ts +3 -3
  38. package/dist/unstable/cli/Command.d.ts.map +1 -1
  39. package/dist/unstable/http/HttpClient.js +3 -0
  40. package/dist/unstable/http/HttpClient.js.map +1 -1
  41. package/dist/unstable/http/HttpClientResponse.d.ts +2 -1
  42. package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
  43. package/dist/unstable/http/HttpClientResponse.js +4 -0
  44. package/dist/unstable/http/HttpClientResponse.js.map +1 -1
  45. package/dist/unstable/http/HttpServerResponse.d.ts +1 -1
  46. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  47. package/dist/unstable/http/HttpServerResponse.js +4 -0
  48. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/Effect.ts +18 -5
  51. package/src/Option.ts +2 -4
  52. package/src/Result.ts +2 -4
  53. package/src/Schema.ts +13 -6
  54. package/src/ServiceMap.ts +2 -2
  55. package/src/Utils.ts +137 -111
  56. package/src/index.ts +56 -0
  57. package/src/internal/effect.ts +20 -4
  58. package/src/testing/TestSchema.ts +322 -25
  59. package/src/testing/index.ts +64 -1
  60. package/src/unstable/cli/Command.ts +3 -3
  61. package/src/unstable/http/HttpClient.ts +5 -1
  62. package/src/unstable/http/HttpClientResponse.ts +7 -2
  63. package/src/unstable/http/HttpServerResponse.ts +6 -2
@@ -1,5 +1,68 @@
1
1
  /**
2
- * Testing utilities for Schema validation and assertions.
2
+ * Testing utilities for asserting Schema decoding, encoding, make, and
3
+ * arbitrary-generation behavior. Used in unit tests to verify that schemas
4
+ * accept, reject, and round-trip values correctly.
5
+ *
6
+ * ## Mental model
7
+ *
8
+ * - **Asserts** – entry point: wraps a schema and exposes helpers grouped by
9
+ * operation (decoding, encoding, make, arbitrary, round-trip).
10
+ * - **Decoding** – returned by `asserts.decoding()`; has `succeed` / `fail`
11
+ * helpers that run the schema's decoder and compare the result.
12
+ * - **Encoding** – returned by `asserts.encoding()`; mirrors {@link Decoding}
13
+ * but exercises the encoder direction.
14
+ * - Every assertion is async (`Promise<void>`) because parsing may involve
15
+ * effectful schemas.
16
+ * - `succeed` with one argument asserts identity (output equals input);
17
+ * with two arguments asserts a specific expected output.
18
+ * - `fail` always takes the input and the expected error message string.
19
+ *
20
+ * ## Common tasks
21
+ *
22
+ * - Assert decoding succeeds / fails → `new Asserts(schema).decoding().succeed(…)` / `.fail(…)`
23
+ * - Assert encoding succeeds / fails → `new Asserts(schema).encoding().succeed(…)` / `.fail(…)`
24
+ * - Assert make succeeds / fails → `new Asserts(schema).make().succeed(…)` / `.fail(…)`
25
+ * - Verify round-trip (encode then decode) → `new Asserts(schema).verifyLosslessTransformation()`
26
+ * - Verify arbitrary generation → `new Asserts(schema).arbitrary().verifyGeneration()`
27
+ * - Compare AST of struct fields → `Asserts.ast.fields.equals(a, b)`
28
+ * - Provide a service dependency for decoding → `asserts.decoding().provide(key, impl)`
29
+ *
30
+ * ## Gotchas
31
+ *
32
+ * - `succeed` uses `assert.deepStrictEqual`, so reference equality is not
33
+ * required but structural equality is.
34
+ * - `fail` compares against the stringified `Issue`, not the `Issue` object
35
+ * itself. Pass the exact multiline string the issue produces.
36
+ * - `verifyLosslessTransformation` and `arbitrary().verifyGeneration` run
37
+ * property-based tests via FastCheck; default run count is 20 for
38
+ * `verifyGeneration`.
39
+ *
40
+ * ## Quickstart
41
+ *
42
+ * **Example** (Basic decoding and encoding assertions)
43
+ *
44
+ * ```ts
45
+ * import { Schema } from "effect"
46
+ * import { TestSchema } from "effect/testing"
47
+ *
48
+ * const schema = Schema.NumberFromString
49
+ * const asserts = new TestSchema.Asserts(schema)
50
+ *
51
+ * // decoding
52
+ * const decoding = asserts.decoding()
53
+ * await decoding.succeed("1", 1)
54
+ * await decoding.fail(null, "Expected string, got null")
55
+ *
56
+ * // encoding
57
+ * const encoding = asserts.encoding()
58
+ * await encoding.succeed(1, "1")
59
+ * ```
60
+ *
61
+ * ## See also
62
+ *
63
+ * - {@link Asserts}
64
+ * - {@link Decoding}
65
+ * - {@link Encoding}
3
66
  *
4
67
  * @since 4.0.0
5
68
  */
@@ -15,20 +78,63 @@ import type * as ServiceMap from "../ServiceMap.ts"
15
78
  import * as FastCheck from "../testing/FastCheck.ts"
16
79
 
17
80
  /**
18
- * The `Asserts` class provides a comprehensive testing framework for schema validation,
19
- * encoding/decoding operations, and property-based testing.
81
+ * Entry point for schema test assertions. Wraps a schema and exposes
82
+ * operation-specific helpers: {@link Decoding}, {@link Encoding}, make,
83
+ * arbitrary generation, and round-trip verification.
84
+ *
85
+ * When to use:
86
+ * - You are writing unit tests for a schema's decoding, encoding, or
87
+ * construction behavior.
88
+ * - You want property-based round-trip or generation checks.
89
+ *
90
+ * **Example** (Decoding and encoding a struct)
91
+ *
92
+ * ```ts
93
+ * import { Schema } from "effect"
94
+ * import { TestSchema } from "effect/testing"
95
+ *
96
+ * const schema = Schema.Struct({ name: Schema.String })
97
+ * const asserts = new TestSchema.Asserts(schema)
98
+ *
99
+ * // decoding
100
+ * await asserts.decoding().succeed({ name: "Alice" })
101
+ *
102
+ * // encoding
103
+ * await asserts.encoding().succeed({ name: "Alice" })
104
+ * ```
105
+ *
106
+ * @see {@link Decoding}
107
+ * @see {@link Encoding}
20
108
  *
21
109
  * @since 4.0.0
22
110
  */
23
111
  export class Asserts<S extends Schema.Top> {
112
+ /**
113
+ * Static helpers for comparing schema AST structures. Useful when you need
114
+ * to assert that two field or element definitions produce the same AST.
115
+ *
116
+ * - `ast.fields.equals(a, b)` – compares struct field ASTs via
117
+ * `assert.deepStrictEqual`.
118
+ * - `ast.elements.equals(a, b)` – compares tuple element ASTs via
119
+ * `assert.deepStrictEqual`.
120
+ *
121
+ * **Example** (Comparing struct fields)
122
+ *
123
+ * ```ts
124
+ * import { Schema } from "effect"
125
+ * import { TestSchema } from "effect/testing"
126
+ *
127
+ * const fieldsA = { name: Schema.String }
128
+ * const fieldsB = { name: Schema.String }
129
+ * TestSchema.Asserts.ast.fields.equals(fieldsA, fieldsB) // no error
130
+ * ```
131
+ */
24
132
  static ast = {
25
- /** Asserts that two struct field definitions are equal by comparing their AST representations. */
26
133
  fields: {
27
134
  equals: (a: Schema.Struct.Fields, b: Schema.Struct.Fields) => {
28
135
  assert.deepStrictEqual(Record.map(a, AST.getAST), Record.map(b, AST.getAST))
29
136
  }
30
137
  },
31
- /** Asserts that two tuple element definitions are equal by comparing their AST representations. */
32
138
  elements: {
33
139
  equals: (a: Schema.Tuple.Elements, b: Schema.Tuple.Elements) => {
34
140
  assert.deepStrictEqual(a.map(AST.getAST), b.map(AST.getAST))
@@ -41,7 +147,23 @@ export class Asserts<S extends Schema.Top> {
41
147
  this.schema = schema
42
148
  }
43
149
  /**
44
- * Provides make operation testing utilities.
150
+ * Returns an object with `succeed` and `fail` helpers for testing the
151
+ * schema's `make` operation.
152
+ *
153
+ * - `succeed(input)` – asserts make returns the input unchanged.
154
+ * - `succeed(input, expected)` – asserts make returns `expected`.
155
+ * - `fail(input, message)` – asserts make fails with `message`.
156
+ *
157
+ * **Example** (Testing make)
158
+ *
159
+ * ```ts
160
+ * import { Schema } from "effect"
161
+ * import { TestSchema } from "effect/testing"
162
+ *
163
+ * const schema = Schema.String
164
+ * const asserts = new TestSchema.Asserts(schema)
165
+ * await asserts.make().succeed("hello")
166
+ * ```
45
167
  */
46
168
  make(options?: Schema.MakeOptions) {
47
169
  const makeEffect = Parser.makeEffect(this.schema)
@@ -59,9 +181,6 @@ export class Asserts<S extends Schema.Top> {
59
181
  }
60
182
  return {
61
183
  succeed,
62
- /**
63
- * Asserts that make operation fails with the expected error message.
64
- */
65
184
  async fail(input: unknown, message: string) {
66
185
  const r = await Effect.runPromise(
67
186
  makeEffect(input, options).pipe(
@@ -74,7 +193,23 @@ export class Asserts<S extends Schema.Top> {
74
193
  }
75
194
  }
76
195
  /**
77
- * Verifies that encoding values produces the same type after decoding (round-trip).
196
+ * Runs a property-based test that encodes arbitrary values and then decodes
197
+ * them, asserting the decoded value equals the original. Useful for verifying
198
+ * that a codec is lossless (encode followed by decode is identity).
199
+ *
200
+ * - Uses FastCheck to generate arbitrary values matching the schema's Type.
201
+ * - Fails the test if any generated value does not round-trip.
202
+ * - Pass `options.params` to control FastCheck parameters (e.g. `numRuns`).
203
+ *
204
+ * **Example** (Round-trip verification)
205
+ *
206
+ * ```ts
207
+ * import { Schema } from "effect"
208
+ * import { TestSchema } from "effect/testing"
209
+ *
210
+ * const asserts = new TestSchema.Asserts(Schema.NumberFromString)
211
+ * await asserts.verifyLosslessTransformation()
212
+ * ```
78
213
  */
79
214
  verifyLosslessTransformation<S extends Schema.Codec<unknown, unknown>>(this: Asserts<S>, options?: {
80
215
  readonly params?: FastCheck.Parameters<[S["Type"]]>
@@ -97,7 +232,24 @@ export class Asserts<S extends Schema.Top> {
97
232
  )
98
233
  }
99
234
  /**
100
- * Provides decoding testing utilities.
235
+ * Returns a {@link Decoding} instance for this schema, providing `succeed`
236
+ * and `fail` helpers to test decoding behavior.
237
+ *
238
+ * - Pass `parseOptions` to control error reporting (e.g. `{ errors: "all" }`).
239
+ *
240
+ * **Example** (Decoding assertions)
241
+ *
242
+ * ```ts
243
+ * import { Schema } from "effect"
244
+ * import { TestSchema } from "effect/testing"
245
+ *
246
+ * const asserts = new TestSchema.Asserts(Schema.NumberFromString)
247
+ * const decoding = asserts.decoding()
248
+ * await decoding.succeed("42", 42)
249
+ * await decoding.fail(null, "Expected string, got null")
250
+ * ```
251
+ *
252
+ * @see {@link Decoding}
101
253
  */
102
254
  decoding(options?: {
103
255
  readonly parseOptions?: AST.ParseOptions | undefined
@@ -105,7 +257,23 @@ export class Asserts<S extends Schema.Top> {
105
257
  return new Decoding(this.schema, options)
106
258
  }
107
259
  /**
108
- * Provides encoding testing utilities.
260
+ * Returns an {@link Encoding} instance for this schema, providing `succeed`
261
+ * and `fail` helpers to test encoding behavior.
262
+ *
263
+ * - Pass `parseOptions` to control error reporting (e.g. `{ errors: "all" }`).
264
+ *
265
+ * **Example** (Encoding assertions)
266
+ *
267
+ * ```ts
268
+ * import { Schema } from "effect"
269
+ * import { TestSchema } from "effect/testing"
270
+ *
271
+ * const asserts = new TestSchema.Asserts(Schema.NumberFromString)
272
+ * const encoding = asserts.encoding()
273
+ * await encoding.succeed(42, "42")
274
+ * ```
275
+ *
276
+ * @see {@link Encoding}
109
277
  */
110
278
  encoding(options?: {
111
279
  readonly parseOptions?: AST.ParseOptions | undefined
@@ -113,15 +281,26 @@ export class Asserts<S extends Schema.Top> {
113
281
  return new Encoding(this.schema, options)
114
282
  }
115
283
  /**
116
- * Provides property-based testing utilities for schema validation.
284
+ * Returns an object with property-based testing helpers for the schema's
285
+ * arbitrary generator.
286
+ *
287
+ * - `verifyGeneration()` – generates arbitrary values and asserts each
288
+ * satisfies the schema's `is` predicate. Defaults to 20 runs.
289
+ * - Pass `options.params` to override FastCheck parameters.
290
+ *
291
+ * **Example** (Verifying arbitrary generation)
292
+ *
293
+ * ```ts
294
+ * import { Schema } from "effect"
295
+ * import { TestSchema } from "effect/testing"
296
+ *
297
+ * const asserts = new TestSchema.Asserts(Schema.String)
298
+ * asserts.arbitrary().verifyGeneration()
299
+ * ```
117
300
  */
118
301
  arbitrary<S extends Schema.Codec<unknown, unknown, never, unknown>>(this: Asserts<S>) {
119
302
  const schema = this.schema
120
303
  return {
121
- /**
122
- * Verifies that the schema generates valid arbitrary values that satisfy
123
- * the schema constraints.
124
- */
125
304
  verifyGeneration(options?: {
126
305
  readonly params?: FastCheck.Parameters<[S["Type"]]> | undefined
127
306
  }) {
@@ -135,6 +314,37 @@ export class Asserts<S extends Schema.Top> {
135
314
  }
136
315
 
137
316
  /**
317
+ * Decoding test helper. Wraps a schema and exposes `succeed` and `fail`
318
+ * methods that run the schema's decoder and compare the result.
319
+ *
320
+ * When to use:
321
+ * - You want to assert that specific inputs decode to expected values.
322
+ * - You want to assert that invalid inputs produce specific error messages.
323
+ * - You need to provide services required by the schema's decoding pipeline.
324
+ *
325
+ * Behavior:
326
+ * - All assertions are async and use `assert.deepStrictEqual` internally.
327
+ * - `succeed(input)` asserts the decoded output equals `input` (identity).
328
+ * - `succeed(input, expected)` asserts the decoded output equals `expected`.
329
+ * - `fail(input, message)` asserts decoding fails and the stringified issue
330
+ * equals `message`.
331
+ * - `provide(key, impl)` returns a new `Decoding` with the service injected
332
+ * into the decoding context.
333
+ *
334
+ * **Example** (Decoding with service provision)
335
+ *
336
+ * ```ts
337
+ * import { Schema } from "effect"
338
+ * import { TestSchema } from "effect/testing"
339
+ *
340
+ * const asserts = new TestSchema.Asserts(Schema.String)
341
+ * const decoding = asserts.decoding()
342
+ * await decoding.succeed("hello")
343
+ * ```
344
+ *
345
+ * @see {@link Asserts}
346
+ * @see {@link Encoding}
347
+ *
138
348
  * @since 4.0.0
139
349
  */
140
350
  export class Decoding<S extends Schema.Top> {
@@ -154,7 +364,19 @@ export class Decoding<S extends Schema.Top> {
154
364
  this.options = options
155
365
  }
156
366
  /**
157
- * Asserts that decoding succeeds with the expected value.
367
+ * Asserts that decoding `input` succeeds. With one argument, asserts the
368
+ * output equals the input. With two arguments, asserts the output equals
369
+ * `expected`.
370
+ *
371
+ * **Example** (Identity and transformed decoding)
372
+ *
373
+ * ```ts
374
+ * import { Schema } from "effect"
375
+ * import { TestSchema } from "effect/testing"
376
+ *
377
+ * const decoding = new TestSchema.Asserts(Schema.NumberFromString).decoding()
378
+ * await decoding.succeed("1", 1) // transformed
379
+ * ```
158
380
  */
159
381
  async succeed<S extends Schema.Decoder<unknown, never>>(
160
382
  this: Decoding<S>,
@@ -180,7 +402,18 @@ export class Decoding<S extends Schema.Top> {
180
402
  assert.deepStrictEqual(r, Result.succeed(expected))
181
403
  }
182
404
  /**
183
- * Asserts that decoding fails with the expected error message.
405
+ * Asserts that decoding `input` fails and the stringified issue equals
406
+ * `message`.
407
+ *
408
+ * **Example** (Asserting a decoding failure)
409
+ *
410
+ * ```ts
411
+ * import { Schema } from "effect"
412
+ * import { TestSchema } from "effect/testing"
413
+ *
414
+ * const decoding = new TestSchema.Asserts(Schema.String).decoding()
415
+ * await decoding.fail(42, "Expected string, got 42")
416
+ * ```
184
417
  */
185
418
  async fail<S extends Schema.Decoder<unknown, never>>(
186
419
  this: Decoding<S>,
@@ -196,8 +429,13 @@ export class Decoding<S extends Schema.Top> {
196
429
  assert.deepStrictEqual(r, Result.fail(message))
197
430
  }
198
431
  /**
199
- * Creates a new Decoding instance with the provided service available in the
200
- * decoding context.
432
+ * Returns a new {@link Decoding} instance with the given service injected
433
+ * into the decoding effect context. Use this when the schema's decoder
434
+ * requires a service dependency.
435
+ *
436
+ * - Does not mutate the current instance; returns a new one.
437
+ *
438
+ * @see {@link Encoding.provide}
201
439
  */
202
440
  provide<Id, Service>(
203
441
  service: ServiceMap.Key<Id, Service>,
@@ -211,6 +449,37 @@ export class Decoding<S extends Schema.Top> {
211
449
  }
212
450
 
213
451
  /**
452
+ * Encoding test helper. Mirrors {@link Decoding} but exercises the schema's
453
+ * encoder direction.
454
+ *
455
+ * When to use:
456
+ * - You want to assert that specific values encode to expected outputs.
457
+ * - You want to assert that invalid inputs produce specific error messages
458
+ * during encoding.
459
+ * - You need to provide services required by the schema's encoding pipeline.
460
+ *
461
+ * Behavior:
462
+ * - All assertions are async and use `assert.deepStrictEqual` internally.
463
+ * - `succeed(input)` asserts the encoded output equals `input` (identity).
464
+ * - `succeed(input, expected)` asserts the encoded output equals `expected`.
465
+ * - `fail(input, message)` asserts encoding fails and the stringified issue
466
+ * equals `message`.
467
+ * - `provide(key, impl)` returns a new `Encoding` with the service injected
468
+ * into the encoding context.
469
+ *
470
+ * **Example** (Encoding assertions)
471
+ *
472
+ * ```ts
473
+ * import { Schema } from "effect"
474
+ * import { TestSchema } from "effect/testing"
475
+ *
476
+ * const encoding = new TestSchema.Asserts(Schema.NumberFromString).encoding()
477
+ * await encoding.succeed(42, "42")
478
+ * ```
479
+ *
480
+ * @see {@link Asserts}
481
+ * @see {@link Decoding}
482
+ *
214
483
  * @since 4.0.0
215
484
  */
216
485
  class Encoding<S extends Schema.Top> {
@@ -230,7 +499,19 @@ class Encoding<S extends Schema.Top> {
230
499
  this.options = options
231
500
  }
232
501
  /**
233
- * Asserts that encoding succeeds with the expected value.
502
+ * Asserts that encoding `input` succeeds. With one argument, asserts the
503
+ * output equals the input. With two arguments, asserts the output equals
504
+ * `expected`.
505
+ *
506
+ * **Example** (Identity and transformed encoding)
507
+ *
508
+ * ```ts
509
+ * import { Schema } from "effect"
510
+ * import { TestSchema } from "effect/testing"
511
+ *
512
+ * const encoding = new TestSchema.Asserts(Schema.NumberFromString).encoding()
513
+ * await encoding.succeed(1, "1") // transformed
514
+ * ```
234
515
  */
235
516
  async succeed<S extends Schema.Encoder<unknown, never>>(
236
517
  this: Encoding<S>,
@@ -256,7 +537,18 @@ class Encoding<S extends Schema.Top> {
256
537
  assert.deepStrictEqual(r, Result.succeed(expected))
257
538
  }
258
539
  /**
259
- * Asserts that encoding fails with the expected error message.
540
+ * Asserts that encoding `input` fails and the stringified issue equals
541
+ * `message`.
542
+ *
543
+ * **Example** (Asserting an encoding failure)
544
+ *
545
+ * ```ts
546
+ * import { Schema } from "effect"
547
+ * import { TestSchema } from "effect/testing"
548
+ *
549
+ * const encoding = new TestSchema.Asserts(Schema.NumberFromString).encoding()
550
+ * await encoding.fail("not-a-number", "Expected number, got \"not-a-number\"")
551
+ * ```
260
552
  */
261
553
  async fail<S extends Schema.Encoder<unknown, never>>(
262
554
  this: Encoding<S>,
@@ -272,8 +564,13 @@ class Encoding<S extends Schema.Top> {
272
564
  assert.deepStrictEqual(r, Result.fail(message))
273
565
  }
274
566
  /**
275
- * Creates a new Encoding instance with the provided service available in the
276
- * encoding context.
567
+ * Returns a new {@link Encoding} instance with the given service injected
568
+ * into the encoding effect context. Use this when the schema's encoder
569
+ * requires a service dependency.
570
+ *
571
+ * - Does not mutate the current instance; returns a new one.
572
+ *
573
+ * @see {@link Decoding.provide}
277
574
  */
278
575
  provide<Id, Service>(
279
576
  service: ServiceMap.Key<Id, Service>,
@@ -28,7 +28,70 @@ export * as TestClock from "./TestClock.ts"
28
28
  export * as TestConsole from "./TestConsole.ts"
29
29
 
30
30
  /**
31
- * Testing utilities for Schema validation and assertions.
31
+ * Testing utilities for asserting Schema decoding, encoding, make, and
32
+ * arbitrary-generation behavior. Used in unit tests to verify that schemas
33
+ * accept, reject, and round-trip values correctly.
34
+ *
35
+ * ## Mental model
36
+ *
37
+ * - **Asserts** – entry point: wraps a schema and exposes helpers grouped by
38
+ * operation (decoding, encoding, make, arbitrary, round-trip).
39
+ * - **Decoding** – returned by `asserts.decoding()`; has `succeed` / `fail`
40
+ * helpers that run the schema's decoder and compare the result.
41
+ * - **Encoding** – returned by `asserts.encoding()`; mirrors {@link Decoding}
42
+ * but exercises the encoder direction.
43
+ * - Every assertion is async (`Promise<void>`) because parsing may involve
44
+ * effectful schemas.
45
+ * - `succeed` with one argument asserts identity (output equals input);
46
+ * with two arguments asserts a specific expected output.
47
+ * - `fail` always takes the input and the expected error message string.
48
+ *
49
+ * ## Common tasks
50
+ *
51
+ * - Assert decoding succeeds / fails → `new Asserts(schema).decoding().succeed(…)` / `.fail(…)`
52
+ * - Assert encoding succeeds / fails → `new Asserts(schema).encoding().succeed(…)` / `.fail(…)`
53
+ * - Assert make succeeds / fails → `new Asserts(schema).make().succeed(…)` / `.fail(…)`
54
+ * - Verify round-trip (encode then decode) → `new Asserts(schema).verifyLosslessTransformation()`
55
+ * - Verify arbitrary generation → `new Asserts(schema).arbitrary().verifyGeneration()`
56
+ * - Compare AST of struct fields → `Asserts.ast.fields.equals(a, b)`
57
+ * - Provide a service dependency for decoding → `asserts.decoding().provide(key, impl)`
58
+ *
59
+ * ## Gotchas
60
+ *
61
+ * - `succeed` uses `assert.deepStrictEqual`, so reference equality is not
62
+ * required but structural equality is.
63
+ * - `fail` compares against the stringified `Issue`, not the `Issue` object
64
+ * itself. Pass the exact multiline string the issue produces.
65
+ * - `verifyLosslessTransformation` and `arbitrary().verifyGeneration` run
66
+ * property-based tests via FastCheck; default run count is 20 for
67
+ * `verifyGeneration`.
68
+ *
69
+ * ## Quickstart
70
+ *
71
+ * **Example** (Basic decoding and encoding assertions)
72
+ *
73
+ * ```ts
74
+ * import { Schema } from "effect"
75
+ * import { TestSchema } from "effect/testing"
76
+ *
77
+ * const schema = Schema.NumberFromString
78
+ * const asserts = new TestSchema.Asserts(schema)
79
+ *
80
+ * // decoding
81
+ * const decoding = asserts.decoding()
82
+ * await decoding.succeed("1", 1)
83
+ * await decoding.fail(null, "Expected string, got null")
84
+ *
85
+ * // encoding
86
+ * const encoding = asserts.encoding()
87
+ * await encoding.succeed(1, "1")
88
+ * ```
89
+ *
90
+ * ## See also
91
+ *
92
+ * - {@link Asserts}
93
+ * - {@link Decoding}
94
+ * - {@link Encoding}
32
95
  *
33
96
  * @since 4.0.0
34
97
  */
@@ -1157,15 +1157,15 @@ export const withGlobalFlags: {
1157
1157
 
1158
1158
  // Type extractors for subcommand arrays - T[number] gives union of all elements
1159
1159
  type ExtractGlobalFlagContext<T extends ReadonlyArray<GlobalFlag.GlobalFlag<any>>> = T[number] extends infer F
1160
- ? F extends GlobalFlag.Setting<infer Id, any> ? GlobalFlag.Setting.Identifier<Id>
1160
+ ? F extends GlobalFlag.Setting<infer Id, infer _A> ? GlobalFlag.Setting.Identifier<Id>
1161
1161
  : never
1162
1162
  : never
1163
- type ExtractSubcommand<T> = T extends Command<any, any, any, any, any> ? T
1163
+ type ExtractSubcommand<T> = T extends Command<infer _Name, infer _Input, infer _CI, infer _E, infer _R> ? T
1164
1164
  : T extends Command.SubcommandGroup<infer Commands> ? Commands[number]
1165
1165
  : never
1166
1166
  type ExtractSubcommandErrors<T extends ReadonlyArray<Command.SubcommandEntry>> = Error<ExtractSubcommand<T[number]>>
1167
1167
  type ExtractSubcommandContext<T extends ReadonlyArray<Command.SubcommandEntry>> = ExtractSubcommand<T[number]> extends
1168
- Command<any, any, any, any, infer R> ? R : never
1168
+ Command<infer _Name, infer _Input, infer _CI, infer _E, infer _R> ? _R : never
1169
1169
 
1170
1170
  /**
1171
1171
  * Sets the description for a command.
@@ -1663,7 +1663,7 @@ const responseRegistry = (() => {
1663
1663
 
1664
1664
  const scopedRequests = new WeakMap<HttpClientRequest.HttpClientRequest, AbortController>()
1665
1665
 
1666
- class InterruptibleResponse implements HttpClientResponse.HttpClientResponse {
1666
+ class InterruptibleResponse implements HttpClientResponse.HttpClientResponse, Pipeable {
1667
1667
  readonly original: HttpClientResponse.HttpClientResponse
1668
1668
  readonly controller: AbortController
1669
1669
 
@@ -1750,6 +1750,10 @@ class InterruptibleResponse implements HttpClientResponse.HttpClientResponse {
1750
1750
  [Inspectable.NodeInspectSymbol]() {
1751
1751
  return this.original[Inspectable.NodeInspectSymbol]()
1752
1752
  }
1753
+
1754
+ pipe() {
1755
+ return pipeArguments(this, arguments)
1756
+ }
1753
1757
  }
1754
1758
 
1755
1759
  const isTransientError = (error: unknown) => Cause.isTimeoutError(error) || isTransientHttpError(error)
@@ -4,6 +4,7 @@
4
4
  import * as Effect from "../../Effect.ts"
5
5
  import { dual } from "../../Function.ts"
6
6
  import * as Inspectable from "../../Inspectable.ts"
7
+ import { type Pipeable, pipeArguments } from "../../Pipeable.ts"
7
8
  import * as Schema from "../../Schema.ts"
8
9
  import type { ParseOptions } from "../../SchemaAST.ts"
9
10
  import * as Stream from "../../Stream.ts"
@@ -43,7 +44,7 @@ export const TypeId = "~effect/http/HttpClientResponse"
43
44
  * @since 4.0.0
44
45
  * @category models
45
46
  */
46
- export interface HttpClientResponse extends HttpIncomingMessage.HttpIncomingMessage<Error.HttpClientError> {
47
+ export interface HttpClientResponse extends HttpIncomingMessage.HttpIncomingMessage<Error.HttpClientError>, Pipeable {
47
48
  readonly [TypeId]: typeof TypeId
48
49
  readonly request: HttpClientRequest.HttpClientRequest
49
50
  readonly status: number
@@ -227,7 +228,7 @@ export const filterStatusOk = (self: HttpClientResponse): Effect.Effect<HttpClie
227
228
  // internal
228
229
  // -----------------------------------------------------------------------------
229
230
 
230
- class WebHttpClientResponse extends Inspectable.Class implements HttpClientResponse {
231
+ class WebHttpClientResponse extends Inspectable.Class implements HttpClientResponse, Pipeable {
231
232
  readonly [HttpIncomingMessage.TypeId]: typeof HttpIncomingMessage.TypeId
232
233
  readonly [TypeId]: typeof TypeId
233
234
 
@@ -371,4 +372,8 @@ class WebHttpClientResponse extends Inspectable.Class implements HttpClientRespo
371
372
  })
372
373
  }).pipe(Effect.cached, Effect.runSync)
373
374
  }
375
+
376
+ pipe() {
377
+ return pipeArguments(this, arguments)
378
+ }
374
379
  }
@@ -7,7 +7,7 @@ import type * as FileSystem from "../../FileSystem.ts"
7
7
  import { dual } from "../../Function.ts"
8
8
  import * as Inspectable from "../../Inspectable.ts"
9
9
  import { PipeInspectableProto } from "../../internal/core.ts"
10
- import type { Pipeable } from "../../Pipeable.ts"
10
+ import { type Pipeable, pipeArguments } from "../../Pipeable.ts"
11
11
  import type { PlatformError } from "../../PlatformError.ts"
12
12
  import { hasProperty } from "../../Predicate.ts"
13
13
  import { redact } from "../../Redactable.ts"
@@ -924,7 +924,7 @@ export const toClientResponse = (
924
924
  response
925
925
  )
926
926
 
927
- class ServerHttpClientResponse extends Inspectable.Class implements HttpClientResponse.HttpClientResponse {
927
+ class ServerHttpClientResponse extends Inspectable.Class implements HttpClientResponse.HttpClientResponse, Pipeable {
928
928
  readonly [HttpIncomingMessage.TypeId]: typeof HttpIncomingMessage.TypeId
929
929
  readonly [HttpClientResponse.TypeId]: typeof HttpClientResponse.TypeId
930
930
 
@@ -1115,6 +1115,10 @@ class ServerHttpClientResponse extends Inspectable.Class implements HttpClientRe
1115
1115
  private getFormDataResponse(): Response {
1116
1116
  return this.formDataResponse ??= new Response((this.response.body as Body.FormData).formData)
1117
1117
  }
1118
+
1119
+ pipe() {
1120
+ return pipeArguments(this, arguments)
1121
+ }
1118
1122
  }
1119
1123
 
1120
1124
  const textDecoder = new TextDecoder()