@livestore/sync-cf 0.4.0-dev.2 → 0.4.0-dev.20

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 (136) hide show
  1. package/README.md +60 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cf-worker/do/durable-object.d.ts +45 -0
  4. package/dist/cf-worker/do/durable-object.d.ts.map +1 -0
  5. package/dist/cf-worker/do/durable-object.js +151 -0
  6. package/dist/cf-worker/do/durable-object.js.map +1 -0
  7. package/dist/cf-worker/do/layer.d.ts +34 -0
  8. package/dist/cf-worker/do/layer.d.ts.map +1 -0
  9. package/dist/cf-worker/do/layer.js +91 -0
  10. package/dist/cf-worker/do/layer.js.map +1 -0
  11. package/dist/cf-worker/do/pull.d.ts +6 -0
  12. package/dist/cf-worker/do/pull.d.ts.map +1 -0
  13. package/dist/cf-worker/do/pull.js +47 -0
  14. package/dist/cf-worker/do/pull.js.map +1 -0
  15. package/dist/cf-worker/do/push.d.ts +14 -0
  16. package/dist/cf-worker/do/push.d.ts.map +1 -0
  17. package/dist/cf-worker/do/push.js +131 -0
  18. package/dist/cf-worker/do/push.js.map +1 -0
  19. package/dist/cf-worker/{durable-object.d.ts → do/sqlite.d.ts} +83 -67
  20. package/dist/cf-worker/do/sqlite.d.ts.map +1 -0
  21. package/dist/cf-worker/do/sqlite.js +36 -0
  22. package/dist/cf-worker/do/sqlite.js.map +1 -0
  23. package/dist/cf-worker/do/sync-storage.d.ts +25 -0
  24. package/dist/cf-worker/do/sync-storage.d.ts.map +1 -0
  25. package/dist/cf-worker/do/sync-storage.js +191 -0
  26. package/dist/cf-worker/do/sync-storage.js.map +1 -0
  27. package/dist/cf-worker/do/transport/do-rpc-server.d.ts +9 -0
  28. package/dist/cf-worker/do/transport/do-rpc-server.d.ts.map +1 -0
  29. package/dist/cf-worker/do/transport/do-rpc-server.js +45 -0
  30. package/dist/cf-worker/do/transport/do-rpc-server.js.map +1 -0
  31. package/dist/cf-worker/do/transport/http-rpc-server.d.ts +8 -0
  32. package/dist/cf-worker/do/transport/http-rpc-server.d.ts.map +1 -0
  33. package/dist/cf-worker/do/transport/http-rpc-server.js +30 -0
  34. package/dist/cf-worker/do/transport/http-rpc-server.js.map +1 -0
  35. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts +4 -0
  36. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts.map +1 -0
  37. package/dist/cf-worker/do/transport/ws-rpc-server.js +21 -0
  38. package/dist/cf-worker/do/transport/ws-rpc-server.js.map +1 -0
  39. package/dist/cf-worker/mod.d.ts +4 -2
  40. package/dist/cf-worker/mod.d.ts.map +1 -1
  41. package/dist/cf-worker/mod.js +3 -2
  42. package/dist/cf-worker/mod.js.map +1 -1
  43. package/dist/cf-worker/shared.d.ts +175 -0
  44. package/dist/cf-worker/shared.d.ts.map +1 -0
  45. package/dist/cf-worker/shared.js +43 -0
  46. package/dist/cf-worker/shared.js.map +1 -0
  47. package/dist/cf-worker/worker.d.ts +59 -51
  48. package/dist/cf-worker/worker.d.ts.map +1 -1
  49. package/dist/cf-worker/worker.js +75 -43
  50. package/dist/cf-worker/worker.js.map +1 -1
  51. package/dist/client/mod.d.ts +4 -0
  52. package/dist/client/mod.d.ts.map +1 -0
  53. package/dist/client/mod.js +4 -0
  54. package/dist/client/mod.js.map +1 -0
  55. package/dist/client/transport/do-rpc-client.d.ts +40 -0
  56. package/dist/client/transport/do-rpc-client.d.ts.map +1 -0
  57. package/dist/client/transport/do-rpc-client.js +115 -0
  58. package/dist/client/transport/do-rpc-client.js.map +1 -0
  59. package/dist/client/transport/http-rpc-client.d.ts +43 -0
  60. package/dist/client/transport/http-rpc-client.d.ts.map +1 -0
  61. package/dist/client/transport/http-rpc-client.js +103 -0
  62. package/dist/client/transport/http-rpc-client.js.map +1 -0
  63. package/dist/client/transport/ws-rpc-client.d.ts +46 -0
  64. package/dist/client/transport/ws-rpc-client.d.ts.map +1 -0
  65. package/dist/client/transport/ws-rpc-client.js +108 -0
  66. package/dist/client/transport/ws-rpc-client.js.map +1 -0
  67. package/dist/common/constants.d.ts +7 -0
  68. package/dist/common/constants.d.ts.map +1 -0
  69. package/dist/common/constants.js +17 -0
  70. package/dist/common/constants.js.map +1 -0
  71. package/dist/common/do-rpc-schema.d.ts +76 -0
  72. package/dist/common/do-rpc-schema.d.ts.map +1 -0
  73. package/dist/common/do-rpc-schema.js +48 -0
  74. package/dist/common/do-rpc-schema.js.map +1 -0
  75. package/dist/common/http-rpc-schema.d.ts +58 -0
  76. package/dist/common/http-rpc-schema.d.ts.map +1 -0
  77. package/dist/common/http-rpc-schema.js +37 -0
  78. package/dist/common/http-rpc-schema.js.map +1 -0
  79. package/dist/common/mod.d.ts +8 -1
  80. package/dist/common/mod.d.ts.map +1 -1
  81. package/dist/common/mod.js +7 -1
  82. package/dist/common/mod.js.map +1 -1
  83. package/dist/common/{ws-message-types.d.ts → sync-message-types.d.ts} +119 -153
  84. package/dist/common/sync-message-types.d.ts.map +1 -0
  85. package/dist/common/sync-message-types.js +60 -0
  86. package/dist/common/sync-message-types.js.map +1 -0
  87. package/dist/common/ws-rpc-schema.d.ts +55 -0
  88. package/dist/common/ws-rpc-schema.d.ts.map +1 -0
  89. package/dist/common/ws-rpc-schema.js +32 -0
  90. package/dist/common/ws-rpc-schema.js.map +1 -0
  91. package/package.json +7 -8
  92. package/src/cf-worker/do/durable-object.ts +238 -0
  93. package/src/cf-worker/do/layer.ts +128 -0
  94. package/src/cf-worker/do/pull.ts +75 -0
  95. package/src/cf-worker/do/push.ts +205 -0
  96. package/src/cf-worker/do/sqlite.ts +37 -0
  97. package/src/cf-worker/do/sync-storage.ts +323 -0
  98. package/src/cf-worker/do/transport/do-rpc-server.ts +84 -0
  99. package/src/cf-worker/do/transport/http-rpc-server.ts +51 -0
  100. package/src/cf-worker/do/transport/ws-rpc-server.ts +34 -0
  101. package/src/cf-worker/mod.ts +4 -2
  102. package/src/cf-worker/shared.ts +141 -0
  103. package/src/cf-worker/worker.ts +138 -116
  104. package/src/client/mod.ts +3 -0
  105. package/src/client/transport/do-rpc-client.ts +189 -0
  106. package/src/client/transport/http-rpc-client.ts +225 -0
  107. package/src/client/transport/ws-rpc-client.ts +202 -0
  108. package/src/common/constants.ts +18 -0
  109. package/src/common/do-rpc-schema.ts +54 -0
  110. package/src/common/http-rpc-schema.ts +40 -0
  111. package/src/common/mod.ts +10 -1
  112. package/src/common/sync-message-types.ts +117 -0
  113. package/src/common/ws-rpc-schema.ts +36 -0
  114. package/dist/cf-worker/cf-types.d.ts +0 -2
  115. package/dist/cf-worker/cf-types.d.ts.map +0 -1
  116. package/dist/cf-worker/cf-types.js +0 -2
  117. package/dist/cf-worker/cf-types.js.map +0 -1
  118. package/dist/cf-worker/durable-object.d.ts.map +0 -1
  119. package/dist/cf-worker/durable-object.js +0 -317
  120. package/dist/cf-worker/durable-object.js.map +0 -1
  121. package/dist/common/ws-message-types.d.ts.map +0 -1
  122. package/dist/common/ws-message-types.js +0 -57
  123. package/dist/common/ws-message-types.js.map +0 -1
  124. package/dist/sync-impl/mod.d.ts +0 -2
  125. package/dist/sync-impl/mod.d.ts.map +0 -1
  126. package/dist/sync-impl/mod.js +0 -2
  127. package/dist/sync-impl/mod.js.map +0 -1
  128. package/dist/sync-impl/ws-impl.d.ts +0 -7
  129. package/dist/sync-impl/ws-impl.d.ts.map +0 -1
  130. package/dist/sync-impl/ws-impl.js +0 -175
  131. package/dist/sync-impl/ws-impl.js.map +0 -1
  132. package/src/cf-worker/cf-types.ts +0 -12
  133. package/src/cf-worker/durable-object.ts +0 -478
  134. package/src/common/ws-message-types.ts +0 -114
  135. package/src/sync-impl/mod.ts +0 -1
  136. package/src/sync-impl/ws-impl.ts +0 -274
@@ -1,17 +1,18 @@
1
- import { UnexpectedError } from '@livestore/common';
2
- import { Effect, UrlParams } from '@livestore/utils/effect';
3
- import { SearchParamsSchema } from "../common/mod.js";
4
- export const makeWorker = (options = {}) => {
1
+ import { env as importedEnv } from 'cloudflare:workers';
2
+ import { UnknownError } from '@livestore/common';
3
+ import { Effect, Schema } from '@livestore/utils/effect';
4
+ import { matchSyncRequest } from "./shared.js";
5
+ /**
6
+ * Produces a Cloudflare Worker `fetch` handler that delegates sync traffic to the
7
+ * Durable Object identified by `syncBackendBinding`.
8
+ *
9
+ * For more complex setups prefer implementing a custom `fetch` and call {@link handleSyncRequest}
10
+ * from the branch that handles LiveStore sync requests.
11
+ */
12
+ export const makeWorker = (options) => {
5
13
  return {
6
14
  fetch: async (request, env, _ctx) => {
7
15
  const url = new URL(request.url);
8
- await new Promise((resolve) => setTimeout(resolve, 500));
9
- if (request.method === 'GET' && url.pathname === '/') {
10
- return new Response('Info: WebSocket sync backend endpoint for @livestore/sync-cf.', {
11
- status: 200,
12
- headers: { 'Content-Type': 'text/plain' },
13
- });
14
- }
15
16
  const corsHeaders = options.enableCORS
16
17
  ? {
17
18
  'Access-Control-Allow-Origin': '*',
@@ -25,11 +26,25 @@ export const makeWorker = (options = {}) => {
25
26
  headers: corsHeaders,
26
27
  });
27
28
  }
28
- if (url.pathname.endsWith('/websocket')) {
29
- return handleWebSocket(request, env, _ctx, {
29
+ const searchParams = matchSyncRequest(request);
30
+ // Check if this is a sync request first, before showing info message
31
+ if (searchParams !== undefined) {
32
+ return handleSyncRequest({
33
+ request,
34
+ searchParams,
35
+ env,
36
+ ctx: _ctx,
37
+ syncBackendBinding: options.syncBackendBinding,
30
38
  headers: corsHeaders,
31
39
  validatePayload: options.validatePayload,
32
- durableObject: options.durableObject,
40
+ syncPayloadSchema: options.syncPayloadSchema,
41
+ });
42
+ }
43
+ // Only show info message for GET requests to / without sync parameters
44
+ if (request.method === 'GET' && url.pathname === '/') {
45
+ return new Response('Info: Sync backend endpoint for @livestore/sync-cf.', {
46
+ status: 200,
47
+ headers: { 'Content-Type': 'text/plain' },
33
48
  });
34
49
  }
35
50
  console.error('Invalid path', url.pathname);
@@ -45,7 +60,7 @@ export const makeWorker = (options = {}) => {
45
60
  };
46
61
  };
47
62
  /**
48
- * Handles `/websocket` endpoint.
63
+ * Handles LiveStore sync requests (e.g. with search params `?storeId=...&transport=...`).
49
64
  *
50
65
  * @example
51
66
  * ```ts
@@ -58,54 +73,71 @@ export const makeWorker = (options = {}) => {
58
73
  *
59
74
  * export default {
60
75
  * fetch: async (request, env, ctx) => {
61
- * if (request.url.endsWith('/websocket')) {
62
- * return handleWebSocket(request, env, ctx, { headers: {}, validatePayload })
76
+ * const searchParams = matchSyncRequest(request)
77
+ *
78
+ * // Is LiveStore sync request
79
+ * if (searchParams !== undefined) {
80
+ * return handleSyncRequest({
81
+ * request,
82
+ * searchParams,
83
+ * env,
84
+ * ctx,
85
+ * syncBackendBinding: 'SYNC_BACKEND_DO',
86
+ * headers: {},
87
+ * validatePayload,
88
+ * })
63
89
  * }
64
90
  *
65
91
  * return new Response('Invalid path', { status: 400 })
66
- * return new Response('Invalid path', { status: 400 })
67
92
  * }
68
93
  * }
69
94
  * ```
70
95
  *
71
- * @throws {UnexpectedError} If the payload is invalid
96
+ * @throws {UnknownError} If the payload is invalid
72
97
  */
73
- export const handleWebSocket = (request, env, _ctx, options = {}) => Effect.gen(function* () {
74
- const url = new URL(request.url);
75
- const urlParams = UrlParams.fromInput(url.searchParams);
76
- const paramsResult = yield* UrlParams.schemaStruct(SearchParamsSchema)(urlParams).pipe(Effect.either);
77
- if (paramsResult._tag === 'Left') {
78
- return new Response(`Invalid search params: ${paramsResult.left.toString()}`, {
79
- status: 500,
80
- headers: options?.headers,
81
- });
82
- }
83
- const { storeId, payload } = paramsResult.right;
84
- if (options.validatePayload !== undefined) {
85
- const result = yield* Effect.promise(async () => options.validatePayload(payload, { storeId })).pipe(UnexpectedError.mapToUnexpectedError, Effect.either);
86
- if (result._tag === 'Left') {
87
- console.error('Invalid payload', result.left);
88
- return new Response(result.left.toString(), { status: 400, headers: options.headers });
98
+ export const handleSyncRequest = ({ request, searchParams: { storeId, payload, transport }, env: explicitlyProvidedEnv, syncBackendBinding, headers, validatePayload, syncPayloadSchema, }) => Effect.gen(function* () {
99
+ if (validatePayload !== undefined) {
100
+ // Always decode with the supplied schema when present, even if payload is undefined.
101
+ // This ensures required payloads are enforced by the schema.
102
+ if (syncPayloadSchema !== undefined) {
103
+ const decodedEither = Schema.decodeUnknownEither(syncPayloadSchema)(payload);
104
+ if (decodedEither._tag === 'Left') {
105
+ const message = decodedEither.left.toString();
106
+ console.error('Invalid payload (decode failed)', message);
107
+ return new Response(message, { status: 400, headers });
108
+ }
109
+ const result = yield* Effect.promise(async () => validatePayload(decodedEither.right, { storeId })).pipe(UnknownError.mapToUnknownError, Effect.either);
110
+ if (result._tag === 'Left') {
111
+ console.error('Invalid payload (validation failed)', result.left);
112
+ return new Response(result.left.toString(), { status: 400, headers });
113
+ }
114
+ }
115
+ else {
116
+ const result = yield* Effect.promise(async () => validatePayload(payload, { storeId })).pipe(UnknownError.mapToUnknownError, Effect.either);
117
+ if (result._tag === 'Left') {
118
+ console.error('Invalid payload (validation failed)', result.left);
119
+ return new Response(result.left.toString(), { status: 400, headers });
120
+ }
89
121
  }
90
122
  }
91
- const durableObjectName = options.durableObject?.name ?? 'WEBSOCKET_SERVER';
92
- if (!(durableObjectName in env)) {
93
- return new Response(`Failed dependency: Required Durable Object binding '${durableObjectName}' not available`, {
123
+ const env = explicitlyProvidedEnv ?? importedEnv;
124
+ if (!(syncBackendBinding in env)) {
125
+ return new Response(`Failed dependency: Required Durable Object binding '${syncBackendBinding}' not available`, {
94
126
  status: 424,
95
- headers: options.headers,
127
+ headers,
96
128
  });
97
129
  }
98
- const durableObjectNamespace = env[durableObjectName];
130
+ const durableObjectNamespace = env[syncBackendBinding];
99
131
  const id = durableObjectNamespace.idFromName(storeId);
100
132
  const durableObject = durableObjectNamespace.get(id);
133
+ // Handle WebSocket upgrade request
101
134
  const upgradeHeader = request.headers.get('Upgrade');
102
- if (!upgradeHeader || upgradeHeader !== 'websocket') {
135
+ if (transport === 'ws' && (upgradeHeader === null || upgradeHeader !== 'websocket')) {
103
136
  return new Response('Durable Object expected Upgrade: websocket', {
104
137
  status: 426,
105
- headers: options?.headers,
138
+ headers,
106
139
  });
107
140
  }
108
- // Cloudflare Durable Object type clashing with lib.dom Response type, which is why we need the casts here.
109
141
  return yield* Effect.promise(() => durableObject.fetch(request));
110
142
  }).pipe(Effect.tapCauseLogPretty, Effect.runPromise);
111
143
  //# sourceMappingURL=worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './transport/do-rpc-client.ts';
2
+ export * from './transport/http-rpc-client.ts';
3
+ export * from './transport/ws-rpc-client.ts';
4
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/client/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,8BAA8B,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from "./transport/do-rpc-client.js";
2
+ export * from "./transport/http-rpc-client.js";
3
+ export * from "./transport/ws-rpc-client.js";
4
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/client/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,8BAA8B,CAAA"}
@@ -0,0 +1,40 @@
1
+ import { SyncBackend } from '@livestore/common';
2
+ import { type CfTypes } from '@livestore/common-cf';
3
+ import type { SyncBackendRpcInterface } from '../../cf-worker/shared.ts';
4
+ import type { SyncMetadata } from '../../common/sync-message-types.ts';
5
+ export interface SyncBackendRpcStub extends CfTypes.DurableObjectStub, SyncBackendRpcInterface {
6
+ }
7
+ export interface DoRpcSyncOptions {
8
+ /** Durable Object stub that implements the SyncDoRpc interface */
9
+ syncBackendStub: SyncBackendRpcStub;
10
+ /** Information about this DurableObject instance so the Sync DO instance can call back to this instance */
11
+ durableObjectContext: {
12
+ /** See `wrangler.toml` for the binding name */
13
+ bindingName: string;
14
+ /** `state.id.toString()` in the DO */
15
+ durableObjectId: string;
16
+ };
17
+ }
18
+ /**
19
+ * Creates a sync backend that uses Durable Object RPC to communicate with the sync backend.
20
+ *
21
+ * Used internally by `@livestore/adapter-cf` to connect to the sync backend.
22
+ */
23
+ export declare const makeDoRpcSync: ({ syncBackendStub, durableObjectContext }: DoRpcSyncOptions) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
24
+ /**
25
+ *
26
+ * ```ts
27
+ * import { DurableObject } from 'cloudflare:workers'
28
+ * import { ClientDoWithRpcCallback } from '@livestore/common-cf'
29
+ *
30
+ * export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback {
31
+ * // ...
32
+ *
33
+ * async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) {
34
+ * return handleSyncUpdateRpc(payload)
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ export declare const handleSyncUpdateRpc: (payload: unknown) => Promise<void>;
40
+ //# sourceMappingURL=do-rpc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"do-rpc-client.d.ts","sourceRoot":"","sources":["../../../src/client/transport/do-rpc-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,WAAW,EAAgB,MAAM,mBAAmB,CAAA;AAEjG,OAAO,EAAE,KAAK,OAAO,EAA8B,MAAM,sBAAsB,CAAA;AAe/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAIxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,iBAAiB,EAAE,uBAAuB;CAAG;AAMjG,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,eAAe,EAAE,kBAAkB,CAAA;IACnC,2GAA2G;IAC3G,oBAAoB,EAAE;QACpB,+CAA+C;QAC/C,WAAW,EAAE,MAAM,CAAA;QACnB,sCAAsC;QACtC,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACvB,2CAA2C,gBAAgB,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CAyGnD,CAAA;AAE7D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,kBAckD,CAAA"}
@@ -0,0 +1,115 @@
1
+ import { InvalidPullError, InvalidPushError, SyncBackend, UnknownError } from '@livestore/common';
2
+ import { splitChunkBySize } from '@livestore/common/sync';
3
+ import { layerProtocolDurableObject } from '@livestore/common-cf';
4
+ import { omit, shouldNeverHappen } from '@livestore/utils';
5
+ import { Chunk, Effect, identity, Layer, Mailbox, Option, RpcClient, RpcSerialization, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
6
+ import { MAX_DO_RPC_REQUEST_BYTES, MAX_PUSH_EVENTS_PER_REQUEST } from "../../common/constants.js";
7
+ import { SyncDoRpc } from "../../common/do-rpc-schema.js";
8
+ import { SyncMessage } from "../../common/mod.js";
9
+ const requestIdMailboxMap = new Map();
10
+ /**
11
+ * Creates a sync backend that uses Durable Object RPC to communicate with the sync backend.
12
+ *
13
+ * Used internally by `@livestore/adapter-cf` to connect to the sync backend.
14
+ */
15
+ export const makeDoRpcSync = ({ syncBackendStub, durableObjectContext }) => ({ storeId, payload }) => Effect.gen(function* () {
16
+ const isConnected = yield* SubscriptionRef.make(true);
17
+ const ProtocolLive = layerProtocolDurableObject({
18
+ callRpc: (payload) => syncBackendStub.rpc(payload),
19
+ callerContext: durableObjectContext,
20
+ }).pipe(Layer.provide(RpcSerialization.layerJson));
21
+ const context = yield* Layer.build(ProtocolLive);
22
+ const rpcClient = yield* RpcClient.make(SyncDoRpc).pipe(Effect.provide(context));
23
+ // Nothing to do here
24
+ const connect = Effect.void;
25
+ const backendIdHelper = yield* SyncBackend.makeBackendIdHelper;
26
+ const pull = (cursor, options) => rpcClient.SyncDoRpc.Pull({
27
+ cursor: cursor.pipe(Option.map((a) => ({
28
+ eventSequenceNumber: a.eventSequenceNumber,
29
+ backendId: backendIdHelper.get().pipe(Option.getOrThrow),
30
+ }))),
31
+ storeId,
32
+ rpcContext: options?.live ? { callerContext: durableObjectContext } : undefined,
33
+ }).pipe(options?.live
34
+ ? Stream.concatWithLastElement((res) => Effect.gen(function* () {
35
+ if (res._tag === 'None')
36
+ return shouldNeverHappen('There should at least be a no-more page info response');
37
+ const mailbox = yield* Mailbox.make().pipe(Effect.acquireRelease((mailbox) => mailbox.shutdown));
38
+ requestIdMailboxMap.set(res.value.rpcRequestId, mailbox);
39
+ return Mailbox.toStream(mailbox);
40
+ }).pipe(Stream.unwrapScoped))
41
+ : identity, Stream.tap((res) => backendIdHelper.lazySet(res.backendId)), Stream.map((res) => omit(res, ['backendId'])), Stream.mapError((cause) => (cause._tag === 'InvalidPullError' ? cause : InvalidPullError.make({ cause }))), Stream.withSpan('rpc-sync-client:pull'));
42
+ const push = (batch) => Effect.gen(function* () {
43
+ if (batch.length === 0) {
44
+ return;
45
+ }
46
+ const backendId = backendIdHelper.get();
47
+ const batchChunks = yield* Chunk.fromIterable(batch).pipe(splitChunkBySize({
48
+ maxItems: MAX_PUSH_EVENTS_PER_REQUEST,
49
+ maxBytes: MAX_DO_RPC_REQUEST_BYTES,
50
+ encode: (items) => ({
51
+ batch: items,
52
+ storeId,
53
+ backendId,
54
+ }),
55
+ }), Effect.mapError((cause) => new InvalidPushError({ cause: new UnknownError({ cause }) })));
56
+ for (const chunk of Chunk.toReadonlyArray(batchChunks)) {
57
+ const chunkArray = Chunk.toReadonlyArray(chunk);
58
+ yield* rpcClient.SyncDoRpc.Push({ batch: chunkArray, storeId, backendId });
59
+ }
60
+ }).pipe(Effect.mapError((cause) => cause._tag === 'InvalidPushError' ? cause : InvalidPushError.make({ cause: new UnknownError({ cause }) })), Effect.withSpan('rpc-sync-client:push'));
61
+ const ping = rpcClient.SyncDoRpc.Ping({
62
+ storeId,
63
+ payload,
64
+ }).pipe(UnknownError.mapToUnknownError, Effect.withSpan('rpc-sync-client:ping'));
65
+ return SyncBackend.of({
66
+ connect,
67
+ isConnected,
68
+ pull,
69
+ push,
70
+ ping,
71
+ metadata: {
72
+ name: 'rpc-sync-client',
73
+ description: 'Cloudflare Durable Object RPC Sync Client',
74
+ protocol: 'rpc',
75
+ storeId,
76
+ },
77
+ supports: {
78
+ pullPageInfoKnown: true,
79
+ pullLive: true,
80
+ },
81
+ });
82
+ }).pipe(Effect.withSpan('rpc-sync-client:makeDoRpcSync'));
83
+ /**
84
+ *
85
+ * ```ts
86
+ * import { DurableObject } from 'cloudflare:workers'
87
+ * import { ClientDoWithRpcCallback } from '@livestore/common-cf'
88
+ *
89
+ * export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback {
90
+ * // ...
91
+ *
92
+ * async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) {
93
+ * return handleSyncUpdateRpc(payload)
94
+ * }
95
+ * }
96
+ * ```
97
+ */
98
+ export const handleSyncUpdateRpc = (payload) => Effect.gen(function* () {
99
+ const decodedPayload = yield* Schema.decodeUnknown(ResponseChunkEncoded)(payload);
100
+ const decoded = yield* Schema.decodeUnknown(SyncMessage.PullResponse)(decodedPayload.values[0]);
101
+ const pullStreamMailbox = requestIdMailboxMap.get(decodedPayload.requestId);
102
+ if (pullStreamMailbox === undefined) {
103
+ // Case: DO was hibernated, so we need to manually update the store
104
+ yield* Effect.log(`No mailbox found for ${decodedPayload.requestId}`);
105
+ }
106
+ else {
107
+ // Case: DO was still alive, so the existing `pull` will pick up the new events
108
+ yield* pullStreamMailbox.offer(decoded);
109
+ }
110
+ }).pipe(Effect.withSpan('rpc-sync-client:rpcCallback'), Effect.tapCauseLogPretty, Effect.runPromise);
111
+ const ResponseChunkEncoded = Schema.Struct({
112
+ requestId: Schema.String,
113
+ values: Schema.Array(Schema.Any),
114
+ });
115
+ //# sourceMappingURL=do-rpc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"do-rpc-client.js","sourceRoot":"","sources":["../../../src/client/transport/do-rpc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { SyncBackend } from '@livestore/common';
2
+ import { type Duration } from '@livestore/utils/effect';
3
+ import type { SyncMetadata } from '../../common/sync-message-types.ts';
4
+ export interface HttpSyncOptions {
5
+ /**
6
+ * URL of the sync backend
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const syncBackend = makeHttpSync({ url: 'https://sync.example.com' })
11
+ * ```
12
+ */
13
+ url: string;
14
+ headers?: Record<string, string>;
15
+ livePull?: {
16
+ /**
17
+ * How often to poll for new events
18
+ * @default 5 seconds
19
+ */
20
+ pollInterval?: Duration.DurationInput;
21
+ };
22
+ ping?: {
23
+ /**
24
+ * @default true
25
+ */
26
+ enabled?: boolean;
27
+ /**
28
+ * How long to wait for a ping response before timing out
29
+ * @default 10 seconds
30
+ */
31
+ requestTimeout?: Duration.DurationInput;
32
+ /**
33
+ * How often to send ping requests
34
+ * @default 10 seconds
35
+ */
36
+ requestInterval?: Duration.DurationInput;
37
+ };
38
+ }
39
+ /**
40
+ * Note: This implementation requires the `enable_request_signal` compatibility flag to properly support `pull` streaming responses
41
+ */
42
+ export declare const makeHttpSync: (options: HttpSyncOptions) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
43
+ //# sourceMappingURL=http-rpc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-rpc-client.d.ts","sourceRoot":"","sources":["../../../src/client/transport/http-rpc-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,WAAW,EAAgB,MAAM,mBAAmB,CAAA;AAIjG,OAAO,EAEL,KAAK,QAAQ,EAcd,MAAM,yBAAyB,CAAA;AAIhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,QAAQ,CAAC,EAAE;QACT;;;WAGG;QACH,YAAY,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;KACtC,CAAA;IACD,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB;;;WAGG;QACH,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;QACvC;;;WAGG;QACH,eAAe,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;KACzC,CAAA;CACF;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,GACtB,SAAS,eAAe,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CA8JvE,CAAA"}
@@ -0,0 +1,103 @@
1
+ import { InvalidPullError, InvalidPushError, SyncBackend, UnknownError } from '@livestore/common';
2
+ import { splitChunkBySize } from '@livestore/common/sync';
3
+ import { omit } from '@livestore/utils';
4
+ import { Chunk, Effect, HttpClient, HttpClientRequest, identity, Layer, Option, RpcClient, RpcSerialization, Schedule, Schema, Stream, SubscriptionRef, UrlParams, } from '@livestore/utils/effect';
5
+ import { MAX_HTTP_REQUEST_BYTES, MAX_PUSH_EVENTS_PER_REQUEST } from "../../common/constants.js";
6
+ import { SyncHttpRpc } from "../../common/http-rpc-schema.js";
7
+ import { SearchParamsSchema } from "../../common/mod.js";
8
+ /**
9
+ * Note: This implementation requires the `enable_request_signal` compatibility flag to properly support `pull` streaming responses
10
+ */
11
+ export const makeHttpSync = (options) => ({ storeId, payload }) => Effect.gen(function* () {
12
+ // Based on ping responses
13
+ const isConnected = yield* SubscriptionRef.make(false);
14
+ const livePullInterval = options.livePull?.pollInterval ?? 5_000;
15
+ const urlParamsData = yield* Schema.encode(SearchParamsSchema)({
16
+ storeId,
17
+ payload,
18
+ transport: 'http',
19
+ }).pipe(UnknownError.mapToUnknownError);
20
+ const urlParams = UrlParams.fromInput(urlParamsData);
21
+ // Setup HTTP RPC Protocol
22
+ const HttpProtocolLive = RpcClient.layerProtocolHttp({
23
+ url: `${options.url}?${UrlParams.toString(urlParams)}`,
24
+ transformClient: HttpClient.mapRequest((request) => request.pipe(HttpClientRequest.setHeaders({
25
+ ...options.headers,
26
+ // Used in CF Worker to identify the store (additionally to storeId embedded in the RPC requests)
27
+ 'x-livestore-store-id': storeId,
28
+ }))),
29
+ }).pipe(Layer.provide(RpcSerialization.layerJson));
30
+ const rpcClient = yield* RpcClient.make(SyncHttpRpc).pipe(Effect.provide(HttpProtocolLive));
31
+ const pingTimeout = options.ping?.requestTimeout ?? 10_000;
32
+ const ping = Effect.gen(function* () {
33
+ yield* rpcClient.SyncHttpRpc.Ping({ storeId, payload });
34
+ yield* SubscriptionRef.set(isConnected, true);
35
+ }).pipe(UnknownError.mapToUnknownError, Effect.timeout(pingTimeout), Effect.catchTag('TimeoutException', () => SubscriptionRef.set(isConnected, false)));
36
+ const pingInterval = options.ping?.requestInterval ?? 10_000;
37
+ if (options.ping?.enabled !== false) {
38
+ // Automatically ping the server to keep the connection alive
39
+ yield* ping.pipe(Effect.repeat(Schedule.spaced(pingInterval)), Effect.tapCauseLogPretty, Effect.forkScoped);
40
+ }
41
+ // Helps already establish a TCP connection to the server
42
+ const connect = ping.pipe(UnknownError.mapToUnknownError);
43
+ const backendIdHelper = yield* SyncBackend.makeBackendIdHelper;
44
+ const mapCursor = (cursor) => cursor.pipe(Option.map((a) => ({
45
+ eventSequenceNumber: a.eventSequenceNumber,
46
+ backendId: backendIdHelper.get().pipe(Option.getOrThrow),
47
+ })));
48
+ const pull = (cursor, options) => rpcClient.SyncHttpRpc.Pull({
49
+ storeId,
50
+ payload,
51
+ cursor: mapCursor(cursor),
52
+ }).pipe(options?.live
53
+ ? // Phase 2: Simulate `live` pull by polling for new events
54
+ Stream.concatWithLastElement((lastElement) => {
55
+ const initialPhase2Cursor = lastElement.pipe(Option.flatMap((_) => Option.fromNullable(_.batch.at(-1)?.eventEncoded.seqNum)), Option.map((eventSequenceNumber) => ({ eventSequenceNumber })), Option.orElse(() => cursor), mapCursor);
56
+ return Stream.unfoldChunkEffect(initialPhase2Cursor, (currentCursor) => Effect.gen(function* () {
57
+ yield* Effect.sleep(livePullInterval);
58
+ const items = yield* rpcClient.SyncHttpRpc.Pull({ storeId, payload, cursor: currentCursor }).pipe(Stream.runCollect);
59
+ const nextCursor = Chunk.last(items).pipe(Option.flatMap((item) => Option.fromNullable(item.batch.at(-1)?.eventEncoded.seqNum)), Option.map((eventSequenceNumber) => ({ eventSequenceNumber })), Option.orElse(() => currentCursor), mapCursor);
60
+ return Option.some([items, nextCursor]);
61
+ }));
62
+ })
63
+ : identity, Stream.tap((res) => backendIdHelper.lazySet(res.backendId)), Stream.map((res) => omit(res, ['backendId'])), Stream.mapError((cause) => (cause._tag === 'InvalidPullError' ? cause : InvalidPullError.make({ cause }))), Stream.withSpan('http-sync-client:pull'));
64
+ const pushSemaphore = yield* Effect.makeSemaphore(1);
65
+ const push = (batch) => Effect.gen(function* () {
66
+ if (batch.length === 0) {
67
+ return;
68
+ }
69
+ const backendId = backendIdHelper.get();
70
+ const batchChunks = yield* Chunk.fromIterable(batch).pipe(splitChunkBySize({
71
+ maxItems: MAX_PUSH_EVENTS_PER_REQUEST,
72
+ maxBytes: MAX_HTTP_REQUEST_BYTES,
73
+ encode: (items) => ({
74
+ batch: items,
75
+ storeId,
76
+ payload,
77
+ backendId,
78
+ }),
79
+ }), Effect.mapError((cause) => new InvalidPushError({ cause: new UnknownError({ cause }) })));
80
+ for (const chunk of Chunk.toReadonlyArray(batchChunks)) {
81
+ const chunkArray = Chunk.toReadonlyArray(chunk);
82
+ yield* rpcClient.SyncHttpRpc.Push({ storeId, payload, batch: chunkArray, backendId });
83
+ }
84
+ }).pipe(pushSemaphore.withPermits(1), Effect.mapError((cause) => cause._tag === 'InvalidPushError' ? cause : new InvalidPushError({ cause: new UnknownError({ cause }) })), Effect.withSpan('http-sync-client:push'));
85
+ return SyncBackend.of({
86
+ connect,
87
+ isConnected,
88
+ pull,
89
+ push,
90
+ ping,
91
+ metadata: {
92
+ name: '@livestore/cf-sync-http',
93
+ description: 'LiveStore sync backend implementation using HTTP RPC',
94
+ protocol: 'http',
95
+ url: options.url,
96
+ },
97
+ supports: {
98
+ pullPageInfoKnown: true,
99
+ pullLive: true,
100
+ },
101
+ });
102
+ });
103
+ //# sourceMappingURL=http-rpc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-rpc-client.js","sourceRoot":"","sources":["../../../src/client/transport/http-rpc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { SyncBackend } from '@livestore/common';
2
+ import { type Duration, Effect, type Scope } from '@livestore/utils/effect';
3
+ import type { WebSocket } from '@livestore/utils/effect/browser';
4
+ import type { SyncMetadata } from '../../common/sync-message-types.ts';
5
+ export interface WsSyncOptions {
6
+ /**
7
+ * URL of the sync backend
8
+ *
9
+ * The protocol can either `http`/`https` or `ws`/`wss`
10
+ *
11
+ * @example 'https://sync.example.com'
12
+ */
13
+ url: string;
14
+ /**
15
+ * Optional WebSocket factory for custom WebSocket implementations (e.g., Cloudflare Durable Objects)
16
+ * If not provided, uses standard WebSocket from @livestore/utils/effect
17
+ */
18
+ webSocketFactory?: (wsUrl: string) => Effect.Effect<globalThis.WebSocket, WebSocket.WebSocketError, Scope.Scope>;
19
+ ping?: {
20
+ /**
21
+ * @default true
22
+ */
23
+ enabled?: boolean;
24
+ /**
25
+ * How long to wait for a ping response before timing out
26
+ * @default 10 seconds
27
+ */
28
+ requestTimeout?: Duration.DurationInput;
29
+ /**
30
+ * How often to send ping requests
31
+ * @default 10 seconds
32
+ */
33
+ requestInterval?: Duration.DurationInput;
34
+ };
35
+ }
36
+ /**
37
+ * Creates a sync backend that uses WebSocket to communicate with the sync backend.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { makeWsSync } from '@livestore/sync-cf/client'
42
+ *
43
+ * const syncBackend = makeWsSync({ url: 'wss://sync.example.com' })
44
+ */
45
+ export declare const makeWsSync: (options: WsSyncOptions) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
46
+ //# sourceMappingURL=ws-rpc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-rpc-client.d.ts","sourceRoot":"","sources":["../../../src/client/transport/ws-rpc-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsD,WAAW,EAAgB,MAAM,mBAAmB,CAAA;AAIjH,OAAO,EAEL,KAAK,QAAQ,EACb,MAAM,EAON,KAAK,KAAK,EAKX,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAGhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAGtE,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IAChH,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB;;;WAGG;QACH,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;QACvC;;;WAGG;QACH,eAAe,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;KACzC,CAAA;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GACpB,SAAS,aAAa,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CAqIrE,CAAA"}