@livestore/sync-electric 0.3.0-dev.8 → 0.3.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.
@@ -0,0 +1,47 @@
1
+ import { Schema } from '@livestore/utils/effect';
2
+ export declare const PushPayload: Schema.Struct<{
3
+ _tag: Schema.tag<"@livestore/sync-electric.Push">;
4
+ } & {
5
+ storeId: typeof Schema.String;
6
+ batch: Schema.Array$<Schema.Struct<{
7
+ name: typeof Schema.String;
8
+ args: typeof Schema.Any;
9
+ seqNum: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
10
+ parentSeqNum: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
11
+ clientId: typeof Schema.String;
12
+ sessionId: typeof Schema.String;
13
+ }>>;
14
+ }>;
15
+ export declare const PullPayload: Schema.Struct<{
16
+ _tag: Schema.tag<"@livestore/sync-electric.Pull">;
17
+ } & {
18
+ storeId: typeof Schema.String;
19
+ payload: Schema.UndefinedOr<Schema.Schema<Schema.JsonValue, Schema.JsonValue, never>>;
20
+ handle: Schema.Option<Schema.Struct<{
21
+ offset: typeof Schema.String;
22
+ handle: typeof Schema.String;
23
+ }>>;
24
+ }>;
25
+ export declare const ApiPayload: Schema.Union<[Schema.Struct<{
26
+ _tag: Schema.tag<"@livestore/sync-electric.Pull">;
27
+ } & {
28
+ storeId: typeof Schema.String;
29
+ payload: Schema.UndefinedOr<Schema.Schema<Schema.JsonValue, Schema.JsonValue, never>>;
30
+ handle: Schema.Option<Schema.Struct<{
31
+ offset: typeof Schema.String;
32
+ handle: typeof Schema.String;
33
+ }>>;
34
+ }>, Schema.Struct<{
35
+ _tag: Schema.tag<"@livestore/sync-electric.Push">;
36
+ } & {
37
+ storeId: typeof Schema.String;
38
+ batch: Schema.Array$<Schema.Struct<{
39
+ name: typeof Schema.String;
40
+ args: typeof Schema.Any;
41
+ seqNum: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
42
+ parentSeqNum: Schema.BrandSchema<number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">, number, never>;
43
+ clientId: typeof Schema.String;
44
+ sessionId: typeof Schema.String;
45
+ }>>;
46
+ }>]>;
47
+ //# sourceMappingURL=api-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-schema.d.ts","sourceRoot":"","sources":["../src/api-schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,eAAO,MAAM,WAAW;;;;;;;;;;;;EAGyC,CAAA;AAEjE,eAAO,MAAM,WAAW;;;;;;;;;EASyC,CAAA;AAEjE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;IAAyC,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { LiveStoreEvent } from '@livestore/common/schema';
2
+ import { Schema } from '@livestore/utils/effect';
3
+ export const PushPayload = Schema.TaggedStruct('@livestore/sync-electric.Push', {
4
+ storeId: Schema.String,
5
+ batch: Schema.Array(LiveStoreEvent.AnyEncodedGlobal),
6
+ }).annotations({ title: '@livestore/sync-electric.PushPayload' });
7
+ export const PullPayload = Schema.TaggedStruct('@livestore/sync-electric.Pull', {
8
+ storeId: Schema.String,
9
+ payload: Schema.UndefinedOr(Schema.JsonValue),
10
+ handle: Schema.Option(Schema.Struct({
11
+ offset: Schema.String,
12
+ handle: Schema.String,
13
+ })),
14
+ }).annotations({ title: '@livestore/sync-electric.PullPayload' });
15
+ export const ApiPayload = Schema.Union(PullPayload, PushPayload);
16
+ //# sourceMappingURL=api-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-schema.js","sourceRoot":"","sources":["../src/api-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAEhD,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,+BAA+B,EAAE;IAC9E,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC;CACrD,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,+BAA+B,EAAE;IAC9E,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC,MAAM,CACnB,MAAM,CAAC,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CACH;CACF,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,51 +1,61 @@
1
- import type { SyncBackend } from '@livestore/common';
2
- import type { Scope } from '@livestore/utils/effect';
3
- import { Effect, Schema } from '@livestore/utils/effect';
1
+ import type { SyncBackendConstructor } from '@livestore/common';
2
+ import { Schema } from '@livestore/utils/effect';
3
+ export * as ApiSchema from './api-schema.js';
4
4
  export declare const syncBackend: any;
5
- export declare const ApiPushEventPayload: Schema.TaggedStruct<"sync-electric.PushEvent", {
6
- roomId: 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
- }>>;
13
- }>;
14
- export declare const ApiInitRoomPayload: Schema.TaggedStruct<"sync-electric.InitRoom", {
15
- roomId: typeof Schema.String;
16
- }>;
17
- export declare const ApiPayload: Schema.Union<[Schema.TaggedStruct<"sync-electric.PushEvent", {
18
- roomId: 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
- }>>;
25
- }>, Schema.TaggedStruct<"sync-electric.InitRoom", {
26
- roomId: typeof Schema.String;
27
- }>]>;
28
5
  export declare const syncBackendOptions: <TOptions extends SyncBackendOptions>(options: TOptions) => TOptions;
29
- export interface SyncBackendOptions {
6
+ /**
7
+ * This function should be called in a trusted environment (e.g. a proxy server) as it
8
+ * requires access to senstive information (e.g. `apiSecret` / `sourceSecret`).
9
+ */
10
+ export declare const makeElectricUrl: ({ electricHost, searchParams: providedSearchParams, sourceId, sourceSecret, apiSecret, }: {
11
+ electricHost: string;
30
12
  /**
31
- * The host of the Electric server
32
- *
33
- * @example "https://localhost:3000"
13
+ * Needed to extract information from the search params which the `@livestore/sync-electric`
14
+ * client implementation automatically adds:
15
+ * - `handle`: the ElectricSQL handle
16
+ * - `storeId`: the Livestore storeId
34
17
  */
35
- electricHost: string;
36
- roomId: string;
18
+ searchParams: URLSearchParams;
19
+ /** Needed for Electric Cloud */
20
+ sourceId?: string;
21
+ /** Needed for Electric Cloud */
22
+ sourceSecret?: string;
23
+ /** For self-hosted ElectricSQL */
24
+ apiSecret?: string;
25
+ }) => {
26
+ url: string;
27
+ storeId: string;
28
+ needsInit: boolean;
29
+ payload: Schema.JsonValue | undefined;
30
+ };
31
+ export interface SyncBackendOptions {
37
32
  /**
38
- * The POST endpoint to push events to
33
+ * The endpoint to pull/push events. Pull is a `GET` request, push is a `POST` request.
34
+ * Usually this endpoint is part of your API layer to proxy requests to the Electric server
35
+ * e.g. to implement auth, rate limiting, etc.
39
36
  *
40
- * @example "/api/push-event"
41
- * @example "https://api.myapp.com/push-event"
37
+ * @example "/api/electric"
38
+ * @example { push: "/api/push-event", pull: "/api/pull-event" }
42
39
  */
43
- pushEventEndpoint: string;
40
+ endpoint: string | {
41
+ push: string;
42
+ pull: string;
43
+ };
44
44
  }
45
+ export declare const SyncMetadata: Schema.Struct<{
46
+ offset: typeof Schema.String;
47
+ handle: typeof Schema.String;
48
+ }>;
45
49
  type SyncMetadata = {
46
50
  offset: string;
47
- shapeId: string;
51
+ handle: string;
48
52
  };
49
- export declare const makeSyncBackend: ({ electricHost, roomId, pushEventEndpoint, }: SyncBackendOptions) => Effect.Effect<SyncBackend<SyncMetadata>, never, Scope.Scope>;
50
- export {};
53
+ export declare const makeSyncBackend: ({ endpoint }: SyncBackendOptions) => SyncBackendConstructor<SyncMetadata>;
54
+ /**
55
+ * Needs to be bumped when the storage format changes (e.g. eventlogTable schema changes)
56
+ *
57
+ * Changing this version number will lead to a "soft reset".
58
+ */
59
+ export declare const PERSISTENCE_FORMAT_VERSION = 6;
60
+ export declare const toTableName: (storeId: string) => string;
51
61
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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;;;yBA2Bf,OAAQ,MAGzB;qBAAkB,OACd,GAAG;YAEL,OADK,WAAW,iBAAiB,cAAc;kBACtC,OAGX,WAAS,iBAAiB,cACpB;;EAlCJ,CAAA;AAEF,eAAO,MAAM,kBAAkB;;EAE7B,CAAA;AAEF,eAAO,MAAM,UAAU;;;yBAkBN,OAAQ,MAGzB;qBAAkB,OACd,GAAG;YAEL,OADK,WAAW,iBAAiB,cAAc;kBACtC,OAGX,WAAS,iBAAiB,cACpB;;;;IA5ByE,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,MAAM,EAAE,MAAM,CAAA;IACd;;;;;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,iDAIzB,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAgI/E,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAI5F,OAAO,EAOL,MAAM,EAGP,MAAM,yBAAyB,CAAA;AAIhC,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAA;AA8E5C,eAAO,MAAM,WAAW,EAAS,GAAG,CAAA;AAEpC,eAAO,MAAM,kBAAkB,GAAI,QAAQ,SAAS,kBAAkB,EAAE,SAAS,QAAQ,aAAY,CAAA;AAErG;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,0FAM7B;IACD,YAAY,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,YAAY,EAAE,eAAe,CAAA;IAC7B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;;;;;CAwCA,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,QAAQ,EACJ,MAAM,GACN;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACN;AAED,eAAO,MAAM,YAAY;;;EAIvB,CAAA;AAEF,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAA;IAEd,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,eAAe,GACzB,cAAc,kBAAkB,KAAG,sBAAsB,CAAC,YAAY,CA2InE,CAAA;AAEN;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,WAG1C,CAAA"}
package/dist/index.js CHANGED
@@ -1,107 +1,207 @@
1
- import { InvalidPullError, InvalidPushError } from '@livestore/common';
2
- import { MutationEvent } from '@livestore/common/schema';
3
- import { Chunk, Deferred, Effect, HttpClient, HttpClientRequest, HttpClientResponse, Option, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
1
+ import { InvalidPullError, InvalidPushError, UnexpectedError } from '@livestore/common';
2
+ import { LiveStoreEvent } from '@livestore/common/schema';
3
+ import { notYetImplemented, shouldNeverHappen } from '@livestore/utils';
4
+ import { Chunk, Effect, HttpClient, HttpClientRequest, HttpClientResponse, Option, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
5
+ import * as ApiSchema from './api-schema.js';
6
+ export * as ApiSchema from './api-schema.js';
4
7
  /*
5
8
  Example data:
6
9
 
7
- [{"key":"\"public\".\"events\"/\"1\"","value":{"id":"1","mutation":"test","args_json":"{\"test\":\"test\"}","schema_hash":"1","created_at":"2024-09-07T10:05:31.445Z"},"headers":{"operation":"insert","relation":["public","events"]},"offset":"0_0"}
8
- ,{"key":"\"public\".\"events\"/\"1725703554783\"","value":{"id":"1725703554783","mutation":"test","args_json":"{\"test\":\"test\"}","schema_hash":"1","created_at":"2024-09-07T10:05:54.783Z"},"headers":{"operation":"insert","relation":["public","events"]},"offset":"0_0"}
9
- ,{"headers":{"control":"up-to-date"}}]
10
+ [
11
+ {
12
+ "value": {
13
+ "args": "{\"id\": \"127c3df4-0855-4587-ae75-14463f4a3aa0\", \"text\": \"1\"}",
14
+ "clientId": "S_YOa",
15
+ "id": "0",
16
+ "name": "todoCreated",
17
+ "parentSeqNum": "-1"
18
+ },
19
+ "key": "\"public\".\"events_9069baf0_b3e6_42f7_980f_188416eab3fx3\"/\"0\"",
20
+ "headers": {
21
+ "last": true,
22
+ "relation": [
23
+ "public",
24
+ "events_9069baf0_b3e6_42f7_980f_188416eab3fx3"
25
+ ],
26
+ "operation": "insert",
27
+ "lsn": 27294160,
28
+ "op_position": 0,
29
+ "txids": [
30
+ 753
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "headers": {
36
+ "control": "up-to-date",
37
+ "global_last_seen_lsn": 27294160
38
+ }
39
+ }
40
+ ]
41
+
10
42
 
11
43
  Also see: https://github.com/electric-sql/electric/blob/main/packages/typescript-client/src/client.ts
12
44
 
13
45
  */
46
+ const LiveStoreEventGlobalFromStringRecord = Schema.Struct({
47
+ seqNum: Schema.NumberFromString,
48
+ parentSeqNum: Schema.NumberFromString,
49
+ name: Schema.String,
50
+ args: Schema.parseJson(Schema.Any),
51
+ clientId: Schema.String,
52
+ sessionId: Schema.String,
53
+ }).pipe(Schema.transform(LiveStoreEvent.AnyEncodedGlobal, {
54
+ decode: (_) => _,
55
+ encode: (_) => _,
56
+ }));
14
57
  const ResponseItem = Schema.Struct({
15
- /** Postgres path (e.g. "public.events/1") */
58
+ /** Postgres path (e.g. `"public"."events_9069baf0_b3e6_42f7_980f_188416eab3fx3"/"0"`) */
16
59
  key: Schema.optional(Schema.String),
17
- value: Schema.optional(MutationEvent.AnyEncodedGlobal),
18
- headers: Schema.Record({ key: Schema.String, value: Schema.Any }),
19
- offset: Schema.optional(Schema.String),
60
+ value: Schema.optional(LiveStoreEventGlobalFromStringRecord),
61
+ headers: Schema.Union(Schema.Struct({
62
+ operation: Schema.Union(Schema.Literal('insert'), Schema.Literal('update'), Schema.Literal('delete')),
63
+ relation: Schema.Array(Schema.String),
64
+ }), Schema.Struct({
65
+ control: Schema.String,
66
+ })),
20
67
  });
21
68
  const ResponseHeaders = Schema.Struct({
22
- 'x-electric-shape-id': Schema.String,
23
- // 'x-electric-schema': Schema.parseJson(Schema.Any),
69
+ 'electric-handle': Schema.String,
70
+ // 'electric-schema': Schema.parseJson(Schema.Any),
24
71
  /** e.g. 26799576_0 */
25
- 'x-electric-chunk-last-offset': Schema.String,
72
+ 'electric-offset': Schema.String,
26
73
  });
27
74
  export const syncBackend = {};
28
- export const ApiPushEventPayload = Schema.TaggedStruct('sync-electric.PushEvent', {
29
- roomId: Schema.String,
30
- batch: Schema.Array(MutationEvent.AnyEncodedGlobal),
31
- });
32
- export const ApiInitRoomPayload = Schema.TaggedStruct('sync-electric.InitRoom', {
33
- roomId: Schema.String,
34
- });
35
- export const ApiPayload = Schema.Union(ApiPushEventPayload, ApiInitRoomPayload);
36
75
  export const syncBackendOptions = (options) => options;
37
- export const makeSyncBackend = ({ electricHost, roomId, pushEventEndpoint, }) => Effect.gen(function* () {
38
- const endpointUrl = `${electricHost}/v1/shape/events_${roomId}`;
76
+ /**
77
+ * This function should be called in a trusted environment (e.g. a proxy server) as it
78
+ * requires access to senstive information (e.g. `apiSecret` / `sourceSecret`).
79
+ */
80
+ export const makeElectricUrl = ({ electricHost, searchParams: providedSearchParams, sourceId, sourceSecret, apiSecret, }) => {
81
+ const endpointUrl = `${electricHost}/v1/shape`;
82
+ const argsResult = Schema.decodeUnknownEither(Schema.Struct({ args: Schema.parseJson(ApiSchema.PullPayload) }))(Object.fromEntries(providedSearchParams.entries()));
83
+ if (argsResult._tag === 'Left') {
84
+ return shouldNeverHappen('Invalid search params provided to makeElectricUrl', providedSearchParams, Object.fromEntries(providedSearchParams.entries()));
85
+ }
86
+ const args = argsResult.right.args;
87
+ const tableName = toTableName(args.storeId);
88
+ const searchParams = new URLSearchParams();
89
+ searchParams.set('table', tableName);
90
+ if (sourceId !== undefined) {
91
+ searchParams.set('source_id', sourceId);
92
+ }
93
+ if (sourceSecret !== undefined) {
94
+ searchParams.set('source_secret', sourceSecret);
95
+ }
96
+ if (apiSecret !== undefined) {
97
+ searchParams.set('api_secret', apiSecret);
98
+ }
99
+ if (args.handle._tag === 'None') {
100
+ searchParams.set('offset', '-1');
101
+ }
102
+ else {
103
+ searchParams.set('offset', args.handle.value.offset);
104
+ searchParams.set('handle', args.handle.value.handle);
105
+ searchParams.set('live', 'true');
106
+ }
107
+ const payload = args.payload;
108
+ const url = `${endpointUrl}?${searchParams.toString()}`;
109
+ return { url, storeId: args.storeId, needsInit: args.handle._tag === 'None', payload };
110
+ };
111
+ export const SyncMetadata = Schema.Struct({
112
+ offset: Schema.String,
113
+ // TODO move this into some kind of "global" sync metadata as it's the same for each event
114
+ handle: Schema.String,
115
+ });
116
+ export const makeSyncBackend = ({ endpoint }) => ({ storeId, payload }) => Effect.gen(function* () {
39
117
  const isConnected = yield* SubscriptionRef.make(true);
40
- const initRoom = HttpClientRequest.schemaBodyJson(ApiInitRoomPayload)(HttpClientRequest.post(pushEventEndpoint), ApiInitRoomPayload.make({ roomId })).pipe(Effect.andThen(HttpClient.execute));
41
- // TODO check whether we still need this
42
- const pendingPushDeferredMap = new Map();
43
- const pull = (args) => Effect.gen(function* () {
44
- const url = args._tag === 'None'
45
- ? `${endpointUrl}?offset=-1`
46
- : `${endpointUrl}?offset=${args.value.offset}&shape_id=${args.value.shapeId}&live=true`;
47
- const resp = yield* HttpClient.get(url).pipe(Effect.tapErrorTag('ResponseError', (error) =>
48
- // TODO handle 409 error when the shapeId you request no longer exists for whatever reason.
49
- // The correct behavior here is to refetch the shape from scratch and to reset the local state.
50
- error.response.status === 400 ? initRoom : Effect.fail(error)), Effect.retry({ times: 1 }));
118
+ const pullEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.pull;
119
+ const pushEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.push;
120
+ const pull = (handle) => Effect.gen(function* () {
121
+ const argsJson = yield* Schema.encode(Schema.parseJson(ApiSchema.PullPayload))(ApiSchema.PullPayload.make({ storeId, handle, payload }));
122
+ const url = `${pullEndpoint}?args=${argsJson}`;
123
+ const resp = yield* HttpClient.get(url);
124
+ if (resp.status === 401) {
125
+ const body = yield* resp.text.pipe(Effect.catchAll(() => Effect.succeed('-')));
126
+ return yield* InvalidPullError.make({
127
+ message: `Unauthorized (401): Couldn't connect to ElectricSQL: ${body}`,
128
+ });
129
+ }
130
+ else if (resp.status === 409) {
131
+ // https://electric-sql.com/openapi.html#/paths/~1v1~1shape/get
132
+ // {
133
+ // "message": "The shape associated with this shape_handle and offset was not found. Resync to fetch the latest shape",
134
+ // "shape_handle": "2494_84241",
135
+ // "offset": "-1"
136
+ // }
137
+ // TODO: implementation plan:
138
+ // start pulling events from scratch with the new handle and ignore the "old events"
139
+ // until we found a new event, then, continue with the new handle
140
+ return notYetImplemented(`Electric shape not found`);
141
+ }
142
+ else if (resp.status < 200 || resp.status >= 300) {
143
+ return yield* InvalidPullError.make({
144
+ message: `Unexpected status code: ${resp.status}`,
145
+ });
146
+ }
51
147
  const headers = yield* HttpClientResponse.schemaHeaders(ResponseHeaders)(resp);
52
- const nextCursor = {
53
- offset: headers['x-electric-chunk-last-offset'],
54
- shapeId: headers['x-electric-shape-id'],
148
+ const nextHandle = {
149
+ offset: headers['electric-offset'],
150
+ handle: headers['electric-handle'],
55
151
  };
56
152
  // Electric completes the long-poll request after ~20 seconds with a 204 status
57
153
  // In this case we just retry where we left off
58
154
  if (resp.status === 204) {
59
- return Option.some([Chunk.empty(), Option.some(nextCursor)]);
155
+ return Option.some([Chunk.empty(), Option.some(nextHandle)]);
60
156
  }
61
- const body = yield* HttpClientResponse.schemaBodyJson(Schema.Array(ResponseItem))(resp);
157
+ const body = yield* HttpClientResponse.schemaBodyJson(Schema.Array(ResponseItem), {
158
+ onExcessProperty: 'preserve',
159
+ })(resp);
62
160
  const items = body
63
- .filter((item) => item.value !== undefined)
161
+ .filter((item) => item.value !== undefined && item.headers.operation === 'insert')
64
162
  .map((item) => ({
65
- metadata: Option.some({ offset: item.offset, shapeId: nextCursor.shapeId }),
66
- mutationEventEncoded: {
67
- mutation: item.value.mutation,
68
- args: JSON.parse(item.value.args),
69
- id: item.value.id,
70
- parentId: item.value.parentId,
71
- },
163
+ metadata: Option.some({ offset: nextHandle.offset, handle: nextHandle.handle }),
164
+ eventEncoded: item.value,
72
165
  }));
73
166
  // // TODO implement proper `remaining` handling
74
167
  // remaining: 0,
75
168
  // if (listenForNew === false && items.length === 0) {
76
169
  // return Option.none()
77
170
  // }
78
- const [newItems, pendingPushItems] = Chunk.fromIterable(items).pipe(Chunk.partition((item) => pendingPushDeferredMap.has(item.mutationEventEncoded.id)));
79
- for (const item of pendingPushItems) {
80
- const deferred = pendingPushDeferredMap.get(item.mutationEventEncoded.id);
81
- yield* Deferred.succeed(deferred, Option.getOrThrow(item.metadata));
82
- }
83
- return Option.some([newItems, Option.some(nextCursor)]);
84
- }).pipe(Effect.scoped, Effect.mapError((cause) => InvalidPullError.make({ message: cause.toString() })));
171
+ return Option.some([Chunk.fromIterable(items), Option.some(nextHandle)]);
172
+ }).pipe(Effect.scoped, Effect.mapError((cause) => cause._tag === 'InvalidPullError' ? cause : InvalidPullError.make({ message: cause.toString() })));
173
+ const pullEndpointHasSameOrigin = pullEndpoint.startsWith('/') ||
174
+ (globalThis.location !== undefined && globalThis.location.origin === new URL(pullEndpoint).origin);
85
175
  return {
176
+ // If the pull endpoint has the same origin as the current page, we can assume that we already have a connection
177
+ // otherwise we send a HEAD request to speed up the connection process
178
+ connect: pullEndpointHasSameOrigin
179
+ ? Effect.void
180
+ : HttpClient.head(pullEndpoint).pipe(UnexpectedError.mapToUnexpectedError),
86
181
  pull: (args) => Stream.unfoldChunkEffect(args.pipe(Option.map((_) => _.metadata), Option.flatten), (metadataOption) => pull(metadataOption)).pipe(Stream.chunks, Stream.map((chunk) => ({ batch: [...chunk], remaining: 0 }))),
87
182
  push: (batch) => Effect.gen(function* () {
88
- const deferreds = [];
89
- for (const mutationEventEncoded of batch) {
90
- const deferred = yield* Deferred.make();
91
- pendingPushDeferredMap.set(mutationEventEncoded.id, deferred);
92
- deferreds.push(deferred);
93
- }
94
- const resp = yield* HttpClientRequest.schemaBodyJson(ApiPushEventPayload)(HttpClientRequest.post(pushEventEndpoint), ApiPushEventPayload.make({ roomId, 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() } })));
183
+ const resp = yield* HttpClientRequest.schemaBodyJson(ApiSchema.PushPayload)(HttpClientRequest.post(pushEndpoint), ApiSchema.PushPayload.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
184
  if (!resp.success) {
96
185
  yield* InvalidPushError.make({ reason: { _tag: 'Unexpected', message: 'Push failed' } });
97
186
  }
98
- const metadata = yield* Effect.all(deferreds, { concurrency: 'unbounded' }).pipe(Effect.map((_) => _.map(Option.some)));
99
- for (const mutationEventEncoded of batch) {
100
- pendingPushDeferredMap.delete(mutationEventEncoded.id);
101
- }
102
- return { metadata };
103
187
  }),
104
188
  isConnected,
189
+ metadata: {
190
+ name: '@livestore/sync-electric',
191
+ description: 'LiveStore sync backend implementation using ElectricSQL',
192
+ protocol: 'http',
193
+ endpoint,
194
+ },
105
195
  };
106
196
  });
197
+ /**
198
+ * Needs to be bumped when the storage format changes (e.g. eventlogTable schema changes)
199
+ *
200
+ * Changing this version number will lead to a "soft reset".
201
+ */
202
+ export const PERSISTENCE_FORMAT_VERSION = 6;
203
+ export const toTableName = (storeId) => {
204
+ const escapedStoreId = storeId.replaceAll(/[^a-zA-Z0-9_]/g, '_');
205
+ return `eventlog_${PERSISTENCE_FORMAT_VERSION}_${escapedStoreId}`;
206
+ };
107
207
  //# 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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/sync-electric",
3
- "version": "0.3.0-dev.8",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -10,14 +10,20 @@
10
10
  }
11
11
  },
12
12
  "dependencies": {
13
- "@livestore/common": "0.3.0-dev.8",
14
- "@livestore/utils": "0.3.0-dev.8"
13
+ "@livestore/common": "0.3.0",
14
+ "@livestore/utils": "0.3.0"
15
15
  },
16
16
  "devDependencies": {},
17
+ "files": [
18
+ "package.json",
19
+ "src",
20
+ "dist"
21
+ ],
17
22
  "publishConfig": {
18
23
  "access": "public"
19
24
  },
20
25
  "scripts": {
26
+ "build": "",
21
27
  "test": "echo 'No tests yet'"
22
28
  }
23
29
  }
@@ -0,0 +1,20 @@
1
+ import { LiveStoreEvent } from '@livestore/common/schema'
2
+ import { Schema } from '@livestore/utils/effect'
3
+
4
+ export const PushPayload = Schema.TaggedStruct('@livestore/sync-electric.Push', {
5
+ storeId: Schema.String,
6
+ batch: Schema.Array(LiveStoreEvent.AnyEncodedGlobal),
7
+ }).annotations({ title: '@livestore/sync-electric.PushPayload' })
8
+
9
+ export const PullPayload = Schema.TaggedStruct('@livestore/sync-electric.Pull', {
10
+ storeId: Schema.String,
11
+ payload: Schema.UndefinedOr(Schema.JsonValue),
12
+ handle: Schema.Option(
13
+ Schema.Struct({
14
+ offset: Schema.String,
15
+ handle: Schema.String,
16
+ }),
17
+ ),
18
+ }).annotations({ title: '@livestore/sync-electric.PullPayload' })
19
+
20
+ export const ApiPayload = Schema.Union(PullPayload, PushPayload)