@livestore/sync-cf 0.4.0-dev.9 → 0.5.0-dev.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 (113) hide show
  1. package/README.md +7 -8
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cf-worker/do/durable-object.d.ts +1 -1
  4. package/dist/cf-worker/do/durable-object.d.ts.map +1 -1
  5. package/dist/cf-worker/do/durable-object.js +36 -18
  6. package/dist/cf-worker/do/durable-object.js.map +1 -1
  7. package/dist/cf-worker/do/layer.d.ts +24 -20
  8. package/dist/cf-worker/do/layer.d.ts.map +1 -1
  9. package/dist/cf-worker/do/layer.js +57 -24
  10. package/dist/cf-worker/do/layer.js.map +1 -1
  11. package/dist/cf-worker/do/pull.d.ts +8 -3
  12. package/dist/cf-worker/do/pull.d.ts.map +1 -1
  13. package/dist/cf-worker/do/pull.js +26 -21
  14. package/dist/cf-worker/do/pull.js.map +1 -1
  15. package/dist/cf-worker/do/push.d.ts +20 -6
  16. package/dist/cf-worker/do/push.d.ts.map +1 -1
  17. package/dist/cf-worker/do/push.js +84 -56
  18. package/dist/cf-worker/do/push.js.map +1 -1
  19. package/dist/cf-worker/do/push.test.d.ts +2 -0
  20. package/dist/cf-worker/do/push.test.d.ts.map +1 -0
  21. package/dist/cf-worker/do/push.test.js +30 -0
  22. package/dist/cf-worker/do/push.test.js.map +1 -0
  23. package/dist/cf-worker/do/sqlite.d.ts +49 -52
  24. package/dist/cf-worker/do/sqlite.d.ts.map +1 -1
  25. package/dist/cf-worker/do/sqlite.js +14 -5
  26. package/dist/cf-worker/do/sqlite.js.map +1 -1
  27. package/dist/cf-worker/do/sync-storage.d.ts +15 -9
  28. package/dist/cf-worker/do/sync-storage.d.ts.map +1 -1
  29. package/dist/cf-worker/do/sync-storage.js +111 -25
  30. package/dist/cf-worker/do/sync-storage.js.map +1 -1
  31. package/dist/cf-worker/do/transport/do-rpc-server.d.ts +2 -2
  32. package/dist/cf-worker/do/transport/do-rpc-server.d.ts.map +1 -1
  33. package/dist/cf-worker/do/transport/do-rpc-server.js +31 -23
  34. package/dist/cf-worker/do/transport/do-rpc-server.js.map +1 -1
  35. package/dist/cf-worker/do/transport/http-rpc-server.d.ts +5 -3
  36. package/dist/cf-worker/do/transport/http-rpc-server.d.ts.map +1 -1
  37. package/dist/cf-worker/do/transport/http-rpc-server.js +28 -19
  38. package/dist/cf-worker/do/transport/http-rpc-server.js.map +1 -1
  39. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts +3 -2
  40. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts.map +1 -1
  41. package/dist/cf-worker/do/transport/ws-rpc-server.js +32 -10
  42. package/dist/cf-worker/do/transport/ws-rpc-server.js.map +1 -1
  43. package/dist/cf-worker/shared.d.ts +124 -34
  44. package/dist/cf-worker/shared.d.ts.map +1 -1
  45. package/dist/cf-worker/shared.js +52 -17
  46. package/dist/cf-worker/shared.js.map +1 -1
  47. package/dist/cf-worker/worker.d.ts +47 -39
  48. package/dist/cf-worker/worker.d.ts.map +1 -1
  49. package/dist/cf-worker/worker.js +54 -35
  50. package/dist/cf-worker/worker.js.map +1 -1
  51. package/dist/client/transport/do-rpc-client.d.ts +13 -4
  52. package/dist/client/transport/do-rpc-client.d.ts.map +1 -1
  53. package/dist/client/transport/do-rpc-client.js +74 -28
  54. package/dist/client/transport/do-rpc-client.js.map +1 -1
  55. package/dist/client/transport/http-rpc-client.d.ts +3 -3
  56. package/dist/client/transport/http-rpc-client.d.ts.map +1 -1
  57. package/dist/client/transport/http-rpc-client.js +51 -22
  58. package/dist/client/transport/http-rpc-client.js.map +1 -1
  59. package/dist/client/transport/ws-rpc-client.d.ts +4 -3
  60. package/dist/client/transport/ws-rpc-client.d.ts.map +1 -1
  61. package/dist/client/transport/ws-rpc-client.js +40 -22
  62. package/dist/client/transport/ws-rpc-client.js.map +1 -1
  63. package/dist/common/constants.d.ts +7 -0
  64. package/dist/common/constants.d.ts.map +1 -0
  65. package/dist/common/constants.js +17 -0
  66. package/dist/common/constants.js.map +1 -0
  67. package/dist/common/do-rpc-schema.d.ts +42 -43
  68. package/dist/common/do-rpc-schema.d.ts.map +1 -1
  69. package/dist/common/do-rpc-schema.js +5 -5
  70. package/dist/common/do-rpc-schema.js.map +1 -1
  71. package/dist/common/http-rpc-schema.d.ts +37 -38
  72. package/dist/common/http-rpc-schema.d.ts.map +1 -1
  73. package/dist/common/http-rpc-schema.js +7 -7
  74. package/dist/common/http-rpc-schema.js.map +1 -1
  75. package/dist/common/mod.d.ts +5 -3
  76. package/dist/common/mod.d.ts.map +1 -1
  77. package/dist/common/mod.js +4 -2
  78. package/dist/common/mod.js.map +1 -1
  79. package/dist/common/sync-message-types.d.ts +113 -130
  80. package/dist/common/sync-message-types.d.ts.map +1 -1
  81. package/dist/common/sync-message-types.js +29 -17
  82. package/dist/common/sync-message-types.js.map +1 -1
  83. package/dist/common/ws-rpc-schema.d.ts +34 -35
  84. package/dist/common/ws-rpc-schema.d.ts.map +1 -1
  85. package/dist/common/ws-rpc-schema.js +5 -5
  86. package/dist/common/ws-rpc-schema.js.map +1 -1
  87. package/package.json +57 -15
  88. package/src/cf-worker/do/durable-object.ts +59 -41
  89. package/src/cf-worker/do/layer.ts +153 -88
  90. package/src/cf-worker/do/pull.ts +48 -31
  91. package/src/cf-worker/do/push.test.ts +40 -0
  92. package/src/cf-worker/do/push.ts +163 -125
  93. package/src/cf-worker/do/sqlite.ts +15 -5
  94. package/src/cf-worker/do/sync-storage.ts +171 -38
  95. package/src/cf-worker/do/transport/do-rpc-server.ts +40 -40
  96. package/src/cf-worker/do/transport/http-rpc-server.ts +37 -20
  97. package/src/cf-worker/do/transport/ws-rpc-server.ts +44 -16
  98. package/src/cf-worker/shared.ts +152 -36
  99. package/src/cf-worker/worker.ts +110 -58
  100. package/src/client/transport/do-rpc-client.ts +106 -40
  101. package/src/client/transport/http-rpc-client.ts +74 -38
  102. package/src/client/transport/ws-rpc-client.ts +55 -29
  103. package/src/common/constants.ts +18 -0
  104. package/src/common/do-rpc-schema.ts +6 -5
  105. package/src/common/http-rpc-schema.ts +8 -7
  106. package/src/common/mod.ts +4 -3
  107. package/src/common/sync-message-types.ts +19 -19
  108. package/src/common/ws-rpc-schema.ts +6 -5
  109. package/dist/cf-worker/do/ws-chunking.d.ts +0 -22
  110. package/dist/cf-worker/do/ws-chunking.d.ts.map +0 -1
  111. package/dist/cf-worker/do/ws-chunking.js +0 -49
  112. package/dist/cf-worker/do/ws-chunking.js.map +0 -1
  113. package/src/cf-worker/do/ws-chunking.ts +0 -76
@@ -1,50 +1,57 @@
1
- import { BackendIdMismatchError, InvalidPushError, ServerAheadError, SyncBackend, UnexpectedError, } from '@livestore/common';
1
+ import { BackendIdMismatchError, ServerAheadError, SyncBackend, UnknownError } from '@livestore/common';
2
2
  import { emitStreamResponse } from '@livestore/common-cf';
3
- import { Chunk, Effect, Option, Schema } from '@livestore/utils/effect';
3
+ import { splitArrayBySize } from '@livestore/common/sync';
4
+ import { Effect, Option, ReadonlyArray as EffectArray, Schema } from '@livestore/utils/effect';
5
+ import { MAX_PUSH_EVENTS_PER_REQUEST, MAX_WS_MESSAGE_BYTES } from "../../common/constants.js";
4
6
  import { SyncMessage } from "../../common/mod.js";
5
- import { MAX_PULL_EVENTS_PER_MESSAGE, MAX_WS_MESSAGE_BYTES, WebSocketAttachmentSchema, } from "../shared.js";
6
- import { DoCtx } from "./layer.js";
7
- import { splitChunkBySize } from "./ws-chunking.js";
8
- const encodePullResponse = Schema.encodeSync(SyncMessage.PullResponse);
9
- export const makePush = ({ payload, options, storeId, ctx, env, }) => (pushRequest) => Effect.gen(function* () {
7
+ import { rpcSubscriptionKeyPrefix, WebSocketAttachmentSchema, } from "../shared.js";
8
+ import * as DoCtx from "./layer.js";
9
+ const pullResponseJsonSchema = Schema.toCodecJson(SyncMessage.PullResponse);
10
+ const encodePullResponse = Schema.encodeSync(pullResponseJsonSchema);
11
+ const jsonStringify = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown));
12
+ export const makePush = ({ payload, headers, options, storeId, ctx, env, }) => (pushRequest) => Effect.gen(function* () {
10
13
  // yield* Effect.log(`Pushing ${decodedMessage.batch.length} events`, decodedMessage.batch)
11
- const { backendId, storage, currentHeadRef, updateCurrentHead, rpcSubscriptions } = yield* DoCtx;
14
+ const { backendId, storage, currentHeadRef, updateCurrentHead, pushSemaphore } = yield* DoCtx.DoCtx;
12
15
  if (pushRequest.batch.length === 0) {
13
16
  return SyncMessage.PushAck.make({});
14
17
  }
15
- if (options?.onPush) {
16
- yield* Effect.tryAll(() => options.onPush(pushRequest, { storeId, payload })).pipe(UnexpectedError.mapToUnexpectedError);
18
+ if (options?.onPush !== undefined) {
19
+ yield* Effect.trySyncOrPromiseOrEffect(() => options.onPush(pushRequest, {
20
+ storeId,
21
+ ...(payload !== undefined ? { payload } : {}),
22
+ ...(headers !== undefined ? { headers } : {}),
23
+ })).pipe(UnknownError.mapToUnknownError);
17
24
  }
18
25
  if (pushRequest.backendId._tag === 'Some' && pushRequest.backendId.value !== backendId) {
19
26
  return yield* new BackendIdMismatchError({ expected: backendId, received: pushRequest.backendId.value });
20
27
  }
21
- // This part of the code needs to run sequentially to avoid race conditions
22
- const { createdAt } = yield* Effect.gen(function* () {
23
- const currentHead = currentHeadRef.current;
24
- // TODO handle clientId unique conflict
25
- // Validate the batch
26
- const firstEventParent = pushRequest.batch[0].parentSeqNum;
27
- if (firstEventParent !== currentHead) {
28
- // yield* Effect.logDebug('ServerAheadError: backend head mismatch', {
29
- // expectedHead: currentHead,
30
- // providedHead: firstEventParent,
31
- // batchSize: pushRequest.batch.length,
32
- // backendId,
33
- // })
34
- return yield* new ServerAheadError({ minimumExpectedNum: currentHead, providedNum: firstEventParent });
35
- }
36
- const createdAt = new Date().toISOString();
37
- // TODO possibly model this as a queue in order to speed up subsequent pushes
38
- yield* storage.appendEvents(pushRequest.batch, createdAt);
39
- updateCurrentHead(pushRequest.batch.at(-1).seqNum);
40
- return { createdAt };
41
- }).pipe(blockConcurrencyWhile(ctx));
42
- // Run in background but already return the push ack to the client
43
- yield* Effect.gen(function* () {
28
+ // A push is one ordered admit persist publish operation. `blockConcurrencyWhile` below protects
29
+ // the Durable Object state transition, while this semaphore keeps later pushes from overtaking this
30
+ // push during broadcasting without holding Cloudflare's concurrency gate across network I/O.
31
+ yield* runSerializedPushAdmission(pushSemaphore, Effect.gen(function* () {
32
+ // Keep the head check, durable append, and in-memory head update atomic with respect to other
33
+ // Durable Object requests. Broadcasting intentionally happens after this gate is released.
34
+ const { createdAt } = yield* Effect.gen(function* () {
35
+ const currentHead = currentHeadRef.current;
36
+ // TODO handle clientId unique conflict
37
+ // Validate the batch
38
+ const firstEventParent = pushRequest.batch[0].parentSeqNum;
39
+ if (firstEventParent !== currentHead) {
40
+ return yield* new ServerAheadError({ minimumExpectedNum: currentHead, providedNum: firstEventParent });
41
+ }
42
+ const createdAt = new Date().toISOString();
43
+ // TODO possibly model this as a queue in order to speed up subsequent pushes
44
+ yield* storage.appendEvents(pushRequest.batch, createdAt);
45
+ updateCurrentHead(pushRequest.batch.at(-1).seqNum);
46
+ return { createdAt };
47
+ }).pipe(blockConcurrencyWhile(ctx));
44
48
  const connectedClients = ctx.getWebSockets();
45
49
  // Preparing chunks of responses to make sure we don't exceed the WS message size limit.
46
- const responses = Chunk.fromIterable(pushRequest.batch).pipe(splitChunkBySize({
47
- maxItems: MAX_PULL_EVENTS_PER_MESSAGE,
50
+ if (EffectArray.isReadonlyArrayNonEmpty(pushRequest.batch) === false) {
51
+ return;
52
+ }
53
+ const responses = yield* splitArrayBySize({
54
+ maxItems: MAX_PUSH_EVENTS_PER_REQUEST,
48
55
  maxBytes: MAX_WS_MESSAGE_BYTES,
49
56
  encode: (items) => encodePullResponse(SyncMessage.PullResponse.make({
50
57
  batch: items.map((eventEncoded) => ({
@@ -54,8 +61,8 @@ export const makePush = ({ payload, options, storeId, ctx, env, }) => (pushReque
54
61
  pageInfo: SyncBackend.pageInfoNoMore,
55
62
  backendId,
56
63
  })),
57
- }), Chunk.map((eventsChunk) => {
58
- const batchWithMetadata = Chunk.toReadonlyArray(eventsChunk).map((eventEncoded) => ({
64
+ })(pushRequest.batch).pipe(Effect.map((eventBatch) => eventBatch.map((events) => {
65
+ const batchWithMetadata = events.map((eventEncoded) => ({
59
66
  eventEncoded,
60
67
  metadata: Option.some(SyncMessage.SyncMetadata.make({ createdAt })),
61
68
  }));
@@ -66,20 +73,20 @@ export const makePush = ({ payload, options, storeId, ctx, env, }) => (pushReque
66
73
  });
67
74
  return {
68
75
  response,
69
- encoded: Schema.encodeSync(SyncMessage.PullResponse)(response),
76
+ encoded: encodePullResponse(response),
70
77
  };
71
- }));
78
+ })));
72
79
  // Dual broadcasting: WebSocket + RPC clients
73
80
  // Broadcast to WebSocket clients
74
81
  if (connectedClients.length > 0) {
75
82
  for (const { response, encoded } of responses) {
76
83
  // Only calling once for now.
77
- if (options?.onPullRes) {
78
- yield* Effect.tryAll(() => options.onPullRes(response)).pipe(UnexpectedError.mapToUnexpectedError);
84
+ if (options?.onPullRes !== undefined) {
85
+ yield* Effect.trySyncOrPromiseOrEffect(() => options.onPullRes(response)).pipe(UnknownError.mapToUnknownError);
79
86
  }
80
87
  // NOTE we're also sending the pullRes chunk to the pushing ws client as confirmation
81
88
  for (const conn of connectedClients) {
82
- const attachment = Schema.decodeSync(WebSocketAttachmentSchema)(conn.deserializeAttachment());
89
+ const attachment = yield* Schema.decodeEffect(WebSocketAttachmentSchema)(conn.deserializeAttachment());
83
90
  // We're doing something a bit "advanced" here as we're directly emitting Effect RPC-compatible
84
91
  // response messsages on the Effect RPC-managed websocket connection to the WS client.
85
92
  // For this we need to get the RPC `requestId` from the WebSocket attachment.
@@ -89,42 +96,63 @@ export const makePush = ({ payload, options, storeId, ctx, env, }) => (pushReque
89
96
  requestId,
90
97
  values: [encoded],
91
98
  };
92
- conn.send(JSON.stringify(res));
99
+ conn.send(jsonStringify(res));
93
100
  }
94
101
  }
95
102
  }
96
103
  yield* Effect.logDebug(`Broadcasted to ${connectedClients.length} WebSocket clients`);
97
104
  }
98
- // RPC broadcasting would require reconstructing client stubs from clientIds
99
- if (rpcSubscriptions.size > 0) {
100
- for (const subscription of rpcSubscriptions.values()) {
105
+ // Subscribers live in the DO's KV storage (single source of truth), so fan-out survives reconstruction.
106
+ // emitStreamResponse reconstructs each client stub from its callerContext.
107
+ const rpcSubscriptions = Array.from(ctx.storage.kv.list({ prefix: rpcSubscriptionKeyPrefix }));
108
+ if (rpcSubscriptions.length > 0) {
109
+ for (const [, subscription] of rpcSubscriptions) {
101
110
  for (const { encoded } of responses) {
102
111
  yield* emitStreamResponse({
103
112
  callerContext: subscription.callerContext,
104
113
  env,
105
114
  requestId: subscription.requestId,
115
+ storeId: subscription.storeId,
106
116
  values: [encoded],
107
117
  }).pipe(Effect.tapCauseLogPretty, Effect.exit);
108
118
  }
109
119
  }
110
- yield* Effect.logDebug(`Broadcasted to ${rpcSubscriptions.size} RPC clients`);
120
+ yield* Effect.logDebug(`Broadcasted to ${rpcSubscriptions.length} RPC clients`);
111
121
  }
112
- }).pipe(Effect.tapCauseLogPretty, Effect.withSpan('push-rpc-broadcast'), Effect.uninterruptible, // We need to make sure Effect RPC doesn't interrupt this fiber
113
- Effect.fork);
114
- // We need to yield here to make sure the fork above is kicked off before we let Effect RPC finish the request
115
- yield* Effect.yieldNow();
122
+ }).pipe(Effect.tapCauseLogPretty, Effect.withSpan('push-rpc-broadcast')));
123
+ // Acknowledge only after the committed batch has been published, so a client cannot observe an
124
+ // advanced server head while the corresponding pull response is still waiting in a detached fiber.
116
125
  return SyncMessage.PushAck.make({});
117
126
  }).pipe(Effect.tap(Effect.fn(function* (message) {
118
- if (options?.onPushRes) {
119
- yield* Effect.tryAll(() => options.onPushRes(message)).pipe(UnexpectedError.mapToUnexpectedError);
127
+ if (options?.onPushRes !== undefined) {
128
+ yield* Effect.trySyncOrPromiseOrEffect(() => options.onPushRes(message)).pipe(UnknownError.mapToUnknownError);
120
129
  }
121
- })), Effect.mapError((cause) => InvalidPushError.make({ cause })), Effect.withSpan('sync-cf:do:push', { attributes: { storeId, batchSize: pushRequest.batch.length } }));
130
+ })), Effect.mapError((cause) => cause._tag === 'BackendIdMismatchError' || cause._tag === 'ServerAheadError' || cause._tag === 'UnknownError'
131
+ ? cause
132
+ : new UnknownError({ cause })), Effect.withSpan('sync-cf:do:push', { attributes: { storeId, batchSize: pushRequest.batch.length } }));
133
+ /**
134
+ * Serializes the complete push admission lifecycle, including publication to pull subscribers.
135
+ *
136
+ * This complements `blockConcurrencyWhile`: that Cloudflare primitive makes the durable state transition
137
+ * atomic with respect to other Durable Object requests, whereas this semaphore preserves push order after
138
+ * the storage gate is released and broadcasting begins. Keeping broadcast outside `blockConcurrencyWhile`
139
+ * avoids holding Cloudflare's concurrency gate across network I/O.
140
+ *
141
+ * Once admitted, the effect is uninterruptible so cancellation cannot leave a committed head without its
142
+ * matching pull response. Such a gap would make later pushers receive `ServerAhead` while waiting for a
143
+ * response that was never published.
144
+ */
145
+ export const runSerializedPushAdmission = (semaphore, admission) => semaphore.withPermits(1)(admission.pipe(Effect.uninterruptible));
122
146
  /**
147
+ * Runs the storage-backed state transition behind Cloudflare's Durable Object concurrency gate.
148
+ * This scope should remain limited to local persistence and head mutation; ordered publication is handled
149
+ * separately by `runSerializedPushAdmission` so outbound work does not block unrelated Durable Object events.
150
+ *
123
151
  * @see https://developers.cloudflare.com/durable-objects/api/state/#blockconcurrencywhile
124
152
  */
125
153
  const blockConcurrencyWhile = (ctx) => (eff) => Effect.gen(function* () {
126
- const runtime = yield* Effect.runtime();
127
- const exit = yield* Effect.promise(() => ctx.blockConcurrencyWhile(() => eff.pipe(Effect.provide(runtime), Effect.runPromiseExit)));
154
+ const services = yield* Effect.context();
155
+ const exit = yield* Effect.promise(() => ctx.blockConcurrencyWhile(() => eff.pipe(Effect.runPromiseExitWith(services))));
128
156
  return yield* exit;
129
157
  });
130
158
  //# sourceMappingURL=push.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/cf-worker/do/push.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../../src/cf-worker/do/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=push.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.test.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/push.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { Vitest } from '@livestore/utils-dev/node-vitest';
2
+ import { Deferred, Duration, Effect, Fiber, Semaphore } from '@livestore/utils/effect';
3
+ import { runSerializedPushAdmission } from "./push.js";
4
+ Vitest.describe('sync-cf push admission', () => {
5
+ Vitest.live('publishes an admitted push before honoring interruption', () => Effect.gen(function* () {
6
+ const semaphore = yield* Semaphore.make(1);
7
+ const persisted = yield* Deferred.make();
8
+ const allowBroadcast = yield* Deferred.make();
9
+ const broadcasted = yield* Deferred.make();
10
+ const admissionFiber = yield* runSerializedPushAdmission(semaphore, Effect.gen(function* () {
11
+ yield* Deferred.succeed(persisted, undefined);
12
+ yield* Deferred.await(allowBroadcast);
13
+ yield* Deferred.succeed(broadcasted, undefined);
14
+ })).pipe(Effect.forkChild);
15
+ // Reproduce cancellation after persistence but before the pull broadcast handoff.
16
+ yield* Deferred.await(persisted);
17
+ const interruptStarted = yield* Deferred.make();
18
+ const interruptFiber = yield* Effect.gen(function* () {
19
+ yield* Deferred.succeed(interruptStarted, undefined);
20
+ yield* Fiber.interrupt(admissionFiber);
21
+ }).pipe(Effect.forkChild);
22
+ yield* Deferred.await(interruptStarted);
23
+ yield* Effect.yieldNow;
24
+ yield* Deferred.succeed(allowBroadcast, undefined);
25
+ yield* Deferred.await(broadcasted).pipe(Effect.timeout(Duration.seconds(1)));
26
+ yield* Fiber.join(interruptFiber);
27
+ Vitest.expect(yield* Deferred.isDone(broadcasted)).toBe(true);
28
+ }));
29
+ });
30
+ //# sourceMappingURL=push.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.test.js","sourceRoot":"","sources":["../../../src/cf-worker/do/push.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEtF,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAA;AAEtD,MAAM,CAAC,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IAC7C,MAAM,CAAC,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE,CAC1E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAA;QAC9C,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAA;QACnD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAA;QAEhD,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,0BAA0B,CACtD,SAAS,EACT,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YAC7C,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;YACrC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACjD,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAExB,kFAAkF;QAClF,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAChC,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAA;QACrD,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAChD,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;YACpD,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;QACxC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACzB,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;QACvC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAA;QAEtB,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,CAAC,CAAA;QAClD,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5E,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAEjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/D,CAAC,CAAC,CACH,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -1,9 +1,14 @@
1
1
  import { State } from '@livestore/common/schema';
2
2
  import { Schema } from '@livestore/utils/effect';
3
+ /**
4
+ * Main event log table storing all LiveStore events.
5
+ *
6
+ * ⚠️ IMPORTANT: Any changes to this schema require bumping PERSISTENCE_FORMAT_VERSION in shared.ts
7
+ */
3
8
  export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"eventlog_7_$storeId", {
4
9
  readonly seqNum: {
5
10
  columnType: "integer";
6
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
11
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
7
12
  default: import("effect/Option").None<never>;
8
13
  nullable: false;
9
14
  primaryKey: true;
@@ -11,7 +16,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
11
16
  };
12
17
  readonly parentSeqNum: {
13
18
  columnType: "integer";
14
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
19
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
15
20
  default: import("effect/Option").None<never>;
16
21
  nullable: false;
17
22
  primaryKey: false;
@@ -19,7 +24,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
19
24
  };
20
25
  readonly name: {
21
26
  columnType: "text";
22
- schema: Schema.Schema<string, string, never>;
27
+ schema: Schema.Codec<string, string, never, never>;
23
28
  default: import("effect/Option").None<never>;
24
29
  nullable: false;
25
30
  primaryKey: false;
@@ -27,7 +32,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
27
32
  };
28
33
  readonly args: {
29
34
  columnType: "text";
30
- schema: Schema.Schema<any, string | null, never>;
35
+ schema: Schema.Codec<any, string | null, never, never>;
31
36
  default: import("effect/Option").None<never>;
32
37
  nullable: true;
33
38
  primaryKey: false;
@@ -36,7 +41,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
36
41
  /** ISO date format. Currently only used for debugging purposes. */
37
42
  readonly createdAt: {
38
43
  columnType: "text";
39
- schema: Schema.Schema<string, string, never>;
44
+ schema: Schema.Codec<string, string, never, never>;
40
45
  default: import("effect/Option").None<never>;
41
46
  nullable: false;
42
47
  primaryKey: false;
@@ -44,7 +49,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
44
49
  };
45
50
  readonly clientId: {
46
51
  columnType: "text";
47
- schema: Schema.Schema<string, string, never>;
52
+ schema: Schema.Codec<string, string, never, never>;
48
53
  default: import("effect/Option").None<never>;
49
54
  nullable: false;
50
55
  primaryKey: false;
@@ -52,7 +57,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
52
57
  };
53
58
  readonly sessionId: {
54
59
  columnType: "text";
55
- schema: Schema.Schema<string, string, never>;
60
+ schema: Schema.Codec<string, string, never, never>;
56
61
  default: import("effect/Option").None<never>;
57
62
  nullable: false;
58
63
  primaryKey: false;
@@ -61,7 +66,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
61
66
  }>, State.SQLite.WithDefaults<{
62
67
  readonly seqNum: {
63
68
  columnType: "integer";
64
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
69
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
65
70
  default: import("effect/Option").None<never>;
66
71
  nullable: false;
67
72
  primaryKey: true;
@@ -69,7 +74,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
69
74
  };
70
75
  readonly parentSeqNum: {
71
76
  columnType: "integer";
72
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
77
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
73
78
  default: import("effect/Option").None<never>;
74
79
  nullable: false;
75
80
  primaryKey: false;
@@ -77,7 +82,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
77
82
  };
78
83
  readonly name: {
79
84
  columnType: "text";
80
- schema: Schema.Schema<string, string, never>;
85
+ schema: Schema.Codec<string, string, never, never>;
81
86
  default: import("effect/Option").None<never>;
82
87
  nullable: false;
83
88
  primaryKey: false;
@@ -85,7 +90,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
85
90
  };
86
91
  readonly args: {
87
92
  columnType: "text";
88
- schema: Schema.Schema<any, string | null, never>;
93
+ schema: Schema.Codec<any, string | null, never, never>;
89
94
  default: import("effect/Option").None<never>;
90
95
  nullable: true;
91
96
  primaryKey: false;
@@ -94,7 +99,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
94
99
  /** ISO date format. Currently only used for debugging purposes. */
95
100
  readonly createdAt: {
96
101
  columnType: "text";
97
- schema: Schema.Schema<string, string, never>;
102
+ schema: Schema.Codec<string, string, never, never>;
98
103
  default: import("effect/Option").None<never>;
99
104
  nullable: false;
100
105
  primaryKey: false;
@@ -102,7 +107,7 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
102
107
  };
103
108
  readonly clientId: {
104
109
  columnType: "text";
105
- schema: Schema.Schema<string, string, never>;
110
+ schema: Schema.Codec<string, string, never, never>;
106
111
  default: import("effect/Option").None<never>;
107
112
  nullable: false;
108
113
  primaryKey: false;
@@ -110,34 +115,30 @@ export declare const eventlogTable: State.SQLite.TableDef<State.SQLite.SqliteTab
110
115
  };
111
116
  readonly sessionId: {
112
117
  columnType: "text";
113
- schema: Schema.Schema<string, string, never>;
114
- default: import("effect/Option").None<never>;
115
- nullable: false;
116
- primaryKey: false;
117
- autoIncrement: false;
118
- };
119
- }>, Schema.Schema<{
120
- readonly seqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
121
- readonly parentSeqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
122
- readonly name: string;
123
- readonly args: any;
124
- readonly createdAt: string;
125
- readonly clientId: string;
126
- readonly sessionId: string;
127
- }, {
128
- readonly seqNum: number;
129
- readonly parentSeqNum: number;
130
- readonly name: string;
131
- readonly args: string | null;
132
- readonly createdAt: string;
133
- readonly clientId: string;
134
- readonly sessionId: string;
135
- }, never>>;
136
- /** Will only ever have one row per durable object. */
118
+ schema: Schema.Codec<string, string, never, never>;
119
+ default: import("effect/Option").None<never>;
120
+ nullable: false;
121
+ primaryKey: false;
122
+ autoIncrement: false;
123
+ };
124
+ }>, Schema.Struct<{
125
+ readonly seqNum: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
126
+ readonly parentSeqNum: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
127
+ readonly name: Schema.Codec<string, string, never, never>;
128
+ readonly args: Schema.Codec<any, string | null, never, never>;
129
+ readonly createdAt: Schema.Codec<string, string, never, never>;
130
+ readonly clientId: Schema.Codec<string, string, never, never>;
131
+ readonly sessionId: Schema.Codec<string, string, never, never>;
132
+ }>>;
133
+ /**
134
+ * Context metadata table - one row per Durable Object.
135
+ *
136
+ * ⚠️ IMPORTANT: Any changes to this schema require bumping PERSISTENCE_FORMAT_VERSION in shared.ts
137
+ */
137
138
  export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"context_7", {
138
139
  readonly storeId: {
139
140
  columnType: "text";
140
- schema: Schema.Schema<string, string, never>;
141
+ schema: Schema.Codec<string, string, never, never>;
141
142
  default: import("effect/Option").None<never>;
142
143
  nullable: false;
143
144
  primaryKey: true;
@@ -145,7 +146,7 @@ export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTabl
145
146
  };
146
147
  readonly currentHead: {
147
148
  columnType: "integer";
148
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
149
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
149
150
  default: import("effect/Option").None<never>;
150
151
  nullable: false;
151
152
  primaryKey: false;
@@ -153,7 +154,7 @@ export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTabl
153
154
  };
154
155
  readonly backendId: {
155
156
  columnType: "text";
156
- schema: Schema.Schema<string, string, never>;
157
+ schema: Schema.Codec<string, string, never, never>;
157
158
  default: import("effect/Option").None<never>;
158
159
  nullable: false;
159
160
  primaryKey: false;
@@ -162,7 +163,7 @@ export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTabl
162
163
  }>, State.SQLite.WithDefaults<{
163
164
  readonly storeId: {
164
165
  columnType: "text";
165
- schema: Schema.Schema<string, string, never>;
166
+ schema: Schema.Codec<string, string, never, never>;
166
167
  default: import("effect/Option").None<never>;
167
168
  nullable: false;
168
169
  primaryKey: true;
@@ -170,7 +171,7 @@ export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTabl
170
171
  };
171
172
  readonly currentHead: {
172
173
  columnType: "integer";
173
- schema: Schema.Schema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
174
+ schema: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
174
175
  default: import("effect/Option").None<never>;
175
176
  nullable: false;
176
177
  primaryKey: false;
@@ -178,19 +179,15 @@ export declare const contextTable: State.SQLite.TableDef<State.SQLite.SqliteTabl
178
179
  };
179
180
  readonly backendId: {
180
181
  columnType: "text";
181
- schema: Schema.Schema<string, string, never>;
182
+ schema: Schema.Codec<string, string, never, never>;
182
183
  default: import("effect/Option").None<never>;
183
184
  nullable: false;
184
185
  primaryKey: false;
185
186
  autoIncrement: false;
186
187
  };
187
- }>, Schema.Schema<{
188
- readonly storeId: string;
189
- readonly currentHead: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
190
- readonly backendId: string;
191
- }, {
192
- readonly storeId: string;
193
- readonly currentHead: number;
194
- readonly backendId: string;
195
- }, never>>;
188
+ }>, Schema.Struct<{
189
+ readonly storeId: Schema.Codec<string, string, never, never>;
190
+ readonly currentHead: Schema.Codec<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never, never>;
191
+ readonly backendId: Schema.Codec<string, string, never, never>;
192
+ }>>;
196
193
  //# sourceMappingURL=sqlite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGhD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQtB,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAnE,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAKrE,CAAA;AAEF,sDAAsD;AACtD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAOvB,CAAA"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAIhD;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQtB,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAnE,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAKrE,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAOvB,CAAA"}
@@ -1,26 +1,35 @@
1
1
  import { EventSequenceNumber, State } from '@livestore/common/schema';
2
2
  import { Schema } from '@livestore/utils/effect';
3
3
  import { PERSISTENCE_FORMAT_VERSION } from "../shared.js";
4
+ /**
5
+ * Main event log table storing all LiveStore events.
6
+ *
7
+ * ⚠️ IMPORTANT: Any changes to this schema require bumping PERSISTENCE_FORMAT_VERSION in shared.ts
8
+ */
4
9
  export const eventlogTable = State.SQLite.table({
5
10
  // NOTE actual table name is determined at runtime to use proper storeId
6
11
  name: `eventlog_${PERSISTENCE_FORMAT_VERSION}_$storeId`,
7
12
  columns: {
8
- seqNum: State.SQLite.integer({ primaryKey: true, schema: EventSequenceNumber.GlobalEventSequenceNumber }),
9
- parentSeqNum: State.SQLite.integer({ schema: EventSequenceNumber.GlobalEventSequenceNumber }),
13
+ seqNum: State.SQLite.integer({ primaryKey: true, schema: EventSequenceNumber.Global.Schema }),
14
+ parentSeqNum: State.SQLite.integer({ schema: EventSequenceNumber.Global.Schema }),
10
15
  name: State.SQLite.text({}),
11
- args: State.SQLite.text({ schema: Schema.parseJson(Schema.Any), nullable: true }),
16
+ args: State.SQLite.text({ schema: Schema.fromJsonString(Schema.Any), nullable: true }),
12
17
  /** ISO date format. Currently only used for debugging purposes. */
13
18
  createdAt: State.SQLite.text({}),
14
19
  clientId: State.SQLite.text({}),
15
20
  sessionId: State.SQLite.text({}),
16
21
  },
17
22
  });
18
- /** Will only ever have one row per durable object. */
23
+ /**
24
+ * Context metadata table - one row per Durable Object.
25
+ *
26
+ * ⚠️ IMPORTANT: Any changes to this schema require bumping PERSISTENCE_FORMAT_VERSION in shared.ts
27
+ */
19
28
  export const contextTable = State.SQLite.table({
20
29
  name: `context_${PERSISTENCE_FORMAT_VERSION}`,
21
30
  columns: {
22
31
  storeId: State.SQLite.text({ primaryKey: true }),
23
- currentHead: State.SQLite.integer({ schema: EventSequenceNumber.GlobalEventSequenceNumber }),
32
+ currentHead: State.SQLite.integer({ schema: EventSequenceNumber.Global.Schema }),
24
33
  backendId: State.SQLite.text({}),
25
34
  },
26
35
  });
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../src/cf-worker/do/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;IAC9C,wEAAwE;IACxE,IAAI,EAAE,YAAY,0BAA0B,WAAW;IACvD,OAAO,EAAE;QACP,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,CAAC,yBAAyB,EAAE,CAAC;QACzG,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,yBAAyB,EAAE,CAAC;QAC7F,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACjF,mEAAmE;QACnE,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;KACjC;CACF,CAAC,CAAA;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;IAC7C,IAAI,EAAE,WAAW,0BAA0B,EAAE;IAC7C,OAAO,EAAE;QACP,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAChD,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,yBAAyB,EAAE,CAAC;QAC5F,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;KACjC;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../src/cf-worker/do/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;IAC9C,wEAAwE;IACxE,IAAI,EAAE,YAAY,0BAA0B,WAAW;IACvD,OAAO,EAAE;QACP,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7F,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACtF,mEAAmE;QACnE,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;KACjC;CACF,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;IAC7C,IAAI,EAAE,WAAW,0BAA0B,EAAE;IAC7C,OAAO,EAAE;QACP,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAChD,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAChF,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;KACjC;CACF,CAAC,CAAA"}
@@ -1,20 +1,26 @@
1
- import { UnexpectedError } from '@livestore/common';
2
- import type { LiveStoreEvent } from '@livestore/common/schema';
1
+ import { UnknownError } from '@livestore/common';
3
2
  import type { CfTypes } from '@livestore/common-cf';
3
+ import type { LiveStoreEvent } from '@livestore/common/schema';
4
4
  import { Effect, Option, Stream } from '@livestore/utils/effect';
5
5
  import { SyncMetadata } from '../../common/sync-message-types.ts';
6
- import { type Env, type StoreId } from '../shared.ts';
6
+ import { type StoreId } from '../shared.ts';
7
+ export type StorageEngine = {
8
+ _tag: 'd1';
9
+ db: CfTypes.D1Database;
10
+ } | {
11
+ _tag: 'do-sqlite';
12
+ };
7
13
  export type SyncStorage = {
8
14
  dbName: string;
9
15
  getEvents: (cursor: number | undefined) => Effect.Effect<{
10
16
  total: number;
11
17
  stream: Stream.Stream<{
12
- eventEncoded: LiveStoreEvent.AnyEncodedGlobal;
18
+ eventEncoded: LiveStoreEvent.Global.Encoded;
13
19
  metadata: Option.Option<SyncMetadata>;
14
- }, UnexpectedError>;
15
- }, UnexpectedError>;
16
- appendEvents: (batch: ReadonlyArray<LiveStoreEvent.AnyEncodedGlobal>, createdAt: string) => Effect.Effect<void, UnexpectedError>;
17
- resetStore: Effect.Effect<void, UnexpectedError>;
20
+ }, UnknownError>;
21
+ }, UnknownError>;
22
+ appendEvents: (batch: ReadonlyArray<LiveStoreEvent.Global.Encoded>, createdAt: string) => Effect.Effect<void, UnknownError>;
23
+ resetStore: Effect.Effect<void, UnknownError>;
18
24
  };
19
- export declare const makeStorage: (ctx: CfTypes.DurableObjectState, env: Env, storeId: StoreId) => SyncStorage;
25
+ export declare const makeStorage: (ctx: CfTypes.DurableObjectState, storeId: StoreId, engine: StorageEngine) => SyncStorage;
20
26
  //# sourceMappingURL=sync-storage.d.ts.map