effect-start 0.17.2 → 0.19.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 (80) hide show
  1. package/dist/Development.d.ts +7 -2
  2. package/dist/Development.js +12 -6
  3. package/dist/PlatformRuntime.d.ts +4 -0
  4. package/dist/PlatformRuntime.js +9 -0
  5. package/dist/Route.d.ts +6 -2
  6. package/dist/Route.js +22 -0
  7. package/dist/RouteHttp.d.ts +1 -1
  8. package/dist/RouteHttp.js +12 -19
  9. package/dist/RouteMount.d.ts +2 -1
  10. package/dist/Start.d.ts +1 -5
  11. package/dist/Start.js +1 -8
  12. package/dist/Unique.d.ts +50 -0
  13. package/dist/Unique.js +187 -0
  14. package/dist/bun/BunHttpServer.js +5 -6
  15. package/dist/bun/BunRoute.d.ts +1 -1
  16. package/dist/bun/BunRoute.js +2 -2
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/node/Effectify.d.ts +209 -0
  20. package/dist/node/Effectify.js +19 -0
  21. package/dist/node/FileSystem.d.ts +3 -5
  22. package/dist/node/FileSystem.js +42 -62
  23. package/dist/node/PlatformError.d.ts +46 -0
  24. package/dist/node/PlatformError.js +43 -0
  25. package/dist/testing/TestLogger.js +1 -1
  26. package/package.json +10 -5
  27. package/src/Development.ts +13 -18
  28. package/src/PlatformRuntime.ts +11 -0
  29. package/src/Route.ts +31 -2
  30. package/src/RouteHttp.ts +15 -31
  31. package/src/RouteMount.ts +1 -1
  32. package/src/Start.ts +1 -15
  33. package/src/Unique.ts +232 -0
  34. package/src/bun/BunHttpServer.ts +6 -9
  35. package/src/bun/BunRoute.ts +3 -3
  36. package/src/index.ts +1 -0
  37. package/src/node/Effectify.ts +262 -0
  38. package/src/node/FileSystem.ts +59 -97
  39. package/src/node/PlatformError.ts +102 -0
  40. package/src/testing/TestLogger.ts +1 -1
  41. package/dist/Random.d.ts +0 -5
  42. package/dist/Random.js +0 -49
  43. package/src/Commander.test.ts +0 -1639
  44. package/src/ContentNegotiation.test.ts +0 -603
  45. package/src/Development.test.ts +0 -119
  46. package/src/Entity.test.ts +0 -592
  47. package/src/FileRouterPattern.test.ts +0 -147
  48. package/src/FileRouter_files.test.ts +0 -64
  49. package/src/FileRouter_path.test.ts +0 -145
  50. package/src/FileRouter_tree.test.ts +0 -132
  51. package/src/Http.test.ts +0 -319
  52. package/src/HttpAppExtra.test.ts +0 -103
  53. package/src/HttpUtils.test.ts +0 -85
  54. package/src/PathPattern.test.ts +0 -648
  55. package/src/Random.ts +0 -59
  56. package/src/RouteBody.test.ts +0 -232
  57. package/src/RouteHook.test.ts +0 -40
  58. package/src/RouteHttp.test.ts +0 -2909
  59. package/src/RouteMount.test.ts +0 -481
  60. package/src/RouteSchema.test.ts +0 -427
  61. package/src/RouteSse.test.ts +0 -249
  62. package/src/RouteTree.test.ts +0 -494
  63. package/src/RouteTrie.test.ts +0 -322
  64. package/src/RouterPattern.test.ts +0 -676
  65. package/src/Values.test.ts +0 -263
  66. package/src/bun/BunBundle.test.ts +0 -268
  67. package/src/bun/BunBundle_imports.test.ts +0 -48
  68. package/src/bun/BunHttpServer.test.ts +0 -251
  69. package/src/bun/BunImportTrackerPlugin.test.ts +0 -77
  70. package/src/bun/BunRoute.test.ts +0 -162
  71. package/src/bundler/BundleHttp.test.ts +0 -132
  72. package/src/effect/HttpRouter.test.ts +0 -548
  73. package/src/experimental/EncryptedCookies.test.ts +0 -488
  74. package/src/hyper/HyperHtml.test.ts +0 -209
  75. package/src/hyper/HyperRoute.test.tsx +0 -197
  76. package/src/middlewares/BasicAuthMiddleware.test.ts +0 -84
  77. package/src/testing/TestHttpClient.test.ts +0 -83
  78. package/src/testing/TestLogger.test.ts +0 -51
  79. package/src/x/datastar/Datastar.test.ts +0 -266
  80. package/src/x/tailwind/TailwindPlugin.test.ts +0 -333
@@ -1,119 +0,0 @@
1
- import * as FileSystem from "@effect/platform/FileSystem"
2
- import * as test from "bun:test"
3
- import { MemoryFileSystem } from "effect-memfs"
4
- import * as Chunk from "effect/Chunk"
5
- import * as Effect from "effect/Effect"
6
- import * as Fiber from "effect/Fiber"
7
- import * as Layer from "effect/Layer"
8
- import * as Stream from "effect/Stream"
9
- import * as Development from "./Development.ts"
10
-
11
- test.beforeEach(() => {
12
- Development._resetForTesting()
13
- })
14
-
15
- test.describe("watch", () => {
16
- test.it("creates pubsub and publishes file events", () =>
17
- Effect
18
- .gen(function*() {
19
- const fs = yield* FileSystem.FileSystem
20
- const watchDir = "/dev-watch"
21
-
22
- const dev = yield* Development.watch({ path: watchDir })
23
-
24
- const subFiber = yield* Effect.fork(
25
- Stream.runCollect(
26
- Stream.take(Stream.fromPubSub(dev.events), 1),
27
- ),
28
- )
29
-
30
- yield* Effect.sleep(1)
31
- yield* fs.writeFileString(`${watchDir}/test.ts`, "const x = 1")
32
-
33
- const events = yield* Fiber.join(subFiber)
34
-
35
- test
36
- .expect(Chunk.size(events))
37
- .toBe(1)
38
- const first = Chunk.unsafeGet(events, 0)
39
- test
40
- .expect("path" in first && first.path)
41
- .toContain("test.ts")
42
- })
43
- .pipe(
44
- Effect.scoped,
45
- Effect.provide(
46
- MemoryFileSystem.layerWith({ "/dev-watch/.gitkeep": "" }),
47
- ),
48
- Effect.runPromise,
49
- ))
50
- })
51
-
52
- test.describe("layerWatch", () => {
53
- test.it("provides Development service", () =>
54
- Effect
55
- .gen(function*() {
56
- const dev = yield* Development.Development
57
-
58
- test
59
- .expect(dev.events)
60
- .toBeDefined()
61
- })
62
- .pipe(
63
- Effect.scoped,
64
- Effect.provide(Development.layerWatch({ path: "/layer-test" })),
65
- Effect.provide(
66
- MemoryFileSystem.layerWith({ "/layer-test/.gitkeep": "" }),
67
- ),
68
- Effect.runPromise,
69
- ))
70
- })
71
-
72
- test.describe("stream", () => {
73
- test.it("returns stream from pubsub when Development is available", () =>
74
- Effect
75
- .gen(function*() {
76
- const fs = yield* FileSystem.FileSystem
77
- const watchDir = "/events-test"
78
-
79
- const collectFiber = yield* Effect.fork(
80
- Stream.runCollect(Stream.take(Development.stream(), 1)),
81
- )
82
-
83
- yield* Effect.sleep(1)
84
- yield* fs.writeFileString(`${watchDir}/file.ts`, "content")
85
-
86
- const collected = yield* Fiber.join(collectFiber)
87
-
88
- test
89
- .expect(Chunk.size(collected))
90
- .toBe(1)
91
- const first = Chunk.unsafeGet(collected, 0)
92
- test
93
- .expect("path" in first && first.path)
94
- .toContain("file.ts")
95
- })
96
- .pipe(
97
- Effect.scoped,
98
- Effect.provide(Development.layerWatch({ path: "/events-test" })),
99
- Effect.provide(
100
- MemoryFileSystem.layerWith({ "/events-test/.gitkeep": "" }),
101
- ),
102
- Effect.runPromise,
103
- ))
104
-
105
- test.it("returns empty stream when Development is not available", () =>
106
- Effect
107
- .gen(function*() {
108
- const collected = yield* Stream.runCollect(Development.stream())
109
-
110
- test
111
- .expect(Chunk.size(collected))
112
- .toBe(0)
113
- })
114
- .pipe(
115
- Effect.scoped,
116
- Effect.provide(Layer.empty),
117
- Effect.runPromise,
118
- ))
119
- })
@@ -1,592 +0,0 @@
1
- import * as test from "bun:test"
2
- import * as Data from "effect/Data"
3
- import * as Effect from "effect/Effect"
4
- import * as ParseResult from "effect/ParseResult"
5
- import * as Schema from "effect/Schema"
6
- import * as Stream from "effect/Stream"
7
- import * as Entity from "./Entity.ts"
8
-
9
- test.describe(Entity.make, () => {
10
- test.it("creates entity with string body", () => {
11
- const entity = Entity.make("hello")
12
-
13
- test
14
- .expect(entity.body)
15
- .toBe("hello")
16
- test
17
- .expect(entity.headers)
18
- .toEqual({})
19
- test
20
- .expect(entity.url)
21
- .toBeUndefined()
22
- test
23
- .expect(entity.status)
24
- .toBeUndefined()
25
- })
26
-
27
- test.it("creates entity with all options", () => {
28
- const entity = Entity.make("hello", {
29
- headers: { "content-type": "text/plain" },
30
- url: "https://example.com",
31
- status: 200,
32
- })
33
-
34
- test
35
- .expect(entity.body)
36
- .toBe("hello")
37
- test
38
- .expect(entity.headers)
39
- .toEqual({ "content-type": "text/plain" })
40
- test
41
- .expect(entity.url)
42
- .toBe("https://example.com")
43
- test
44
- .expect(entity.status)
45
- .toBe(200)
46
- })
47
-
48
- test.it("creates entity with object body", () => {
49
- const data = { key: "value" }
50
- const entity = Entity.make(data)
51
-
52
- test
53
- .expect(entity.body)
54
- .toBe(data)
55
- })
56
-
57
- test.it("creates entity with Uint8Array body", () => {
58
- const bytes = new Uint8Array([1, 2, 3])
59
- const entity = Entity.make(bytes)
60
-
61
- test
62
- .expect(entity.body)
63
- .toBe(bytes)
64
- })
65
-
66
- test.it("creates entity with ArrayBuffer body", () => {
67
- const buffer = new ArrayBuffer(8)
68
- const entity = Entity.make(buffer)
69
-
70
- test
71
- .expect(entity.body)
72
- .toBe(buffer)
73
- })
74
-
75
- test.it("creates entity with Stream body", () => {
76
- const stream = Stream.make(new Uint8Array([1, 2, 3]))
77
- const entity = Entity.make(stream)
78
-
79
- test
80
- .expect(entity.body)
81
- .toBe(stream)
82
- })
83
- })
84
-
85
- test.describe(Entity.type, () => {
86
- test.it("returns content-type from headers if present", () => {
87
- const entity = Entity.make("hello", {
88
- headers: { "content-type": "application/xml" },
89
- })
90
-
91
- test
92
- .expect(Entity.type(entity))
93
- .toBe("application/xml")
94
- })
95
-
96
- test.it("infers text/plain for string body", () => {
97
- const entity = Entity.make("hello")
98
-
99
- test
100
- .expect(Entity.type(entity))
101
- .toBe("text/plain")
102
- })
103
-
104
- test.it("infers application/octet-stream for Uint8Array body", () => {
105
- const entity = Entity.make(new Uint8Array([1, 2, 3]))
106
-
107
- test
108
- .expect(Entity.type(entity))
109
- .toBe("application/octet-stream")
110
- })
111
-
112
- test.it("infers application/octet-stream for ArrayBuffer body", () => {
113
- const entity = Entity.make(new ArrayBuffer(8))
114
-
115
- test
116
- .expect(Entity.type(entity))
117
- .toBe("application/octet-stream")
118
- })
119
-
120
- test.it("infers application/json for object body", () => {
121
- const entity = Entity.make({ key: "value" })
122
-
123
- test
124
- .expect(Entity.type(entity))
125
- .toBe("application/json")
126
- })
127
-
128
- test.it("returns application/octet-stream for unknown body types", () => {
129
- const entity = Entity.make(null as any)
130
-
131
- test
132
- .expect(Entity.type(entity))
133
- .toBe("application/octet-stream")
134
- })
135
- })
136
-
137
- test.describe(Entity.length, () => {
138
- test.it("returns content-length from headers if present", () => {
139
- const entity = Entity.make("hello", {
140
- headers: { "content-length": "42" },
141
- })
142
-
143
- test
144
- .expect(Entity.length(entity))
145
- .toBe(42)
146
- })
147
-
148
- test.it("calculates length for string body", () => {
149
- const entity = Entity.make("hello")
150
-
151
- test
152
- .expect(Entity.length(entity))
153
- .toBe(5)
154
- })
155
-
156
- test.it("calculates length for multi-byte string", () => {
157
- const entity = Entity.make("héllo")
158
-
159
- test
160
- .expect(Entity.length(entity))
161
- .toBe(6)
162
- })
163
-
164
- test.it("returns byteLength for Uint8Array body", () => {
165
- const entity = Entity.make(new Uint8Array([1, 2, 3, 4, 5]))
166
-
167
- test
168
- .expect(Entity.length(entity))
169
- .toBe(5)
170
- })
171
-
172
- test.it("returns byteLength for ArrayBuffer body", () => {
173
- const entity = Entity.make(new ArrayBuffer(8))
174
-
175
- test
176
- .expect(Entity.length(entity))
177
- .toBe(8)
178
- })
179
-
180
- test.it("returns undefined for object body", () => {
181
- const entity = Entity.make({ a: 1 })
182
-
183
- test
184
- .expect(Entity.length(entity))
185
- .toBeUndefined()
186
- })
187
- })
188
-
189
- test.describe("text", () => {
190
- test.it("returns string body directly", async () => {
191
- const entity = Entity.make("hello world")
192
- const result = await Effect.runPromise(entity.text)
193
-
194
- test
195
- .expect(result)
196
- .toBe("hello world")
197
- })
198
-
199
- test.it("decodes Uint8Array body to string", async () => {
200
- const bytes = new TextEncoder().encode("hello world")
201
- const entity = Entity.make(bytes)
202
- const result = await Effect.runPromise(entity.text)
203
-
204
- test
205
- .expect(result)
206
- .toBe("hello world")
207
- })
208
-
209
- test.it("decodes ArrayBuffer body to string", async () => {
210
- const bytes = new TextEncoder().encode("hello world")
211
- const buffer = bytes.buffer.slice(
212
- bytes.byteOffset,
213
- bytes.byteOffset + bytes.byteLength,
214
- )
215
- const entity = Entity.make(buffer)
216
- const result = await Effect.runPromise(entity.text)
217
-
218
- test
219
- .expect(result)
220
- .toBe("hello world")
221
- })
222
-
223
- test.it("decodes Stream body to string", async () => {
224
- const bytes1 = new TextEncoder().encode("hello ")
225
- const bytes2 = new TextEncoder().encode("world")
226
- const stream = Stream.make(bytes1, bytes2)
227
- const entity = Entity.make(stream)
228
- const result = await Effect.runPromise(entity.text)
229
-
230
- test
231
- .expect(result)
232
- .toBe("hello world")
233
- })
234
-
235
- test.it("fails for unsupported body types", async () => {
236
- const entity = Entity.make(42 as any)
237
- const result = await Effect.runPromiseExit(entity.text)
238
-
239
- test
240
- .expect(result._tag)
241
- .toBe("Failure")
242
- })
243
- })
244
-
245
- test.describe("json", () => {
246
- test.it("returns object body directly", async () => {
247
- const data = { key: "value", num: 42 }
248
- const entity = Entity.make(data)
249
- const result = await Effect.runPromise(entity.json)
250
-
251
- test
252
- .expect(result)
253
- .toEqual(data)
254
- })
255
-
256
- test.it("parses string body as JSON", async () => {
257
- const entity = Entity.make("{\"key\":\"value\"}")
258
- const result = await Effect.runPromise(entity.json)
259
-
260
- test
261
- .expect(result)
262
- .toEqual({ key: "value" })
263
- })
264
-
265
- test.it("parses Uint8Array body as JSON", async () => {
266
- const bytes = new TextEncoder().encode("{\"key\":\"value\"}")
267
- const entity = Entity.make(bytes)
268
- const result = await Effect.runPromise(entity.json)
269
-
270
- test
271
- .expect(result)
272
- .toEqual({ key: "value" })
273
- })
274
-
275
- test.it("parses ArrayBuffer body as JSON", async () => {
276
- const bytes = new TextEncoder().encode("{\"key\":\"value\"}")
277
- const buffer = bytes.buffer.slice(
278
- bytes.byteOffset,
279
- bytes.byteOffset + bytes.byteLength,
280
- )
281
- const entity = Entity.make(buffer)
282
- const result = await Effect.runPromise(entity.json)
283
-
284
- test
285
- .expect(result)
286
- .toEqual({ key: "value" })
287
- })
288
-
289
- test.it("parses Stream body as JSON", async () => {
290
- const bytes = new TextEncoder().encode("{\"key\":\"value\"}")
291
- const stream = Stream.make(bytes)
292
- const entity = Entity.make(stream)
293
- const result = await Effect.runPromise(entity.json)
294
-
295
- test
296
- .expect(result)
297
- .toEqual({ key: "value" })
298
- })
299
-
300
- test.it("fails for invalid JSON string", async () => {
301
- const entity = Entity.make("not valid json")
302
- const result = await Effect.runPromiseExit(entity.json)
303
-
304
- test
305
- .expect(result._tag)
306
- .toBe("Failure")
307
- })
308
-
309
- test.it("fails for unsupported body types", async () => {
310
- const entity = Entity.make(42 as any)
311
- const result = await Effect.runPromiseExit(entity.json)
312
-
313
- test
314
- .expect(result._tag)
315
- .toBe("Failure")
316
- })
317
- })
318
-
319
- test.describe("bytes", () => {
320
- test.it("returns Uint8Array body directly", async () => {
321
- const bytes = new Uint8Array([1, 2, 3])
322
- const entity = Entity.make(bytes)
323
- const result = await Effect.runPromise(entity.bytes)
324
-
325
- test
326
- .expect(result)
327
- .toBe(bytes)
328
- })
329
-
330
- test.it("converts ArrayBuffer body to Uint8Array", async () => {
331
- const buffer = new ArrayBuffer(4)
332
- new Uint8Array(buffer).set([1, 2, 3, 4])
333
- const entity = Entity.make(buffer)
334
- const result = await Effect.runPromise(entity.bytes)
335
-
336
- test
337
- .expect(result)
338
- .toEqual(new Uint8Array([1, 2, 3, 4]))
339
- })
340
-
341
- test.it("encodes string body to Uint8Array", async () => {
342
- const entity = Entity.make("hello")
343
- const result = await Effect.runPromise(entity.bytes)
344
-
345
- test
346
- .expect(result)
347
- .toEqual(new TextEncoder().encode("hello"))
348
- })
349
-
350
- test.it("collects Stream body to Uint8Array", async () => {
351
- const chunk1 = new Uint8Array([1, 2])
352
- const chunk2 = new Uint8Array([3, 4])
353
- const stream = Stream.make(chunk1, chunk2)
354
- const entity = Entity.make(stream)
355
- const result = await Effect.runPromise(entity.bytes)
356
-
357
- test
358
- .expect(result)
359
- .toEqual(new Uint8Array([1, 2, 3, 4]))
360
- })
361
-
362
- test.it("serializes objects to JSON bytes", async () => {
363
- const entity = Entity.make({ key: "value" })
364
- const result = await Effect.runPromise(entity.bytes)
365
- const text = new TextDecoder().decode(result)
366
-
367
- test
368
- .expect(text)
369
- .toBe("{\"key\":\"value\"}")
370
- })
371
- })
372
-
373
- test.describe("stream", () => {
374
- test.it("returns Stream body content", async () => {
375
- const bytes = new Uint8Array([1, 2, 3])
376
- const entity = Entity.make(Stream.make(bytes))
377
- const chunks = await Effect.runPromise(Stream.runCollect(entity.stream))
378
-
379
- test
380
- .expect(Array.from(chunks))
381
- .toEqual([bytes])
382
- })
383
-
384
- test.it("converts Uint8Array body to stream", async () => {
385
- const bytes = new Uint8Array([1, 2, 3])
386
- const entity = Entity.make(bytes)
387
- const chunks = await Effect.runPromise(Stream.runCollect(entity.stream))
388
-
389
- test
390
- .expect(Array.from(chunks))
391
- .toEqual([bytes])
392
- })
393
-
394
- test.it("converts ArrayBuffer body to stream", async () => {
395
- const buffer = new ArrayBuffer(3)
396
- new Uint8Array(buffer).set([1, 2, 3])
397
- const entity = Entity.make(buffer)
398
- const chunks = await Effect.runPromise(Stream.runCollect(entity.stream))
399
-
400
- test
401
- .expect(Array.from(chunks))
402
- .toEqual([new Uint8Array([1, 2, 3])])
403
- })
404
-
405
- test.it("converts string body to stream", async () => {
406
- const entity = Entity.make("hello")
407
- const chunks = await Effect.runPromise(Stream.runCollect(entity.stream))
408
-
409
- test
410
- .expect(Array.from(chunks))
411
- .toEqual([new TextEncoder().encode("hello")])
412
- })
413
- })
414
-
415
- test.describe("Effect body", () => {
416
- test.it("executes lazily on accessor access", async () => {
417
- let count = 0
418
- const entity = Entity.make(
419
- Effect.sync(() => {
420
- count++
421
- return "hello"
422
- }),
423
- )
424
-
425
- test.expect(count).toBe(0)
426
-
427
- await Effect.runPromise(entity.text)
428
- test.expect(count).toBe(1)
429
- })
430
-
431
- test.it("propagates Effect errors", async () => {
432
- const error = new ParseResult.ParseError({
433
- issue: new ParseResult.Type(Schema.String.ast, 123),
434
- })
435
- const effect = Effect.fail(error)
436
- const entity = Entity.make(effect)
437
- const result = await Effect.runPromiseExit(entity.text)
438
-
439
- test
440
- .expect(result._tag)
441
- .toBe("Failure")
442
- })
443
-
444
- test.it("tracks error type in Entity accessors", () => {
445
- class CustomError extends Data.TaggedError("CustomError")<{
446
- readonly reason: string
447
- }> {}
448
-
449
- const entity = Entity.make(Effect.fail(new CustomError({ reason: "test" })))
450
-
451
- test
452
- .expectTypeOf<
453
- CustomError extends Effect.Effect.Error<typeof entity.text> ? true
454
- : false
455
- >()
456
- .toEqualTypeOf<true>()
457
- })
458
-
459
- test.it("text decodes Effect<Uint8Array> to string", async () => {
460
- const bytes = new TextEncoder().encode("hello world")
461
- const effect = Effect.succeed(bytes)
462
- const entity = Entity.make(effect)
463
- const result = await Effect.runPromise(entity.text)
464
-
465
- test
466
- .expect(result)
467
- .toBe("hello world")
468
- })
469
-
470
- test.it("json parses Effect<string> as JSON", async () => {
471
- const effect = Effect.succeed("{\"key\":\"value\"}")
472
- const entity = Entity.make(effect)
473
- const result = await Effect.runPromise(entity.json)
474
-
475
- test
476
- .expect(result)
477
- .toEqual({ key: "value" })
478
- })
479
-
480
- test.it("bytes encodes Effect<string> to Uint8Array", async () => {
481
- const effect = Effect.succeed("hello")
482
- const entity = Entity.make(effect)
483
- const result = await Effect.runPromise(entity.bytes)
484
-
485
- test
486
- .expect(result)
487
- .toEqual(new TextEncoder().encode("hello"))
488
- })
489
- })
490
-
491
- test.describe("Pipeable interface", () => {
492
- test.it("supports piping", () => {
493
- const entity = Entity.make("hello")
494
- const piped = entity.pipe((e) => Entity.type(e))
495
-
496
- test
497
- .expect(piped)
498
- .toBe("text/plain")
499
- })
500
- })
501
-
502
- test.describe("Proto getters", () => {
503
- test.it("entity.text returns text", async () => {
504
- const entity = Entity.make("hello")
505
- const result = await Effect.runPromise(entity.text)
506
-
507
- test
508
- .expect(result)
509
- .toBe("hello")
510
- })
511
-
512
- test.it("entity.json returns json", async () => {
513
- const data = { key: "value" }
514
- const entity = Entity.make(data)
515
- const result = await Effect.runPromise(entity.json)
516
-
517
- test
518
- .expect(result)
519
- .toEqual(data)
520
- })
521
-
522
- test.it("entity.bytes returns bytes", async () => {
523
- const bytes = new Uint8Array([1, 2, 3])
524
- const entity = Entity.make(bytes)
525
- const result = await Effect.runPromise(entity.bytes)
526
-
527
- test
528
- .expect(result)
529
- .toBe(bytes)
530
- })
531
-
532
- test.it("entity.stream returns stream", async () => {
533
- const bytes = new Uint8Array([1, 2, 3])
534
- const entity = Entity.make(bytes)
535
- const chunks = await Effect.runPromise(Stream.runCollect(entity.stream))
536
-
537
- test
538
- .expect(Array.from(chunks))
539
- .toEqual([bytes])
540
- })
541
- })
542
-
543
- test.describe("type inference", () => {
544
- test.it("infers correct body type from make()", () => {
545
- const stringEntity = Entity.make("hello")
546
- test
547
- .expectTypeOf(stringEntity.body)
548
- .toEqualTypeOf<string>()
549
-
550
- const objectEntity = Entity.make({ key: "value" })
551
- test
552
- .expectTypeOf(objectEntity.body)
553
- .toEqualTypeOf<{ key: string }>()
554
-
555
- const bytesEntity = Entity.make(new Uint8Array([1, 2, 3]))
556
- test
557
- .expect(bytesEntity.body instanceof Uint8Array)
558
- .toBe(true)
559
- })
560
-
561
- test.it("text returns string for string body", () => {
562
- const entity = Entity.make("hello")
563
-
564
- test
565
- .expectTypeOf<Effect.Effect.Success<typeof entity.text>>()
566
- .toEqualTypeOf<string>()
567
- })
568
-
569
- test.it("json returns T for object body", () => {
570
- const entity = Entity.make({ key: "value" })
571
-
572
- test
573
- .expectTypeOf<Effect.Effect.Success<typeof entity.json>>()
574
- .toEqualTypeOf<{ key: string }>()
575
- })
576
-
577
- test.it("bytes returns Uint8Array for string body", () => {
578
- const entity = Entity.make("hello")
579
-
580
- test
581
- .expectTypeOf<Effect.Effect.Success<typeof entity.bytes>>()
582
- .toEqualTypeOf<Uint8Array>()
583
- })
584
-
585
- test.it("stream returns Stream for string body", () => {
586
- const entity = Entity.make("hello")
587
-
588
- test
589
- .expectTypeOf<Stream.Stream.Success<typeof entity.stream>>()
590
- .toEqualTypeOf<Uint8Array>()
591
- })
592
- })