@livestore/common-cf 0.4.0-dev.5 โ†’ 0.4.0-dev.6

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.
@@ -15,7 +15,7 @@
15
15
  * @see {@link https://developers.cloudflare.com/durable-objects/best-practices/websockets/ Cloudflare WebSocket Best Practices}
16
16
  */
17
17
 
18
- import { notYetImplemented } from '@livestore/utils'
18
+ import { notYetImplemented, omitUndefineds } from '@livestore/utils'
19
19
  import {
20
20
  constVoid,
21
21
  Effect,
@@ -147,7 +147,7 @@ export const setupDurableObjectWebSocketRpc = ({
147
147
  const ProtocolLive = layerRpcServerWebsocket({
148
148
  ws,
149
149
  incomingQueue,
150
- onMessage,
150
+ ...omitUndefineds({ onMessage }),
151
151
  }).pipe(Layer.provide(RpcSerialization.layerJson))
152
152
 
153
153
  const ServerLive = rpcLayer.pipe(Layer.provide(ProtocolLive))
@@ -1,58 +1,69 @@
1
- import { Chunk, Effect, Layer, Option, RpcClient, RpcSerialization, Socket, Stream } from '@livestore/utils/effect'
2
- import { startWranglerDevServerPromise } from '@livestore/utils-dev/node'
1
+ import {
2
+ Chunk,
3
+ Effect,
4
+ FetchHttpClient,
5
+ Layer,
6
+ Option,
7
+ RpcClient,
8
+ RpcSerialization,
9
+ Socket,
10
+ Stream,
11
+ } from '@livestore/utils/effect'
12
+ import { PlatformNode } from '@livestore/utils/node'
13
+ import { WranglerDevServerService } from '@livestore/utils-dev/node'
3
14
  import { Vitest } from '@livestore/utils-dev/node-vitest'
4
- import { beforeAll, expect } from 'vitest'
15
+ import { expect } from 'vitest'
5
16
  import { TestRpcs } from './test-fixtures/rpc-schema.ts'
6
17
 
7
- let port: number
18
+ const testTimeout = 60_000
8
19
 
9
- beforeAll(async () => {
10
- const { port: wranglerPort } = await startWranglerDevServerPromise({
11
- cwd: `${import.meta.dirname}/test-fixtures`,
12
- })
13
- port = wranglerPort
20
+ const withWranglerTest = Vitest.makeWithTestCtx({
21
+ timeout: testTimeout,
22
+ makeLayer: () =>
23
+ WranglerDevServerService.Default({
24
+ cwd: `${import.meta.dirname}/test-fixtures`,
25
+ }).pipe(Layer.provide(PlatformNode.NodeContext.layer), Layer.provide(FetchHttpClient.layer)),
14
26
  })
15
27
 
16
28
  const ProtocolLive = Layer.suspend(() =>
17
- RpcClient.layerProtocolSocket().pipe(
18
- Layer.provide(Socket.layerWebSocket(`ws://localhost:${port}`)),
19
- Layer.provide(Socket.layerWebSocketConstructorGlobal),
20
- Layer.provide(RpcSerialization.layerJson),
21
- ),
29
+ Effect.gen(function* () {
30
+ const server = yield* WranglerDevServerService
31
+ return RpcClient.layerProtocolSocket().pipe(
32
+ Layer.provide(Socket.layerWebSocket(`ws://localhost:${server.port}`)),
33
+ Layer.provide(Socket.layerWebSocketConstructorGlobal),
34
+ Layer.provide(RpcSerialization.layerJson),
35
+ )
36
+ }).pipe(Layer.unwrapEffect),
22
37
  )
23
38
 
24
- Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
39
+ Vitest.describe('Durable Object WebSocket RPC', { timeout: testTimeout }, () => {
25
40
  // Direct HTTP RPC client tests
26
- Vitest.scopedLive(
27
- 'should call ping method',
28
- Effect.fn(function* () {
41
+ Vitest.scopedLive('should call ping method', (test) =>
42
+ Effect.gen(function* () {
29
43
  const client = yield* RpcClient.make(TestRpcs)
30
44
  const result = yield* client.Ping({ message: 'Hello HTTP RPC' })
31
45
  expect(result).toEqual({ response: 'Pong: Hello HTTP RPC' })
32
- }, Effect.provide(ProtocolLive)),
46
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
33
47
  )
34
48
 
35
- Vitest.scopedLive(
36
- 'should call echo method',
37
- Effect.fn(function* () {
49
+ Vitest.scopedLive('should call echo method', (test) =>
50
+ Effect.gen(function* () {
38
51
  const client = yield* RpcClient.make(TestRpcs)
39
52
  const result = yield* client.Echo({ text: 'Echo' })
40
53
  expect(result).toEqual({ echo: 'Echo: Echo' })
41
- }, Effect.provide(ProtocolLive)),
54
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
42
55
  )
43
56
 
44
- Vitest.scopedLive(
45
- 'should call add method',
46
- Effect.fn(function* () {
57
+ Vitest.scopedLive('should call add method', (test) =>
58
+ Effect.gen(function* () {
47
59
  const client = yield* RpcClient.make(TestRpcs)
48
60
  const result = yield* client.Add({ a: 15, b: 25 })
49
61
  expect(result).toEqual({ result: 40 })
50
- }, Effect.provide(ProtocolLive)),
62
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
51
63
  )
52
64
 
53
- Vitest.scopedLive(
54
- 'should handle RPC fail method',
55
- Effect.fn(function* () {
65
+ Vitest.scopedLive('should handle RPC fail method', (test) =>
66
+ Effect.gen(function* () {
56
67
  const client = yield* RpcClient.make(TestRpcs)
57
68
  const error = yield* client.Fail({ message: 'test http failure' }).pipe(Effect.exit)
58
69
  expect(error.toString()).toMatchInlineSnapshot(`
@@ -66,12 +77,11 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
66
77
  }
67
78
  }"
68
79
  `)
69
- }, Effect.provide(ProtocolLive)),
80
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
70
81
  )
71
82
 
72
- Vitest.scopedLive(
73
- 'should handle defect method',
74
- Effect.fn(function* () {
83
+ Vitest.scopedLive('should handle defect method', (test) =>
84
+ Effect.gen(function* () {
75
85
  const client = yield* RpcClient.make(TestRpcs)
76
86
  const error = yield* client.Defect({ message: 'test http defect' }).pipe(Effect.exit)
77
87
  expect(error.toString()).toMatchInlineSnapshot(`
@@ -85,12 +95,11 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
85
95
  }
86
96
  }"
87
97
  `)
88
- }, Effect.provide(ProtocolLive)),
98
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
89
99
  )
90
100
 
91
- Vitest.scopedLive(
92
- 'should handle streaming RPC via HTTP',
93
- Effect.fn(function* () {
101
+ Vitest.scopedLive('should handle streaming RPC via HTTP', (test) =>
102
+ Effect.gen(function* () {
94
103
  const client = yield* RpcClient.make(TestRpcs)
95
104
  const stream = client.Stream({}).pipe(
96
105
  Stream.take(4),
@@ -98,12 +107,11 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
98
107
  )
99
108
  const chunks = yield* Stream.runCollect(stream)
100
109
  expect(Chunk.toReadonlyArray(chunks)).toEqual([1, 4, 9, 16]) // squares of 1,2,3,4
101
- }, Effect.provide(ProtocolLive)),
110
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
102
111
  )
103
112
 
104
- Vitest.scopedLive(
105
- 'should handle streaming RPC with error via HTTP',
106
- Effect.fn(function* () {
113
+ Vitest.scopedLive('should handle streaming RPC with error via HTTP', (test) =>
114
+ Effect.gen(function* () {
107
115
  const client = yield* RpcClient.make(TestRpcs)
108
116
  const stream = client.StreamError({ count: 5, errorAfter: 4 })
109
117
  const error = yield* Stream.runCollect(stream).pipe(Effect.exit)
@@ -118,12 +126,11 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
118
126
  }
119
127
  }"
120
128
  `)
121
- }, Effect.provide(ProtocolLive)),
129
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
122
130
  )
123
131
 
124
- Vitest.scopedLive(
125
- 'should handle streaming RPC with defect via HTTP',
126
- Effect.fn(function* () {
132
+ Vitest.scopedLive('should handle streaming RPC with defect via HTTP', (test) =>
133
+ Effect.gen(function* () {
127
134
  const client = yield* RpcClient.make(TestRpcs)
128
135
  const stream = client.StreamDefect({ count: 4, defectAfter: 1 })
129
136
  const error = yield* Stream.runCollect(stream).pipe(Effect.exit)
@@ -138,24 +145,22 @@ Vitest.describe('Durable Object WebSocket RPC', { timeout: 5000 }, () => {
138
145
  }
139
146
  }"
140
147
  `)
141
- }, Effect.provide(ProtocolLive)),
148
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
142
149
  )
143
150
 
144
- Vitest.scopedLive(
145
- 'should handle stream interruption via HTTP',
146
- Effect.fn(function* () {
151
+ Vitest.scopedLive('should handle stream interruption via HTTP', (test) =>
152
+ Effect.gen(function* () {
147
153
  const client = yield* RpcClient.make(TestRpcs)
148
154
  const stream = client.StreamInterruptible({ delay: 50, interruptAfterCount: 3 }).pipe(Stream.take(3))
149
155
  const chunks = yield* Stream.runCollect(stream)
150
156
  expect(Chunk.toReadonlyArray(chunks)).toEqual([1, 2, 3])
151
- }, Effect.provide(ProtocolLive)),
157
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
152
158
  )
153
159
  })
154
160
 
155
161
  Vitest.describe('Hibernation Tests', { timeout: 25000 }, () => {
156
- Vitest.scopedLive(
157
- 'should maintain RPC functionality after hibernation',
158
- Effect.fn(function* () {
162
+ Vitest.scopedLive('should maintain RPC functionality after hibernation', (test) =>
163
+ Effect.gen(function* () {
159
164
  console.log('๐Ÿงช Testing RPC server persistence across hibernation...')
160
165
 
161
166
  // Step 1: Create client and test initial functionality
@@ -214,12 +219,11 @@ Vitest.describe('Hibernation Tests', { timeout: 25000 }, () => {
214
219
  console.log('โœ… Streaming after hibernation successful')
215
220
 
216
221
  console.log('๐ŸŽ‰ All RPC operations successful after hibernation!')
217
- }, Effect.provide(ProtocolLive)),
222
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
218
223
  )
219
224
 
220
- Vitest.scopedLive(
221
- 'should handle rapid operations after hibernation',
222
- Effect.fn(function* () {
225
+ Vitest.scopedLive('should handle rapid operations after hibernation', (test) =>
226
+ Effect.gen(function* () {
223
227
  console.log('๐Ÿงช Testing rapid operations after hibernation...')
224
228
 
225
229
  console.log('Step 1: Establishing initial connection...')
@@ -266,6 +270,6 @@ Vitest.describe('Hibernation Tests', { timeout: 25000 }, () => {
266
270
  results.map((r) => r.operation),
267
271
  )
268
272
  console.log('๐ŸŽ‰ Rapid operations work correctly after hibernation!')
269
- }, Effect.provide(ProtocolLive)),
273
+ }).pipe(Effect.provide(ProtocolLive), withWranglerTest(test)),
270
274
  )
271
275
  })