@livestore/sync-electric 0.3.0-dev.1 → 0.3.0-dev.11
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/index.d.ts +20 -62
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -13
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +16 -27
package/dist/index.d.ts
CHANGED
|
@@ -1,74 +1,39 @@
|
|
|
1
|
-
import type { SyncBackend
|
|
1
|
+
import type { SyncBackend } from '@livestore/common';
|
|
2
2
|
import type { Scope } from '@livestore/utils/effect';
|
|
3
3
|
import { Effect, Schema } from '@livestore/utils/effect';
|
|
4
4
|
export declare const syncBackend: any;
|
|
5
5
|
export declare const ApiPushEventPayload: Schema.TaggedStruct<"sync-electric.PushEvent", {
|
|
6
|
-
|
|
7
|
-
batch: Schema.Array$<Schema.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly args: any;
|
|
14
|
-
readonly parentId: {
|
|
15
|
-
readonly global: number;
|
|
16
|
-
readonly local: number;
|
|
17
|
-
};
|
|
18
|
-
}, {
|
|
19
|
-
readonly id: {
|
|
20
|
-
readonly global: number;
|
|
21
|
-
readonly local: number;
|
|
22
|
-
};
|
|
23
|
-
readonly mutation: string;
|
|
24
|
-
readonly args: any;
|
|
25
|
-
readonly parentId: {
|
|
26
|
-
readonly global: number;
|
|
27
|
-
readonly local: number;
|
|
28
|
-
};
|
|
29
|
-
}, never>>;
|
|
6
|
+
storeId: typeof Schema.String;
|
|
7
|
+
batch: Schema.Array$<Schema.Struct<{
|
|
8
|
+
mutation: typeof Schema.String;
|
|
9
|
+
args: typeof Schema.Any;
|
|
10
|
+
id: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventId">, number, never>;
|
|
11
|
+
parentId: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventId">, number, never>;
|
|
12
|
+
}>>;
|
|
30
13
|
}>;
|
|
31
14
|
export declare const ApiInitRoomPayload: Schema.TaggedStruct<"sync-electric.InitRoom", {
|
|
32
|
-
|
|
15
|
+
storeId: typeof Schema.String;
|
|
33
16
|
}>;
|
|
34
17
|
export declare const ApiPayload: Schema.Union<[Schema.TaggedStruct<"sync-electric.PushEvent", {
|
|
35
|
-
|
|
36
|
-
batch: Schema.Array$<Schema.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
readonly args: any;
|
|
43
|
-
readonly parentId: {
|
|
44
|
-
readonly global: number;
|
|
45
|
-
readonly local: number;
|
|
46
|
-
};
|
|
47
|
-
}, {
|
|
48
|
-
readonly id: {
|
|
49
|
-
readonly global: number;
|
|
50
|
-
readonly local: number;
|
|
51
|
-
};
|
|
52
|
-
readonly mutation: string;
|
|
53
|
-
readonly args: any;
|
|
54
|
-
readonly parentId: {
|
|
55
|
-
readonly global: number;
|
|
56
|
-
readonly local: number;
|
|
57
|
-
};
|
|
58
|
-
}, never>>;
|
|
18
|
+
storeId: typeof Schema.String;
|
|
19
|
+
batch: Schema.Array$<Schema.Struct<{
|
|
20
|
+
mutation: typeof Schema.String;
|
|
21
|
+
args: typeof Schema.Any;
|
|
22
|
+
id: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventId">, number, never>;
|
|
23
|
+
parentId: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventId">, number, never>;
|
|
24
|
+
}>>;
|
|
59
25
|
}>, Schema.TaggedStruct<"sync-electric.InitRoom", {
|
|
60
|
-
|
|
26
|
+
storeId: typeof Schema.String;
|
|
61
27
|
}>]>;
|
|
62
28
|
export declare const syncBackendOptions: <TOptions extends SyncBackendOptions>(options: TOptions) => TOptions;
|
|
63
|
-
export interface SyncBackendOptions
|
|
64
|
-
type: 'electric';
|
|
29
|
+
export interface SyncBackendOptions {
|
|
65
30
|
/**
|
|
66
31
|
* The host of the Electric server
|
|
67
32
|
*
|
|
68
33
|
* @example "https://localhost:3000"
|
|
69
34
|
*/
|
|
70
35
|
electricHost: string;
|
|
71
|
-
|
|
36
|
+
storeId: string;
|
|
72
37
|
/**
|
|
73
38
|
* The POST endpoint to push events to
|
|
74
39
|
*
|
|
@@ -77,17 +42,10 @@ export interface SyncBackendOptions extends SyncBackendOptionsBase {
|
|
|
77
42
|
*/
|
|
78
43
|
pushEventEndpoint: string;
|
|
79
44
|
}
|
|
80
|
-
interface LiveStoreGlobalElectric {
|
|
81
|
-
syncBackend: SyncBackendOptions;
|
|
82
|
-
}
|
|
83
|
-
declare global {
|
|
84
|
-
interface LiveStoreGlobal extends LiveStoreGlobalElectric {
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
45
|
type SyncMetadata = {
|
|
88
46
|
offset: string;
|
|
89
47
|
shapeId: string;
|
|
90
48
|
};
|
|
91
|
-
export declare const makeSyncBackend: ({ electricHost,
|
|
49
|
+
export declare const makeSyncBackend: ({ electricHost, storeId, pushEventEndpoint, }: SyncBackendOptions) => Effect.Effect<SyncBackend<SyncMetadata>, never, Scope.Scope>;
|
|
92
50
|
export {};
|
|
93
51
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAIpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAGL,MAAM,EAKN,MAAM,EAGP,MAAM,yBAAyB,CAAA;AA4BhC,eAAO,MAAM,WAAW,EAAS,GAAG,CAAA;AAEpC,eAAO,MAAM,mBAAmB;;;yBAyBpB,OAAQ,MAAM;qBAAkB,OACzC,GACH;YAAS,OAAQ,WACjB,iBAEc,cACR;kBACsC,OAAQ,WAAW,iBAAiB,cAC/E;;EA9BC,CAAA;AAEF,eAAO,MAAM,kBAAkB;;EAE7B,CAAA;AAEF,eAAO,MAAM,UAAU;;;yBAgBX,OAAQ,MAAM;qBAAkB,OACzC,GACH;YAAS,OAAQ,WACjB,iBAEc,cACR;kBACsC,OAAQ,WAAW,iBAAiB,cAC/E;;;;IAxB8E,CAAA;AAE/E,eAAO,MAAM,kBAAkB,GAAI,QAAQ,SAAS,kBAAkB,WAAW,QAAQ,aAAY,CAAA;AAErG,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAED,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IAEd,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,eAAe,kDAIzB,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAgI/E,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ Also see: https://github.com/electric-sql/electric/blob/main/packages/typescript
|
|
|
14
14
|
const ResponseItem = Schema.Struct({
|
|
15
15
|
/** Postgres path (e.g. "public.events/1") */
|
|
16
16
|
key: Schema.optional(Schema.String),
|
|
17
|
-
value: Schema.optional(MutationEvent.
|
|
17
|
+
value: Schema.optional(MutationEvent.AnyEncodedGlobal),
|
|
18
18
|
headers: Schema.Record({ key: Schema.String, value: Schema.Any }),
|
|
19
19
|
offset: Schema.optional(Schema.String),
|
|
20
20
|
});
|
|
@@ -26,18 +26,18 @@ const ResponseHeaders = Schema.Struct({
|
|
|
26
26
|
});
|
|
27
27
|
export const syncBackend = {};
|
|
28
28
|
export const ApiPushEventPayload = Schema.TaggedStruct('sync-electric.PushEvent', {
|
|
29
|
-
|
|
30
|
-
batch: Schema.Array(MutationEvent.
|
|
29
|
+
storeId: Schema.String,
|
|
30
|
+
batch: Schema.Array(MutationEvent.AnyEncodedGlobal),
|
|
31
31
|
});
|
|
32
32
|
export const ApiInitRoomPayload = Schema.TaggedStruct('sync-electric.InitRoom', {
|
|
33
|
-
|
|
33
|
+
storeId: Schema.String,
|
|
34
34
|
});
|
|
35
35
|
export const ApiPayload = Schema.Union(ApiPushEventPayload, ApiInitRoomPayload);
|
|
36
36
|
export const syncBackendOptions = (options) => options;
|
|
37
|
-
export const makeSyncBackend = ({ electricHost,
|
|
38
|
-
const endpointUrl = `${electricHost}/v1/shape/events_${
|
|
37
|
+
export const makeSyncBackend = ({ electricHost, storeId, pushEventEndpoint, }) => Effect.gen(function* () {
|
|
38
|
+
const endpointUrl = `${electricHost}/v1/shape/events_${storeId}`;
|
|
39
39
|
const isConnected = yield* SubscriptionRef.make(true);
|
|
40
|
-
const initRoom = HttpClientRequest.schemaBodyJson(ApiInitRoomPayload)(HttpClientRequest.post(pushEventEndpoint), ApiInitRoomPayload.make({
|
|
40
|
+
const initRoom = HttpClientRequest.schemaBodyJson(ApiInitRoomPayload)(HttpClientRequest.post(pushEventEndpoint), ApiInitRoomPayload.make({ storeId })).pipe(Effect.andThen(HttpClient.execute));
|
|
41
41
|
// TODO check whether we still need this
|
|
42
42
|
const pendingPushDeferredMap = new Map();
|
|
43
43
|
const pull = (args) => Effect.gen(function* () {
|
|
@@ -75,9 +75,9 @@ export const makeSyncBackend = ({ electricHost, roomId, pushEventEndpoint, }) =>
|
|
|
75
75
|
// if (listenForNew === false && items.length === 0) {
|
|
76
76
|
// return Option.none()
|
|
77
77
|
// }
|
|
78
|
-
const [newItems, pendingPushItems] = Chunk.fromIterable(items).pipe(Chunk.partition((item) => pendingPushDeferredMap.has(
|
|
78
|
+
const [newItems, pendingPushItems] = Chunk.fromIterable(items).pipe(Chunk.partition((item) => pendingPushDeferredMap.has(item.mutationEventEncoded.id)));
|
|
79
79
|
for (const item of pendingPushItems) {
|
|
80
|
-
const deferred = pendingPushDeferredMap.get(
|
|
80
|
+
const deferred = pendingPushDeferredMap.get(item.mutationEventEncoded.id);
|
|
81
81
|
yield* Deferred.succeed(deferred, Option.getOrThrow(item.metadata));
|
|
82
82
|
}
|
|
83
83
|
return Option.some([newItems, Option.some(nextCursor)]);
|
|
@@ -88,21 +88,20 @@ export const makeSyncBackend = ({ electricHost, roomId, pushEventEndpoint, }) =>
|
|
|
88
88
|
const deferreds = [];
|
|
89
89
|
for (const mutationEventEncoded of batch) {
|
|
90
90
|
const deferred = yield* Deferred.make();
|
|
91
|
-
pendingPushDeferredMap.set(
|
|
91
|
+
pendingPushDeferredMap.set(mutationEventEncoded.id, deferred);
|
|
92
92
|
deferreds.push(deferred);
|
|
93
93
|
}
|
|
94
|
-
const resp = yield* HttpClientRequest.schemaBodyJson(ApiPushEventPayload)(HttpClientRequest.post(pushEventEndpoint), ApiPushEventPayload.make({
|
|
94
|
+
const resp = yield* HttpClientRequest.schemaBodyJson(ApiPushEventPayload)(HttpClientRequest.post(pushEventEndpoint), ApiPushEventPayload.make({ storeId, batch })).pipe(Effect.andThen(HttpClient.execute), Effect.andThen(HttpClientResponse.schemaBodyJson(Schema.Struct({ success: Schema.Boolean }))), Effect.scoped, Effect.mapError((cause) => InvalidPushError.make({ reason: { _tag: 'Unexpected', message: cause.toString() } })));
|
|
95
95
|
if (!resp.success) {
|
|
96
96
|
yield* InvalidPushError.make({ reason: { _tag: 'Unexpected', message: 'Push failed' } });
|
|
97
97
|
}
|
|
98
98
|
const metadata = yield* Effect.all(deferreds, { concurrency: 'unbounded' }).pipe(Effect.map((_) => _.map(Option.some)));
|
|
99
99
|
for (const mutationEventEncoded of batch) {
|
|
100
|
-
pendingPushDeferredMap.delete(
|
|
100
|
+
pendingPushDeferredMap.delete(mutationEventEncoded.id);
|
|
101
101
|
}
|
|
102
102
|
return { metadata };
|
|
103
103
|
}),
|
|
104
104
|
isConnected,
|
|
105
105
|
};
|
|
106
106
|
});
|
|
107
|
-
const eventIdToString = (eventId) => `${eventId.global}_${eventId.local}`;
|
|
108
107
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAExD,OAAO,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,EACN,MAAM,EACN,MAAM,EACN,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAEhC;;;;;;;;;EASE;AAEF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/sync-electric",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.11",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
5
6
|
"exports": {
|
|
6
7
|
".": {
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
@@ -9,8 +10,8 @@
|
|
|
9
10
|
}
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
|
-
"@livestore/common": "0.3.0-dev.
|
|
13
|
-
"@livestore/utils": "0.3.0-dev.
|
|
13
|
+
"@livestore/common": "0.3.0-dev.11",
|
|
14
|
+
"@livestore/utils": "0.3.0-dev.11"
|
|
14
15
|
},
|
|
15
16
|
"devDependencies": {},
|
|
16
17
|
"publishConfig": {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SyncBackend
|
|
1
|
+
import type { SyncBackend } from '@livestore/common'
|
|
2
2
|
import { InvalidPullError, InvalidPushError } from '@livestore/common'
|
|
3
3
|
import type { EventId } from '@livestore/common/schema'
|
|
4
4
|
import { MutationEvent } from '@livestore/common/schema'
|
|
@@ -30,7 +30,7 @@ Also see: https://github.com/electric-sql/electric/blob/main/packages/typescript
|
|
|
30
30
|
const ResponseItem = Schema.Struct({
|
|
31
31
|
/** Postgres path (e.g. "public.events/1") */
|
|
32
32
|
key: Schema.optional(Schema.String),
|
|
33
|
-
value: Schema.optional(MutationEvent.
|
|
33
|
+
value: Schema.optional(MutationEvent.AnyEncodedGlobal),
|
|
34
34
|
headers: Schema.Record({ key: Schema.String, value: Schema.Any }),
|
|
35
35
|
offset: Schema.optional(Schema.String),
|
|
36
36
|
})
|
|
@@ -45,27 +45,26 @@ const ResponseHeaders = Schema.Struct({
|
|
|
45
45
|
export const syncBackend = {} as any
|
|
46
46
|
|
|
47
47
|
export const ApiPushEventPayload = Schema.TaggedStruct('sync-electric.PushEvent', {
|
|
48
|
-
|
|
49
|
-
batch: Schema.Array(MutationEvent.
|
|
48
|
+
storeId: Schema.String,
|
|
49
|
+
batch: Schema.Array(MutationEvent.AnyEncodedGlobal),
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
export const ApiInitRoomPayload = Schema.TaggedStruct('sync-electric.InitRoom', {
|
|
53
|
-
|
|
53
|
+
storeId: Schema.String,
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
export const ApiPayload = Schema.Union(ApiPushEventPayload, ApiInitRoomPayload)
|
|
57
57
|
|
|
58
58
|
export const syncBackendOptions = <TOptions extends SyncBackendOptions>(options: TOptions) => options
|
|
59
59
|
|
|
60
|
-
export interface SyncBackendOptions
|
|
61
|
-
type: 'electric'
|
|
60
|
+
export interface SyncBackendOptions {
|
|
62
61
|
/**
|
|
63
62
|
* The host of the Electric server
|
|
64
63
|
*
|
|
65
64
|
* @example "https://localhost:3000"
|
|
66
65
|
*/
|
|
67
66
|
electricHost: string
|
|
68
|
-
|
|
67
|
+
storeId: string
|
|
69
68
|
/**
|
|
70
69
|
* The POST endpoint to push events to
|
|
71
70
|
*
|
|
@@ -75,14 +74,6 @@ export interface SyncBackendOptions extends SyncBackendOptionsBase {
|
|
|
75
74
|
pushEventEndpoint: string
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
interface LiveStoreGlobalElectric {
|
|
79
|
-
syncBackend: SyncBackendOptions
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
declare global {
|
|
83
|
-
interface LiveStoreGlobal extends LiveStoreGlobalElectric {}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
77
|
type SyncMetadata = {
|
|
87
78
|
offset: string
|
|
88
79
|
// TODO move this into some kind of "global" sync metadata as it's the same for each event
|
|
@@ -91,21 +82,21 @@ type SyncMetadata = {
|
|
|
91
82
|
|
|
92
83
|
export const makeSyncBackend = ({
|
|
93
84
|
electricHost,
|
|
94
|
-
|
|
85
|
+
storeId,
|
|
95
86
|
pushEventEndpoint,
|
|
96
87
|
}: SyncBackendOptions): Effect.Effect<SyncBackend<SyncMetadata>, never, Scope.Scope> =>
|
|
97
88
|
Effect.gen(function* () {
|
|
98
|
-
const endpointUrl = `${electricHost}/v1/shape/events_${
|
|
89
|
+
const endpointUrl = `${electricHost}/v1/shape/events_${storeId}`
|
|
99
90
|
|
|
100
91
|
const isConnected = yield* SubscriptionRef.make(true)
|
|
101
92
|
|
|
102
93
|
const initRoom = HttpClientRequest.schemaBodyJson(ApiInitRoomPayload)(
|
|
103
94
|
HttpClientRequest.post(pushEventEndpoint),
|
|
104
|
-
ApiInitRoomPayload.make({
|
|
95
|
+
ApiInitRoomPayload.make({ storeId }),
|
|
105
96
|
).pipe(Effect.andThen(HttpClient.execute))
|
|
106
97
|
|
|
107
98
|
// TODO check whether we still need this
|
|
108
|
-
const pendingPushDeferredMap = new Map<
|
|
99
|
+
const pendingPushDeferredMap = new Map<EventId.GlobalEventId, Deferred.Deferred<SyncMetadata>>()
|
|
109
100
|
|
|
110
101
|
const pull = (args: Option.Option<SyncMetadata>) =>
|
|
111
102
|
Effect.gen(function* () {
|
|
@@ -157,11 +148,11 @@ export const makeSyncBackend = ({
|
|
|
157
148
|
// }
|
|
158
149
|
|
|
159
150
|
const [newItems, pendingPushItems] = Chunk.fromIterable(items).pipe(
|
|
160
|
-
Chunk.partition((item) => pendingPushDeferredMap.has(
|
|
151
|
+
Chunk.partition((item) => pendingPushDeferredMap.has(item.mutationEventEncoded.id)),
|
|
161
152
|
)
|
|
162
153
|
|
|
163
154
|
for (const item of pendingPushItems) {
|
|
164
|
-
const deferred = pendingPushDeferredMap.get(
|
|
155
|
+
const deferred = pendingPushDeferredMap.get(item.mutationEventEncoded.id)!
|
|
165
156
|
yield* Deferred.succeed(deferred, Option.getOrThrow(item.metadata))
|
|
166
157
|
}
|
|
167
158
|
|
|
@@ -189,13 +180,13 @@ export const makeSyncBackend = ({
|
|
|
189
180
|
const deferreds: Deferred.Deferred<SyncMetadata>[] = []
|
|
190
181
|
for (const mutationEventEncoded of batch) {
|
|
191
182
|
const deferred = yield* Deferred.make<SyncMetadata>()
|
|
192
|
-
pendingPushDeferredMap.set(
|
|
183
|
+
pendingPushDeferredMap.set(mutationEventEncoded.id, deferred)
|
|
193
184
|
deferreds.push(deferred)
|
|
194
185
|
}
|
|
195
186
|
|
|
196
187
|
const resp = yield* HttpClientRequest.schemaBodyJson(ApiPushEventPayload)(
|
|
197
188
|
HttpClientRequest.post(pushEventEndpoint),
|
|
198
|
-
ApiPushEventPayload.make({
|
|
189
|
+
ApiPushEventPayload.make({ storeId, batch }),
|
|
199
190
|
).pipe(
|
|
200
191
|
Effect.andThen(HttpClient.execute),
|
|
201
192
|
Effect.andThen(HttpClientResponse.schemaBodyJson(Schema.Struct({ success: Schema.Boolean }))),
|
|
@@ -214,7 +205,7 @@ export const makeSyncBackend = ({
|
|
|
214
205
|
)
|
|
215
206
|
|
|
216
207
|
for (const mutationEventEncoded of batch) {
|
|
217
|
-
pendingPushDeferredMap.delete(
|
|
208
|
+
pendingPushDeferredMap.delete(mutationEventEncoded.id)
|
|
218
209
|
}
|
|
219
210
|
|
|
220
211
|
return { metadata }
|
|
@@ -222,5 +213,3 @@ export const makeSyncBackend = ({
|
|
|
222
213
|
isConnected,
|
|
223
214
|
} satisfies SyncBackend<SyncMetadata>
|
|
224
215
|
})
|
|
225
|
-
|
|
226
|
-
const eventIdToString = (eventId: EventId.EventId) => `${eventId.global}_${eventId.local}`
|