@livestore/sync-cf 0.3.0-dev.2 → 0.3.0-dev.22

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 (48) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/cf-worker/durable-object.d.ts +42 -37
  3. package/dist/cf-worker/durable-object.d.ts.map +1 -1
  4. package/dist/cf-worker/durable-object.js +224 -152
  5. package/dist/cf-worker/durable-object.js.map +1 -1
  6. package/dist/cf-worker/mod.d.ts +3 -0
  7. package/dist/cf-worker/mod.d.ts.map +1 -0
  8. package/dist/cf-worker/mod.js +3 -0
  9. package/dist/cf-worker/mod.js.map +1 -0
  10. package/dist/cf-worker/worker.d.ts +6 -0
  11. package/dist/cf-worker/worker.d.ts.map +1 -0
  12. package/dist/cf-worker/worker.js +29 -0
  13. package/dist/cf-worker/worker.js.map +1 -0
  14. package/dist/common/{index.js → mod.d.ts} +1 -1
  15. package/dist/common/mod.d.ts.map +1 -0
  16. package/dist/common/{index.d.ts → mod.js} +1 -1
  17. package/dist/common/mod.js.map +1 -0
  18. package/dist/common/ws-message-types.d.ts +58 -233
  19. package/dist/common/ws-message-types.d.ts.map +1 -1
  20. package/dist/common/ws-message-types.js +6 -11
  21. package/dist/common/ws-message-types.js.map +1 -1
  22. package/dist/sync-impl/mod.d.ts +2 -0
  23. package/dist/sync-impl/mod.d.ts.map +1 -0
  24. package/dist/sync-impl/mod.js +2 -0
  25. package/dist/sync-impl/mod.js.map +1 -0
  26. package/dist/sync-impl/ws-impl.d.ts +3 -12
  27. package/dist/sync-impl/ws-impl.d.ts.map +1 -1
  28. package/dist/sync-impl/ws-impl.js +73 -28
  29. package/dist/sync-impl/ws-impl.js.map +1 -1
  30. package/package.json +15 -13
  31. package/src/cf-worker/durable-object.ts +299 -172
  32. package/src/cf-worker/mod.ts +2 -0
  33. package/src/cf-worker/worker.ts +39 -0
  34. package/src/common/ws-message-types.ts +7 -22
  35. package/src/sync-impl/ws-impl.ts +85 -47
  36. package/dist/cf-worker/index.d.ts +0 -8
  37. package/dist/cf-worker/index.d.ts.map +0 -1
  38. package/dist/cf-worker/index.js +0 -67
  39. package/dist/cf-worker/index.js.map +0 -1
  40. package/dist/common/index.d.ts.map +0 -1
  41. package/dist/common/index.js.map +0 -1
  42. package/dist/sync-impl/index.d.ts +0 -2
  43. package/dist/sync-impl/index.d.ts.map +0 -1
  44. package/dist/sync-impl/index.js +0 -2
  45. package/dist/sync-impl/index.js.map +0 -1
  46. package/src/cf-worker/index.ts +0 -84
  47. /package/src/common/{index.ts → mod.ts} +0 -0
  48. /package/src/sync-impl/{index.ts → mod.ts} +0 -0
@@ -17,35 +17,27 @@ export const SyncMetadata = Schema.Struct({
17
17
  export type SyncMetadata = typeof SyncMetadata.Type
18
18
 
19
19
  export const PullRes = Schema.TaggedStruct('WSMessage.PullRes', {
20
- requestId: Schema.String,
21
- events: Schema.Array(
20
+ batch: Schema.Array(
22
21
  Schema.Struct({
23
- mutationEventEncoded: MutationEvent.EncodedAny,
22
+ mutationEventEncoded: MutationEvent.AnyEncodedGlobal,
24
23
  metadata: Schema.Option(SyncMetadata),
25
24
  }),
26
25
  ),
26
+ requestId: Schema.Struct({ context: Schema.Literal('pull', 'push'), requestId: Schema.String }),
27
27
  remaining: Schema.Number,
28
28
  })
29
29
 
30
30
  export type PullRes = typeof PullRes.Type
31
31
 
32
- export const PushBroadcast = Schema.TaggedStruct('WSMessage.PushBroadcast', {
33
- mutationEventEncoded: MutationEvent.EncodedAny,
34
- metadata: Schema.Option(SyncMetadata),
35
- })
36
-
37
- export type PushBroadcast = typeof PushBroadcast.Type
38
-
39
32
  export const PushReq = Schema.TaggedStruct('WSMessage.PushReq', {
40
33
  requestId: Schema.String,
41
- batch: Schema.Array(MutationEvent.EncodedAny),
34
+ batch: Schema.Array(MutationEvent.AnyEncodedGlobal),
42
35
  })
43
36
 
44
37
  export type PushReq = typeof PushReq.Type
45
38
 
46
39
  export const PushAck = Schema.TaggedStruct('WSMessage.PushAck', {
47
40
  requestId: Schema.String,
48
- mutationId: Schema.Number,
49
41
  })
50
42
 
51
43
  export type PushAck = typeof PushAck.Type
@@ -55,6 +47,8 @@ export const Error = Schema.TaggedStruct('WSMessage.Error', {
55
47
  message: Schema.String,
56
48
  })
57
49
 
50
+ export type Error = typeof Error.Type
51
+
58
52
  export const Ping = Schema.TaggedStruct('WSMessage.Ping', {
59
53
  requestId: Schema.Literal('ping'),
60
54
  })
@@ -99,7 +93,6 @@ export type AdminInfoRes = typeof AdminInfoRes.Type
99
93
  export const Message = Schema.Union(
100
94
  PullReq,
101
95
  PullRes,
102
- PushBroadcast,
103
96
  PushReq,
104
97
  PushAck,
105
98
  Error,
@@ -113,15 +106,7 @@ export const Message = Schema.Union(
113
106
  export type Message = typeof Message.Type
114
107
  export type MessageEncoded = typeof Message.Encoded
115
108
 
116
- export const BackendToClientMessage = Schema.Union(
117
- PullRes,
118
- PushBroadcast,
119
- PushAck,
120
- AdminResetRoomRes,
121
- AdminInfoRes,
122
- Error,
123
- Pong,
124
- )
109
+ export const BackendToClientMessage = Schema.Union(PullRes, PushAck, AdminResetRoomRes, AdminInfoRes, Error, Pong)
125
110
  export type BackendToClientMessage = typeof BackendToClientMessage.Type
126
111
 
127
112
  export const ClientToBackendMessage = Schema.Union(PullReq, PushReq, AdminResetRoomReq, AdminInfoReq, Ping)
@@ -1,8 +1,9 @@
1
1
  /// <reference lib="dom" />
2
2
 
3
- import type { SyncBackend, SyncBackendOptionsBase } from '@livestore/common'
3
+ import type { SyncBackend } from '@livestore/common'
4
4
  import { InvalidPullError, InvalidPushError } from '@livestore/common'
5
- import { pick } from '@livestore/utils'
5
+ import { EventId } from '@livestore/common/schema'
6
+ import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
6
7
  import type { Scope } from '@livestore/utils/effect'
7
8
  import {
8
9
  Deferred,
@@ -18,57 +19,92 @@ import {
18
19
  } from '@livestore/utils/effect'
19
20
  import { nanoid } from '@livestore/utils/nanoid'
20
21
 
21
- import { WSMessage } from '../common/index.js'
22
+ import { WSMessage } from '../common/mod.js'
22
23
  import type { SyncMetadata } from '../common/ws-message-types.js'
23
24
 
24
- export interface WsSyncOptions extends SyncBackendOptionsBase {
25
- type: 'cf'
25
+ export interface WsSyncOptions {
26
26
  url: string
27
- roomId: string
28
- }
29
-
30
- interface LiveStoreGlobalCf {
31
- syncBackend: WsSyncOptions
32
- }
33
-
34
- declare global {
35
- interface LiveStoreGlobal extends LiveStoreGlobalCf {}
27
+ storeId: string
36
28
  }
37
29
 
38
30
  export const makeWsSync = (options: WsSyncOptions): Effect.Effect<SyncBackend<SyncMetadata>, never, Scope.Scope> =>
39
31
  Effect.gen(function* () {
40
- const wsUrl = `${options.url}/websocket?room=${options.roomId}`
32
+ // TODO also allow for auth scenarios
33
+ const wsUrl = `${options.url}/websocket?storeId=${options.storeId}`
41
34
 
42
35
  const { isConnected, incomingMessages, send } = yield* connect(wsUrl)
43
36
 
37
+ /**
38
+ * We need to account for the scenario where push-caused PullRes message arrive before the pull-caused PullRes message.
39
+ * i.e. a scenario where the WS connection is created but before the server processed the initial pull, a push from
40
+ * another client triggers a PullRes message sent to this client which we need to stash until our pull-caused
41
+ * PullRes message arrives at which point we can combine the stashed events with the pull-caused events and continue.
42
+ */
43
+ const stashedPullBatch: WSMessage.PullRes['batch'][number][] = []
44
+
45
+ // We currently only support one pull stream for a sync backend.
46
+ let pullStarted = false
47
+
44
48
  const api = {
45
49
  isConnected,
46
50
  pull: (args) =>
47
51
  Effect.gen(function* () {
52
+ if (pullStarted) {
53
+ return shouldNeverHappen(`Pull already started for this sync backend.`)
54
+ }
55
+
56
+ pullStarted = true
57
+
58
+ let pullResponseReceived = false
59
+
48
60
  const requestId = nanoid()
49
61
  const cursor = Option.getOrUndefined(args)?.cursor.global
50
62
 
51
63
  yield* send(WSMessage.PullReq.make({ cursor, requestId }))
52
64
 
53
65
  return Stream.fromPubSub(incomingMessages).pipe(
54
- Stream.filter((_) => (_._tag === 'WSMessage.PullRes' ? _.requestId === requestId : true)),
55
66
  Stream.tap((_) =>
56
67
  _._tag === 'WSMessage.Error' && _.requestId === requestId
57
68
  ? new InvalidPullError({ message: _.message })
58
69
  : Effect.void,
59
70
  ),
60
- Stream.filter(Schema.is(Schema.Union(WSMessage.PushBroadcast, WSMessage.PullRes))),
61
- Stream.map((msg) =>
62
- msg._tag === 'WSMessage.PushBroadcast'
63
- ? { batch: [pick(msg, ['mutationEventEncoded', 'metadata'])], remaining: 0 }
64
- : {
65
- batch: msg.events.map(({ mutationEventEncoded, metadata }) => ({
66
- mutationEventEncoded,
67
- metadata,
68
- })),
69
- remaining: msg.remaining,
70
- },
71
- ),
71
+ Stream.filterMap((msg) => {
72
+ if (msg._tag === 'WSMessage.PullRes') {
73
+ if (msg.requestId.context === 'pull') {
74
+ if (msg.requestId.requestId === requestId) {
75
+ pullResponseReceived = true
76
+
77
+ if (stashedPullBatch.length > 0 && msg.remaining === 0) {
78
+ const pullResHead = msg.batch.at(-1)?.mutationEventEncoded.id ?? EventId.ROOT.global
79
+ // Index where stashed events are greater than pullResHead
80
+ const newPartialBatchIndex = stashedPullBatch.findIndex(
81
+ (batchItem) => batchItem.mutationEventEncoded.id > pullResHead,
82
+ )
83
+ const batchWithNewStashedEvents =
84
+ newPartialBatchIndex === -1 ? [] : stashedPullBatch.slice(newPartialBatchIndex)
85
+ const combinedBatch = [...msg.batch, ...batchWithNewStashedEvents]
86
+ return Option.some({ ...msg, batch: combinedBatch, remaining: 0 })
87
+ } else {
88
+ return Option.some(msg)
89
+ }
90
+ } else {
91
+ // Ignore
92
+ return Option.none()
93
+ }
94
+ } else {
95
+ if (pullResponseReceived) {
96
+ return Option.some(msg)
97
+ } else {
98
+ stashedPullBatch.push(...msg.batch)
99
+ return Option.none()
100
+ }
101
+ }
102
+ }
103
+
104
+ return Option.none()
105
+ }),
106
+ // This call is mostly here to for type narrowing
107
+ Stream.filter(Schema.is(WSMessage.PullRes)),
72
108
  )
73
109
  }).pipe(Stream.unwrap),
74
110
 
@@ -78,15 +114,12 @@ export const makeWsSync = (options: WsSyncOptions): Effect.Effect<SyncBackend<Sy
78
114
  const requestId = nanoid()
79
115
 
80
116
  yield* Stream.fromPubSub(incomingMessages).pipe(
81
- Stream.filter((_) => _._tag !== 'WSMessage.PushBroadcast' && _.requestId === requestId),
82
117
  Stream.tap((_) =>
83
- _._tag === 'WSMessage.Error'
118
+ _._tag === 'WSMessage.Error' && _.requestId === requestId
84
119
  ? Deferred.fail(ready, new InvalidPushError({ reason: { _tag: 'Unexpected', message: _.message } }))
85
120
  : Effect.void,
86
121
  ),
87
- Stream.filter(Schema.is(WSMessage.PushAck)),
88
- // TODO bring back filterting of "own events"
89
- // Stream.filter((_) => _.mutationId === mutationEventEncoded.id.global),
122
+ Stream.filter((_) => _._tag === 'WSMessage.PushAck' && _.requestId === requestId),
90
123
  Stream.take(1),
91
124
  Stream.tap(() => Deferred.succeed(ready, void 0)),
92
125
  Stream.runDrain,
@@ -123,21 +156,23 @@ const connect = (wsUrl: string) =>
123
156
  // Wait first until we're online
124
157
  yield* waitUntilOnline
125
158
 
126
- yield* Effect.spanEvent(
127
- `Sending message: ${message._tag}`,
128
- message._tag === 'WSMessage.PushReq'
129
- ? {
130
- id: message.batch[0]!.id.global,
131
- parentId: message.batch[0]!.parentId.global,
132
- batchLength: message.batch.length,
133
- }
134
- : message._tag === 'WSMessage.PullReq'
135
- ? { cursor: message.cursor ?? '-' }
136
- : {},
137
- )
138
-
139
159
  // TODO use MsgPack instead of JSON to speed up the serialization / reduce the size of the messages
140
160
  socketRef.current!.send(Schema.encodeSync(Schema.parseJson(WSMessage.Message))(message))
161
+
162
+ if (LS_DEV) {
163
+ yield* Effect.spanEvent(
164
+ `Sent message: ${message._tag}`,
165
+ message._tag === 'WSMessage.PushReq'
166
+ ? {
167
+ id: message.batch[0]!.id,
168
+ parentId: message.batch[0]!.parentId,
169
+ batchLength: message.batch.length,
170
+ }
171
+ : message._tag === 'WSMessage.PullReq'
172
+ ? { cursor: message.cursor ?? '-' }
173
+ : {},
174
+ )
175
+ }
141
176
  })
142
177
 
143
178
  const innerConnect = Effect.gen(function* () {
@@ -146,11 +181,13 @@ const connect = (wsUrl: string) =>
146
181
  while (typeof navigator !== 'undefined' && navigator.onLine === false) {
147
182
  yield* Effect.sleep(1000)
148
183
  }
184
+ // TODO bring this back in a cross-platform way
149
185
  // if (navigator.onLine === false) {
150
186
  // yield* Effect.async((cb) => self.addEventListener('online', () => cb(Effect.void)))
151
187
  // }
152
188
 
153
189
  const socket = yield* WebSocket.makeWebSocket({ url: wsUrl, reconnect: Schedule.exponential(100) })
190
+ // socket.binaryType = 'arraybuffer'
154
191
 
155
192
  yield* SubscriptionRef.set(isConnected, true)
156
193
  socketRef.current = socket
@@ -191,7 +228,8 @@ const connect = (wsUrl: string) =>
191
228
  // NOTE it seems that this callback doesn't work reliably on a worker but only via `window.addEventListener`
192
229
  // We might need to proxy the event from the main thread to the worker if we want this to work reliably.
193
230
  // eslint-disable-next-line unicorn/prefer-global-this
194
- if (typeof self !== 'undefined') {
231
+ if (typeof self !== 'undefined' && typeof self.addEventListener === 'function') {
232
+ // TODO support an Expo equivalent for this
195
233
  // eslint-disable-next-line unicorn/prefer-global-this
196
234
  yield* Effect.eventListener(self, 'offline', () => Deferred.succeed(connectionClosed, void 0))
197
235
  }
@@ -1,8 +0,0 @@
1
- /// <reference no-default-lib="true"/>
2
- import type { Env } from './durable-object.js';
3
- export * from './durable-object.js';
4
- declare const _default: {
5
- fetch: (request: Request, env: Env, _ctx: ExecutionContext) => Promise<Response>;
6
- };
7
- export default _default;
8
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":";AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AAE9C,cAAc,qBAAqB,CAAA;;qBA4CV,OAAO,OAAO,GAAG,QAAQ,gBAAgB,KAAG,OAAO,CAAC,QAAQ,CAAC;;AADtF,wBAgCC"}
@@ -1,67 +0,0 @@
1
- /// <reference no-default-lib="true"/>
2
- /// <reference lib="esnext" />
3
- export * from './durable-object.js';
4
- // const handleRequest = (request: Request, env: Env) =>
5
- // HttpServer.router.empty.pipe(
6
- // HttpServer.router.get(
7
- // '/websocket',
8
- // Effect.gen(function* () {
9
- // // This example will refer to the same Durable Object instance,
10
- // // since the name "foo" is hardcoded.
11
- // const id = env.WEBSOCKET_SERVER.idFromName('foo')
12
- // const durableObject = env.WEBSOCKET_SERVER.get(id)
13
- // HttpServer.
14
- // // Expect to receive a WebSocket Upgrade request.
15
- // // If there is one, accept the request and return a WebSocket Response.
16
- // const headerRes = yield* HttpServer.request
17
- // .schemaHeaders(
18
- // Schema.Struct({
19
- // Upgrade: Schema.Literal('websocket'),
20
- // }),
21
- // )
22
- // .pipe(Effect.either)
23
- // if (headerRes._tag === 'Left') {
24
- // // return new Response('Durable Object expected Upgrade: websocket', { status: 426 })
25
- // return yield* HttpServer.response.text('Durable Object expected Upgrade: websocket', { status: 426 })
26
- // }
27
- // HttpServer.response.empty
28
- // return yield* Effect.promise(() => durableObject.fetch(request))
29
- // }),
30
- // ),
31
- // HttpServer.router.catchAll((e) => {
32
- // console.log(e)
33
- // return HttpServer.response.empty({ status: 400 })
34
- // }),
35
- // (_) => HttpServer.app.toWebHandler(_)(request),
36
- // // request
37
- // )
38
- // Worker
39
- export default {
40
- fetch: async (request, env, _ctx) => {
41
- const url = new URL(request.url);
42
- const searchParams = url.searchParams;
43
- const roomId = searchParams.get('room');
44
- if (roomId === null) {
45
- return new Response('Room ID is required', { status: 400 });
46
- }
47
- // This example will refer to the same Durable Object instance,
48
- // since the name "foo" is hardcoded.
49
- const id = env.WEBSOCKET_SERVER.idFromName(roomId);
50
- const durableObject = env.WEBSOCKET_SERVER.get(id);
51
- if (url.pathname.endsWith('/websocket')) {
52
- const upgradeHeader = request.headers.get('Upgrade');
53
- if (!upgradeHeader || upgradeHeader !== 'websocket') {
54
- return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
55
- }
56
- return durableObject.fetch(request);
57
- }
58
- return new Response(null, {
59
- status: 400,
60
- statusText: 'Bad Request',
61
- headers: {
62
- 'Content-Type': 'text/plain',
63
- },
64
- });
65
- },
66
- };
67
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,8BAA8B;AAO9B,cAAc,qBAAqB,CAAA;AAEnC,wDAAwD;AACxD,kCAAkC;AAClC,6BAA6B;AAC7B,sBAAsB;AACtB,kCAAkC;AAClC,0EAA0E;AAC1E,gDAAgD;AAChD,4DAA4D;AAC5D,6DAA6D;AAE7D,sBAAsB;AAEtB,4DAA4D;AAC5D,kFAAkF;AAClF,sDAAsD;AACtD,4BAA4B;AAC5B,8BAA8B;AAC9B,sDAAsD;AACtD,kBAAkB;AAClB,cAAc;AACd,iCAAiC;AAEjC,2CAA2C;AAC3C,kGAAkG;AAClG,kHAAkH;AAClH,YAAY;AAEZ,oCAAoC;AAEpC,2EAA2E;AAC3E,YAAY;AACZ,SAAS;AACT,0CAA0C;AAC1C,uBAAuB;AACvB,0DAA0D;AAC1D,UAAU;AACV,sDAAsD;AACtD,iBAAiB;AACjB,MAAM;AAEN,SAAS;AACT,eAAe;IACb,KAAK,EAAE,KAAK,EAAE,OAAgB,EAAE,GAAQ,EAAE,IAAsB,EAAqB,EAAE;QACrF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAA;QACrC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAEvC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,QAAQ,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC7D,CAAC;QAED,+DAA+D;QAC/D,qCAAqC;QACrC,MAAM,EAAE,GAAG,GAAG,CAAC,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAClD,MAAM,aAAa,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAElD,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACpD,IAAI,CAAC,aAAa,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;gBACpD,OAAO,IAAI,QAAQ,CAAC,4CAA4C,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YACpF,CAAC;YAED,OAAO,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;YACxB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,aAAa;YACzB,OAAO,EAAE;gBACP,cAAc,EAAE,YAAY;aAC7B;SACF,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA"}
@@ -1,2 +0,0 @@
1
- export * from './ws-impl.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync-impl/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA"}
@@ -1,2 +0,0 @@
1
- export * from './ws-impl.js';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync-impl/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA"}
@@ -1,84 +0,0 @@
1
- /// <reference no-default-lib="true"/>
2
- /// <reference lib="esnext" />
3
-
4
- // import { EncodedAny } from '@livestore/common/schema'
5
- // import { Effect, HttpServer, Schema } from '@livestore/utils/effect'
6
-
7
- import type { Env } from './durable-object.js'
8
-
9
- export * from './durable-object.js'
10
-
11
- // const handleRequest = (request: Request, env: Env) =>
12
- // HttpServer.router.empty.pipe(
13
- // HttpServer.router.get(
14
- // '/websocket',
15
- // Effect.gen(function* () {
16
- // // This example will refer to the same Durable Object instance,
17
- // // since the name "foo" is hardcoded.
18
- // const id = env.WEBSOCKET_SERVER.idFromName('foo')
19
- // const durableObject = env.WEBSOCKET_SERVER.get(id)
20
-
21
- // HttpServer.
22
-
23
- // // Expect to receive a WebSocket Upgrade request.
24
- // // If there is one, accept the request and return a WebSocket Response.
25
- // const headerRes = yield* HttpServer.request
26
- // .schemaHeaders(
27
- // Schema.Struct({
28
- // Upgrade: Schema.Literal('websocket'),
29
- // }),
30
- // )
31
- // .pipe(Effect.either)
32
-
33
- // if (headerRes._tag === 'Left') {
34
- // // return new Response('Durable Object expected Upgrade: websocket', { status: 426 })
35
- // return yield* HttpServer.response.text('Durable Object expected Upgrade: websocket', { status: 426 })
36
- // }
37
-
38
- // HttpServer.response.empty
39
-
40
- // return yield* Effect.promise(() => durableObject.fetch(request))
41
- // }),
42
- // ),
43
- // HttpServer.router.catchAll((e) => {
44
- // console.log(e)
45
- // return HttpServer.response.empty({ status: 400 })
46
- // }),
47
- // (_) => HttpServer.app.toWebHandler(_)(request),
48
- // // request
49
- // )
50
-
51
- // Worker
52
- export default {
53
- fetch: async (request: Request, env: Env, _ctx: ExecutionContext): Promise<Response> => {
54
- const url = new URL(request.url)
55
- const searchParams = url.searchParams
56
- const roomId = searchParams.get('room')
57
-
58
- if (roomId === null) {
59
- return new Response('Room ID is required', { status: 400 })
60
- }
61
-
62
- // This example will refer to the same Durable Object instance,
63
- // since the name "foo" is hardcoded.
64
- const id = env.WEBSOCKET_SERVER.idFromName(roomId)
65
- const durableObject = env.WEBSOCKET_SERVER.get(id)
66
-
67
- if (url.pathname.endsWith('/websocket')) {
68
- const upgradeHeader = request.headers.get('Upgrade')
69
- if (!upgradeHeader || upgradeHeader !== 'websocket') {
70
- return new Response('Durable Object expected Upgrade: websocket', { status: 426 })
71
- }
72
-
73
- return durableObject.fetch(request)
74
- }
75
-
76
- return new Response(null, {
77
- status: 400,
78
- statusText: 'Bad Request',
79
- headers: {
80
- 'Content-Type': 'text/plain',
81
- },
82
- })
83
- },
84
- }
File without changes
File without changes