@livestore/sync-s2 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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/api-schema.d.ts +19 -19
- package/dist/api-schema.d.ts.map +1 -1
- package/dist/api-schema.js +4 -4
- package/dist/api-schema.js.map +1 -1
- package/dist/api-schema.test.js +15 -10
- package/dist/api-schema.test.js.map +1 -1
- package/dist/decode.d.ts +1 -1
- package/dist/decode.d.ts.map +1 -1
- package/dist/decode.js +3 -3
- package/dist/decode.js.map +1 -1
- package/dist/http-client-generated.d.ts +337 -1051
- package/dist/http-client-generated.d.ts.map +1 -1
- package/dist/http-client-generated.js +276 -231
- package/dist/http-client-generated.js.map +1 -1
- package/dist/limits.d.ts +39 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +89 -0
- package/dist/limits.js.map +1 -0
- package/dist/limits.test.d.ts +2 -0
- package/dist/limits.test.d.ts.map +1 -0
- package/dist/limits.test.js +30 -0
- package/dist/limits.test.js.map +1 -0
- package/dist/make-s2-url.d.ts.map +1 -1
- package/dist/make-s2-url.js +4 -4
- package/dist/make-s2-url.js.map +1 -1
- package/dist/mod.d.ts +1 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -0
- package/dist/mod.js.map +1 -1
- package/dist/s2-proxy-helpers.d.ts +26 -22
- package/dist/s2-proxy-helpers.d.ts.map +1 -1
- package/dist/s2-proxy-helpers.js +35 -33
- package/dist/s2-proxy-helpers.js.map +1 -1
- package/dist/sync-provider.d.ts +7 -7
- package/dist/sync-provider.d.ts.map +1 -1
- package/dist/sync-provider.js +55 -22
- package/dist/sync-provider.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +57 -13
- package/src/api-schema.test.ts +16 -10
- package/src/api-schema.ts +5 -4
- package/src/decode.ts +5 -4
- package/src/http-client-generated.ts +187 -258
- package/src/limits.test.ts +43 -0
- package/src/limits.ts +133 -0
- package/src/make-s2-url.ts +5 -4
- package/src/mod.ts +1 -0
- package/src/s2-proxy-helpers.ts +57 -47
- package/src/sync-provider.ts +88 -40
- package/src/types.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s2-proxy-helpers.js","sourceRoot":"","sources":["../src/s2-proxy-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"s2-proxy-helpers.js","sourceRoot":"","sources":["../src/s2-proxy-helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/sync-provider.d.ts
CHANGED
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
* DO NOT couple these systems together or assume 1:1 correspondence.
|
|
29
29
|
*
|
|
30
30
|
* Errors
|
|
31
|
-
* - push →
|
|
31
|
+
* - push → UnknownError on non‑2xx; pull → UnknownError on non‑2xx; ping/connect map timeouts to offline.
|
|
32
32
|
* - The proxy should surface helpful status codes and error bodies.
|
|
33
33
|
*/
|
|
34
|
-
import {
|
|
34
|
+
import { SyncBackend, UnknownError } from '@livestore/common';
|
|
35
35
|
import { type Duration, Schedule } from '@livestore/utils/effect';
|
|
36
36
|
import type { SyncMetadata } from './types.ts';
|
|
37
37
|
export interface SyncS2Options {
|
|
@@ -44,17 +44,17 @@ export interface SyncS2Options {
|
|
|
44
44
|
/** Enable periodic ping; default true */
|
|
45
45
|
enabled?: boolean;
|
|
46
46
|
/** Timeout for individual ping request; default 10s */
|
|
47
|
-
requestTimeout?: Duration.
|
|
47
|
+
requestTimeout?: Duration.Input;
|
|
48
48
|
/** Interval between ping requests; default 10s */
|
|
49
|
-
requestInterval?: Duration.
|
|
49
|
+
requestInterval?: Duration.Input;
|
|
50
50
|
};
|
|
51
51
|
retry?: {
|
|
52
52
|
/** Custom retry schedule for non-live pulls (default: 2 recurs, 100ms spaced) */
|
|
53
|
-
pull?: Schedule.Schedule<number,
|
|
53
|
+
pull?: Schedule.Schedule<number, UnknownError>;
|
|
54
54
|
/** Custom retry schedule for pushes (default: 2 recurs, 100ms spaced) */
|
|
55
|
-
push?: Schedule.Schedule<number,
|
|
55
|
+
push?: Schedule.Schedule<number, UnknownError>;
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
export declare const defaultRetry: Schedule.Schedule<number, unknown, never>;
|
|
58
|
+
export declare const defaultRetry: Schedule.Schedule<number, unknown, never, never>;
|
|
59
59
|
export declare const makeSyncBackend: ({ endpoint, ping: pingOptions, retry }: SyncS2Options) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
|
|
60
60
|
//# sourceMappingURL=sync-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-provider.d.ts","sourceRoot":"","sources":["../src/sync-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sync-provider.d.ts","sourceRoot":"","sources":["../src/sync-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAG7D,OAAO,EACL,KAAK,QAAQ,EAOb,QAAQ,EAIT,MAAM,yBAAyB,CAAA;AAOhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,EACJ,MAAM,GACN;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACL,IAAI,CAAC,EAAE;QACL,yCAAyC;QACzC,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,uDAAuD;QACvD,cAAc,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;QAC/B,kDAAkD;QAClD,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;KACjC,CAAA;IACD,KAAK,CAAC,EAAE;QACN,iFAAiF;QACjF,IAAI,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;QAC9C,yEAAyE;QACzE,IAAI,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;KAC/C,CAAA;CACF;AAED,eAAO,MAAM,YAAY,kDAAwE,CAAA;AAcjG,eAAO,MAAM,eAAe,GACzB,wCAAwC,aAAa,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CA+NpG,CAAA"}
|
package/dist/sync-provider.js
CHANGED
|
@@ -28,37 +28,44 @@
|
|
|
28
28
|
* DO NOT couple these systems together or assume 1:1 correspondence.
|
|
29
29
|
*
|
|
30
30
|
* Errors
|
|
31
|
-
* - push →
|
|
31
|
+
* - push → UnknownError on non‑2xx; pull → UnknownError on non‑2xx; ping/connect map timeouts to offline.
|
|
32
32
|
* - The proxy should surface helpful status codes and error bodies.
|
|
33
33
|
*/
|
|
34
|
-
import {
|
|
34
|
+
import { SyncBackend, UnknownError } from '@livestore/common';
|
|
35
35
|
import { shouldNeverHappen } from '@livestore/utils';
|
|
36
|
-
import { Effect, HttpClient, HttpClientRequest, HttpClientResponse, Option, Schedule, Schema,
|
|
36
|
+
import { Effect, Filter, HttpClient, HttpClientRequest, HttpClientResponse, Option, Schedule, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
|
|
37
|
+
import { Sse } from 'effect/unstable/encoding';
|
|
37
38
|
import * as ApiSchema from "./api-schema.js";
|
|
38
39
|
import { decodeReadBatch } from "./decode.js";
|
|
39
40
|
import * as HttpClientGenerated from "./http-client-generated.js";
|
|
40
|
-
|
|
41
|
+
import { chunkEventsForS2, S2LimitExceededError } from "./limits.js";
|
|
42
|
+
export const defaultRetry = Schedule.recurs(2).pipe(Schedule.addDelay(() => Effect.succeed(100)));
|
|
43
|
+
const getBrowserOrigin = () => {
|
|
44
|
+
if (typeof globalThis !== 'object' || globalThis === null || !('location' in globalThis)) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const { location } = globalThis;
|
|
48
|
+
return typeof location?.origin === 'string' ? location.origin : undefined;
|
|
49
|
+
};
|
|
41
50
|
export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ storeId, payload }) => Effect.gen(function* () {
|
|
42
51
|
const isConnected = yield* SubscriptionRef.make(false);
|
|
43
52
|
const pullEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.pull;
|
|
44
53
|
const pushEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.push;
|
|
45
54
|
const pingEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.ping;
|
|
46
55
|
const httpClient = yield* HttpClient.HttpClient;
|
|
47
|
-
const
|
|
48
|
-
|
|
56
|
+
const browserOrigin = getBrowserOrigin();
|
|
57
|
+
const pullEndpointHasSameOrigin = pullEndpoint.startsWith('/') || (browserOrigin !== undefined && browserOrigin === new URL(pullEndpoint).origin);
|
|
49
58
|
const pingTimeout = pingOptions?.requestTimeout ?? 10_000;
|
|
50
59
|
const ping = Effect.gen(function* () {
|
|
51
60
|
yield* httpClient.pipe(HttpClient.filterStatusOk).head(pingEndpoint);
|
|
52
61
|
yield* SubscriptionRef.set(isConnected, true);
|
|
53
|
-
}).pipe(
|
|
62
|
+
}).pipe(UnknownError.mapToUnknownError, Effect.timeout(pingTimeout), Effect.catchTag('TimeoutError', () => SubscriptionRef.set(isConnected, false)));
|
|
54
63
|
const pingInterval = pingOptions?.requestInterval ?? 10_000;
|
|
55
64
|
if (pingOptions?.enabled !== false) {
|
|
56
65
|
yield* ping.pipe(Effect.repeat(Schedule.spaced(pingInterval)), Effect.tapCauseLogPretty, Effect.forkScoped);
|
|
57
66
|
}
|
|
58
67
|
// No need to connect if the pull endpoint has the same origin as the current page
|
|
59
|
-
const connect = pullEndpointHasSameOrigin
|
|
60
|
-
? Effect.void
|
|
61
|
-
: ping.pipe(UnexpectedError.mapToUnexpectedError);
|
|
68
|
+
const connect = pullEndpointHasSameOrigin === true ? Effect.void : ping.pipe(UnknownError.mapToUnknownError);
|
|
62
69
|
const runPullSse = (cursor, live) => {
|
|
63
70
|
// Extract S2 seqNum from metadata for SSE cursor
|
|
64
71
|
const s2SeqNum = cursor.pipe(Option.flatMap((_) => _.metadata), Option.map((_) => _.s2SeqNum), Option.getOrElse(() => 'from-start'));
|
|
@@ -68,17 +75,17 @@ export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ st
|
|
|
68
75
|
.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeaders({ accept: 'text/event-stream' })))
|
|
69
76
|
.pipe(HttpClientResponse.stream,
|
|
70
77
|
// decode text and split into lines
|
|
71
|
-
Stream.decodeText('utf8'), Stream.pipeThroughChannel(Sse.
|
|
78
|
+
Stream.decodeText({ encoding: 'utf8' }), Stream.pipeThroughChannel(Sse.decode()),
|
|
72
79
|
// Filter out pings, map errors to stream failures
|
|
73
80
|
Stream.mapEffect(Effect.fnUntraced(function* (msg) {
|
|
74
81
|
const evt = msg.event.toLowerCase();
|
|
75
82
|
if (evt === 'ping')
|
|
76
83
|
return Option.none();
|
|
77
84
|
if (evt === 'error') {
|
|
78
|
-
return yield* new
|
|
85
|
+
return yield* new UnknownError({ cause: new Error(`SSE error: ${msg.data}`) });
|
|
79
86
|
}
|
|
80
87
|
if (evt === 'batch') {
|
|
81
|
-
const readBatch = yield* Schema.
|
|
88
|
+
const readBatch = yield* Schema.decodeEffect(Schema.fromJsonString(HttpClientGenerated.ReadBatch))(msg.data);
|
|
82
89
|
const batch = decodeReadBatch(readBatch);
|
|
83
90
|
const lastS2SeqNum = batch.at(-1)?.metadata.pipe(Option.map((_) => _.s2SeqNum), Option.getOrUndefined);
|
|
84
91
|
const tailSeqNum = readBatch.tail?.seq_num;
|
|
@@ -97,13 +104,13 @@ export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ st
|
|
|
97
104
|
return Option.none();
|
|
98
105
|
}
|
|
99
106
|
return shouldNeverHappen(`Unexpected SSE event: ${evt}`, msg);
|
|
100
|
-
})), Stream.filterMap((_) => _), // filter out Option.none()
|
|
101
|
-
Stream.mapError((cause) => (cause._tag === '
|
|
107
|
+
})), Stream.filterMap(Filter.fromPredicateOption((_) => _)), // filter out Option.none()
|
|
108
|
+
Stream.mapError((cause) => (cause._tag === 'UnknownError' ? cause : new UnknownError({ cause }))), Stream.retry(retry?.pull ?? defaultRetry));
|
|
102
109
|
};
|
|
103
110
|
const ssePull = (startCursor) => {
|
|
104
111
|
const computeNextCursor = (lastItem, current) => lastItem.pipe(Option.flatMap((item) => {
|
|
105
112
|
const lastBatchItem = item.batch.at(-1);
|
|
106
|
-
if (
|
|
113
|
+
if (lastBatchItem == null)
|
|
107
114
|
return Option.none();
|
|
108
115
|
return Option.some({
|
|
109
116
|
eventSequenceNumber: lastBatchItem.eventEncoded.seqNum,
|
|
@@ -115,7 +122,7 @@ export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ st
|
|
|
115
122
|
batch: [],
|
|
116
123
|
pageInfo: SyncBackend.pageInfoNoMore,
|
|
117
124
|
}));
|
|
118
|
-
const stream = isFirst ? sseStream(false) : sseStream(true);
|
|
125
|
+
const stream = isFirst === true ? sseStream(false) : sseStream(true);
|
|
119
126
|
return stream.pipe(
|
|
120
127
|
// Reconnect from last item if stream
|
|
121
128
|
Stream.concatWithLastElement((lastItem) => loop(computeNextCursor(lastItem, cursor), false)));
|
|
@@ -125,7 +132,7 @@ export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ st
|
|
|
125
132
|
return SyncBackend.of({
|
|
126
133
|
connect,
|
|
127
134
|
pull: (cursor, options) => {
|
|
128
|
-
if (options?.live) {
|
|
135
|
+
if (options?.live === true) {
|
|
129
136
|
return ssePull(cursor);
|
|
130
137
|
}
|
|
131
138
|
else {
|
|
@@ -135,10 +142,36 @@ export const makeSyncBackend = ({ endpoint, ping: pingOptions, retry }) => ({ st
|
|
|
135
142
|
}));
|
|
136
143
|
}
|
|
137
144
|
},
|
|
138
|
-
push: (batch) =>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
push: (batch) => Effect.gen(function* () {
|
|
146
|
+
const toUnknownError = (cause) => {
|
|
147
|
+
if (cause instanceof UnknownError) {
|
|
148
|
+
return cause;
|
|
149
|
+
}
|
|
150
|
+
if (cause instanceof S2LimitExceededError) {
|
|
151
|
+
const note = cause.limitType === 'record-metered-bytes'
|
|
152
|
+
? `S2 record exceeded ${cause.max} metered bytes (actual: ${cause.actual})`
|
|
153
|
+
: `S2 batch exceeded ${cause.max} (type: ${cause.limitType}, actual: ${cause.actual})`;
|
|
154
|
+
return new UnknownError({
|
|
155
|
+
cause,
|
|
156
|
+
note,
|
|
157
|
+
payload: {
|
|
158
|
+
limitType: cause.limitType,
|
|
159
|
+
max: cause.max,
|
|
160
|
+
actual: cause.actual,
|
|
161
|
+
recordIndex: cause.recordIndex,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return new UnknownError({ cause });
|
|
166
|
+
};
|
|
167
|
+
const chunks = yield* Effect.sync(() => chunkEventsForS2(batch)).pipe(Effect.mapError(toUnknownError));
|
|
168
|
+
for (const chunk of chunks) {
|
|
169
|
+
yield* HttpClientRequest.schemaBodyJson(ApiSchema.PushPayload)(HttpClientRequest.post(pushEndpoint), {
|
|
170
|
+
storeId,
|
|
171
|
+
batch: chunk.events,
|
|
172
|
+
}).pipe(Effect.andThen(httpClient.pipe(HttpClient.filterStatusOk).execute), Effect.andThen(HttpClientResponse.schemaBodyJson(ApiSchema.PushResponse)), Effect.mapError(toUnknownError), Effect.retry(retry?.push ?? defaultRetry));
|
|
173
|
+
}
|
|
174
|
+
}),
|
|
142
175
|
ping,
|
|
143
176
|
isConnected,
|
|
144
177
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-provider.js","sourceRoot":"","sources":["../src/sync-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sync-provider.js","sourceRoot":"","sources":["../src/sync-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ import { Brand, Schema } from '@livestore/utils/effect';
|
|
|
10
10
|
* - Are completely independent from LiveStore's logical event sequence numbers
|
|
11
11
|
*/
|
|
12
12
|
export type S2SeqNum = Brand.Branded<number, 'S2SeqNum'>;
|
|
13
|
-
export declare const s2SeqNum: Brand.
|
|
14
|
-
export declare const S2SeqNum: Schema.
|
|
13
|
+
export declare const s2SeqNum: Brand.Constructor<S2SeqNum>;
|
|
14
|
+
export declare const S2SeqNum: Schema.brand<Schema.Int, "S2SeqNum">;
|
|
15
15
|
/**
|
|
16
16
|
* Metadata for tracking S2-specific cursor information.
|
|
17
17
|
* This is separate from LiveStore's event sequence numbers to maintain
|
|
@@ -19,7 +19,7 @@ export declare const S2SeqNum: Schema.BrandSchema<number & Brand.Brand<"S2SeqNum
|
|
|
19
19
|
*/
|
|
20
20
|
export declare const SyncMetadata: Schema.Struct<{
|
|
21
21
|
/** S2's seq_num for stream positioning */
|
|
22
|
-
s2SeqNum: Schema.
|
|
22
|
+
readonly s2SeqNum: Schema.brand<Schema.Int, "S2SeqNum">;
|
|
23
23
|
}>;
|
|
24
24
|
export type SyncMetadata = typeof SyncMetadata.Type;
|
|
25
25
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEvD;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AACxD,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEvD;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AACxD,eAAO,MAAM,QAAQ,6BAA4B,CAAA;AACjD,eAAO,MAAM,QAAQ,sCAA6F,CAAA;AAElH;;;;GAIG;AACH,eAAO,MAAM,YAAY;IACvB,0CAA0C;;EAE1C,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA"}
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Brand, Schema } from '@livestore/utils/effect';
|
|
2
2
|
export const s2SeqNum = Brand.nominal();
|
|
3
|
-
export const S2SeqNum = Schema.fromBrand(s2SeqNum)(Schema.Int.
|
|
3
|
+
export const S2SeqNum = Schema.fromBrand('S2SeqNum', s2SeqNum)(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)));
|
|
4
4
|
/**
|
|
5
5
|
* Metadata for tracking S2-specific cursor information.
|
|
6
6
|
* This is separate from LiveStore's event sequence numbers to maintain
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAavD,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,EAAY,CAAA;AACjD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAavD,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,EAAY,CAAA;AACjD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAElH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,0CAA0C;IAC1C,QAAQ,EAAE,QAAQ;CACnB,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,27 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/sync-s2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-dev.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/livestorejs/livestore-contrib.git"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"package.json",
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
4
14
|
"type": "module",
|
|
5
15
|
"sideEffects": false,
|
|
6
16
|
"exports": {
|
|
7
17
|
".": "./dist/mod.js",
|
|
8
18
|
"./s2-proxy-helpers": "./dist/s2-proxy-helpers.js"
|
|
9
19
|
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"@livestore/common": "0.4.0-dev.9",
|
|
12
|
-
"@livestore/livestore": "0.4.0-dev.9",
|
|
13
|
-
"@livestore/utils": "0.4.0-dev.9"
|
|
14
|
-
},
|
|
15
|
-
"devDependencies": {},
|
|
16
|
-
"files": [
|
|
17
|
-
"package.json",
|
|
18
|
-
"src",
|
|
19
|
-
"dist"
|
|
20
|
-
],
|
|
21
|
-
"license": "Apache-2.0",
|
|
22
20
|
"publishConfig": {
|
|
23
21
|
"access": "public"
|
|
24
22
|
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@livestore/common": "0.5.0-dev.0",
|
|
25
|
+
"@livestore/livestore": "0.5.0-dev.0",
|
|
26
|
+
"@livestore/utils": "0.5.0-dev.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@effect/opentelemetry": "4.0.0-rc.111",
|
|
30
|
+
"@effect/platform-browser": "4.0.0-rc.111",
|
|
31
|
+
"@effect/platform-bun": "4.0.0-rc.111",
|
|
32
|
+
"@effect/platform-node": "4.0.0-rc.111",
|
|
33
|
+
"@effect/platform-node-shared": "4.0.0-rc.111",
|
|
34
|
+
"@effect/vitest": "4.0.0-rc.111",
|
|
35
|
+
"@opentelemetry/api": "1.9.0",
|
|
36
|
+
"@opentelemetry/resources": "2.2.0",
|
|
37
|
+
"@standard-schema/spec": "1.1.0",
|
|
38
|
+
"effect": "4.0.0-rc.111",
|
|
39
|
+
"vitest": "4.1.9"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@effect/opentelemetry": "^4.0.0-rc.111",
|
|
43
|
+
"@effect/platform-browser": "^4.0.0-rc.111",
|
|
44
|
+
"@effect/platform-bun": "^4.0.0-rc.111",
|
|
45
|
+
"@effect/platform-node": "^4.0.0-rc.111",
|
|
46
|
+
"@effect/platform-node-shared": "^4.0.0-rc.111",
|
|
47
|
+
"@effect/vitest": "^4.0.0-rc.111",
|
|
48
|
+
"@opentelemetry/api": "^1.9.0",
|
|
49
|
+
"@opentelemetry/resources": "^2.2.0",
|
|
50
|
+
"@standard-schema/spec": "^1.1.0",
|
|
51
|
+
"effect": "^4.0.0-rc.111"
|
|
52
|
+
},
|
|
53
|
+
"$genie": {
|
|
54
|
+
"source": "package.json.genie.ts",
|
|
55
|
+
"warning": "DO NOT EDIT - changes will be overwritten",
|
|
56
|
+
"workspaceClosureDirs": [
|
|
57
|
+
"packages/@livestore/sync-s2",
|
|
58
|
+
"repos/livestore/packages/@livestore/adapter-web",
|
|
59
|
+
"repos/livestore/packages/@livestore/common",
|
|
60
|
+
"repos/livestore/packages/@livestore/common-cf",
|
|
61
|
+
"repos/livestore/packages/@livestore/livestore",
|
|
62
|
+
"repos/livestore/packages/@livestore/sqlite-wasm",
|
|
63
|
+
"repos/livestore/packages/@livestore/utils",
|
|
64
|
+
"repos/livestore/packages/@livestore/utils-dev",
|
|
65
|
+
"repos/livestore/packages/@livestore/wa-sqlite",
|
|
66
|
+
"repos/livestore/packages/@livestore/webmesh"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
25
69
|
"scripts": {
|
|
26
70
|
"build": "",
|
|
27
71
|
"test": "echo 'No tests yet'"
|
package/src/api-schema.test.ts
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import { Schema } from '@livestore/utils/effect'
|
|
1
|
+
import { Result, Schema } from '@livestore/utils/effect'
|
|
2
2
|
import { describe, expect, it } from 'vitest'
|
|
3
|
+
|
|
3
4
|
import * as Api from './api-schema.ts'
|
|
4
5
|
import { decodePullArgsFromSearchParams } from './make-s2-url.ts'
|
|
5
6
|
import { s2SeqNum } from './types.ts'
|
|
6
7
|
|
|
7
8
|
describe('ApiSchema', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
for (const { name, payload } of [
|
|
10
|
+
{ name: 'an omitted payload', payload: undefined },
|
|
11
|
+
{ name: 'an explicit payload', payload: { a: 1 } },
|
|
12
|
+
] as const) {
|
|
13
|
+
it(`encodes and decodes PullArgs with ${name} via args search param`, () => {
|
|
14
|
+
const args = Api.PullArgs.make({ storeId: 'store-1', s2SeqNum: s2SeqNum(42), live: true, payload })
|
|
15
|
+
const encoded = Schema.encodeSync(Api.ArgsSchema)(args)
|
|
16
|
+
const sp = new URLSearchParams({ args: encoded })
|
|
17
|
+
const roundtrip = decodePullArgsFromSearchParams(sp)
|
|
18
|
+
expect(roundtrip).toEqual(args)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
15
21
|
|
|
16
22
|
it('decodes PushPayload with typed events', () => {
|
|
17
23
|
const payload = Api.PushPayload.make({ storeId: 's', batch: [] })
|
|
18
|
-
const decoded = Schema.
|
|
19
|
-
expect(decoded
|
|
24
|
+
const decoded = Schema.decodeUnknownResult(Api.PushPayload)(payload)
|
|
25
|
+
expect(Result.isSuccess(decoded)).toBe(true)
|
|
20
26
|
})
|
|
21
27
|
})
|
package/src/api-schema.ts
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
2
2
|
import { Schema } from '@livestore/utils/effect'
|
|
3
|
+
|
|
3
4
|
import { S2SeqNum } from './types.ts'
|
|
4
5
|
|
|
5
6
|
export const PullArgs = Schema.Struct({
|
|
6
7
|
storeId: Schema.String,
|
|
7
|
-
s2SeqNum: Schema.Union(S2SeqNum, Schema.Literal('from-start')),
|
|
8
|
+
s2SeqNum: Schema.Union([S2SeqNum, Schema.Literal('from-start')]),
|
|
8
9
|
live: Schema.Boolean,
|
|
9
|
-
payload: Schema.
|
|
10
|
+
payload: Schema.optional(Schema.Json),
|
|
10
11
|
})
|
|
11
12
|
|
|
12
13
|
export const PushPayload = Schema.Struct({
|
|
13
14
|
storeId: Schema.String,
|
|
14
|
-
batch: Schema.Array(LiveStoreEvent.
|
|
15
|
+
batch: Schema.Array(LiveStoreEvent.Global.Encoded),
|
|
15
16
|
})
|
|
16
17
|
|
|
17
18
|
export type PullArgs = typeof PullArgs.Type
|
|
18
19
|
export type PushPayload = typeof PushPayload.Type
|
|
19
20
|
|
|
20
21
|
/** Encoded form for query parameter `args` */
|
|
21
|
-
export const ArgsSchema = Schema.
|
|
22
|
+
export const ArgsSchema = Schema.StringFromUriComponent.pipe(Schema.decodeTo(Schema.fromJsonString(PullArgs)))
|
|
22
23
|
|
|
23
24
|
export const PushResponse = Schema.Struct({ success: Schema.Boolean })
|
|
24
25
|
export type PushResponse = typeof PushResponse.Type
|
package/src/decode.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { LiveStoreEvent } from '@livestore/common/schema'
|
|
2
2
|
import { Option, Schema } from '@livestore/utils/effect'
|
|
3
|
+
|
|
3
4
|
import type * as HttpClientGenerated from './http-client-generated.ts'
|
|
4
5
|
import { S2SeqNum } from './types.ts'
|
|
5
6
|
|
|
6
7
|
const ReadBatchSchema = Schema.Struct({
|
|
7
8
|
records: Schema.Array(
|
|
8
9
|
Schema.Struct({
|
|
9
|
-
body: Schema.optional(Schema.
|
|
10
|
+
body: Schema.optional(Schema.NullOr(Schema.fromJsonString(LiveStoreEvent.Global.Encoded))),
|
|
10
11
|
seq_num: S2SeqNum,
|
|
11
12
|
}),
|
|
12
13
|
),
|
|
13
|
-
}).
|
|
14
|
+
}).annotate({ title: '@livestore/sync-s2:ReadBatchSchema' })
|
|
14
15
|
|
|
15
16
|
export const decodeReadBatch = (
|
|
16
17
|
readBatch: typeof HttpClientGenerated.ReadBatch.Type,
|
|
17
18
|
): ReadonlyArray<{
|
|
18
|
-
eventEncoded: LiveStoreEvent.
|
|
19
|
+
eventEncoded: LiveStoreEvent.Global.Encoded
|
|
19
20
|
metadata: Option.Option<{ s2SeqNum: S2SeqNum }>
|
|
20
21
|
}> => {
|
|
21
22
|
const decoded = Schema.decodeSync(ReadBatchSchema)(readBatch)
|
|
22
23
|
return decoded.records
|
|
23
|
-
.filter((r): r is { body: LiveStoreEvent.
|
|
24
|
+
.filter((r): r is { body: LiveStoreEvent.Global.Encoded; seq_num: S2SeqNum } => r.body != null)
|
|
24
25
|
.map((r) => ({
|
|
25
26
|
eventEncoded: r.body,
|
|
26
27
|
metadata: Option.some({ s2SeqNum: r.seq_num }),
|