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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,6 +21,7 @@ export declare const PullPayload: Schema.Struct<{
21
21
  offset: typeof Schema.String;
22
22
  handle: typeof Schema.String;
23
23
  }>>;
24
+ live: typeof Schema.Boolean;
24
25
  }>;
25
26
  export declare const ApiPayload: Schema.Union<[Schema.Struct<{
26
27
  _tag: Schema.tag<"@livestore/sync-electric.Pull">;
@@ -31,6 +32,7 @@ export declare const ApiPayload: Schema.Union<[Schema.Struct<{
31
32
  offset: typeof Schema.String;
32
33
  handle: typeof Schema.String;
33
34
  }>>;
35
+ live: typeof Schema.Boolean;
34
36
  }>, Schema.Struct<{
35
37
  _tag: Schema.tag<"@livestore/sync-electric.Push">;
36
38
  } & {
@@ -44,4 +46,15 @@ export declare const ApiPayload: Schema.Union<[Schema.Struct<{
44
46
  sessionId: typeof Schema.String;
45
47
  }>>;
46
48
  }>]>;
49
+ export declare const ArgsSchema: Schema.transform<Schema.transformOrFail<Schema.SchemaClass<string, string, never>, typeof Schema.String, never>, Schema.transform<Schema.SchemaClass<unknown, string, never>, Schema.Struct<{
50
+ _tag: Schema.tag<"@livestore/sync-electric.Pull">;
51
+ } & {
52
+ storeId: typeof Schema.String;
53
+ payload: Schema.UndefinedOr<Schema.Schema<Schema.JsonValue, Schema.JsonValue, never>>;
54
+ handle: Schema.Option<Schema.Struct<{
55
+ offset: typeof Schema.String;
56
+ handle: typeof Schema.String;
57
+ }>>;
58
+ live: typeof Schema.Boolean;
59
+ }>>>;
47
60
  //# sourceMappingURL=api-schema.d.ts.map
@@ -1 +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"}
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;;;;;;;;;;EAUyC,CAAA;AAEjE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;IAAyC,CAAA;AAGhE,eAAO,MAAM,UAAU;;;;;;;;;;IAA+E,CAAA"}
@@ -2,7 +2,7 @@ import { LiveStoreEvent } from '@livestore/common/schema';
2
2
  import { Schema } from '@livestore/utils/effect';
3
3
  export const PushPayload = Schema.TaggedStruct('@livestore/sync-electric.Push', {
4
4
  storeId: Schema.String,
5
- batch: Schema.Array(LiveStoreEvent.AnyEncodedGlobal),
5
+ batch: Schema.Array(LiveStoreEvent.Global.Encoded),
6
6
  }).annotations({ title: '@livestore/sync-electric.PushPayload' });
7
7
  export const PullPayload = Schema.TaggedStruct('@livestore/sync-electric.Pull', {
8
8
  storeId: Schema.String,
@@ -11,6 +11,9 @@ export const PullPayload = Schema.TaggedStruct('@livestore/sync-electric.Pull',
11
11
  offset: Schema.String,
12
12
  handle: Schema.String,
13
13
  })),
14
+ live: Schema.Boolean,
14
15
  }).annotations({ title: '@livestore/sync-electric.PullPayload' });
15
16
  export const ApiPayload = Schema.Union(PullPayload, PushPayload);
17
+ // Format for the query params
18
+ export const ArgsSchema = Schema.compose(Schema.StringFromUriComponent, Schema.parseJson(PullPayload));
16
19
  //# sourceMappingURL=api-schema.js.map
@@ -1 +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"}
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,MAAM,CAAC,OAAO,CAAC;CACnD,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;IACD,IAAI,EAAE,MAAM,CAAC,OAAO;CACrB,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;AAEhE,8BAA8B;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,33 +1,16 @@
1
- import type { SyncBackendConstructor } from '@livestore/common';
2
- import { Schema } from '@livestore/utils/effect';
1
+ import { SyncBackend } from '@livestore/common';
2
+ import { type Duration, Schema } from '@livestore/utils/effect';
3
+ declare const InvalidOperationError_base: Schema.TaggedErrorClass<InvalidOperationError, "InvalidOperationError", {
4
+ readonly _tag: Schema.tag<"InvalidOperationError">;
5
+ } & {
6
+ operation: Schema.Literal<["delete", "update"]>;
7
+ message: typeof Schema.String;
8
+ }>;
9
+ export declare class InvalidOperationError extends InvalidOperationError_base {
10
+ }
3
11
  export * as ApiSchema from './api-schema.ts';
4
- export declare const syncBackend: any;
12
+ export * from './make-electric-url.ts';
5
13
  export declare const syncBackendOptions: <TOptions extends SyncBackendOptions>(options: TOptions) => TOptions;
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;
12
- /**
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
17
- */
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
14
  export interface SyncBackendOptions {
32
15
  /**
33
16
  * The endpoint to pull/push events. Pull is a `GET` request, push is a `POST` request.
@@ -40,22 +23,29 @@ export interface SyncBackendOptions {
40
23
  endpoint: string | {
41
24
  push: string;
42
25
  pull: string;
26
+ ping: string;
27
+ };
28
+ ping?: {
29
+ /**
30
+ * @default true
31
+ */
32
+ enabled?: boolean;
33
+ /**
34
+ * How long to wait for a ping response before timing out
35
+ * @default 10 seconds
36
+ */
37
+ requestTimeout?: Duration.DurationInput;
38
+ /**
39
+ * How often to send ping requests
40
+ * @default 10 seconds
41
+ */
42
+ requestInterval?: Duration.DurationInput;
43
43
  };
44
44
  }
45
45
  export declare const SyncMetadata: Schema.Struct<{
46
46
  offset: typeof Schema.String;
47
47
  handle: typeof Schema.String;
48
48
  }>;
49
- type SyncMetadata = {
50
- offset: string;
51
- handle: string;
52
- };
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;
49
+ export type SyncMetadata = typeof SyncMetadata.Type;
50
+ export declare const makeSyncBackend: ({ endpoint, ...options }: SyncBackendOptions) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
61
51
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2D,WAAW,EAAgB,MAAM,mBAAmB,CAAA;AAGtH,OAAO,EACL,KAAK,QAAQ,EAQb,MAAM,EAGP,MAAM,yBAAyB,CAAA;;;;;;;AAIhC,qBAAa,qBAAsB,SAAQ,0BAGzC;CAAG;AAEL,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AAkFtC,eAAO,MAAM,kBAAkB,GAAI,QAAQ,SAAS,kBAAkB,EAAE,SAAS,QAAQ,aAAY,CAAA;AAErG,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,QAAQ,EACJ,MAAM,GACN;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IAEL,IAAI,CAAC,EAAE;QACL;;WAEG;QACH,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB;;;WAGG;QACH,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;QACvC;;;WAGG;QACH,eAAe,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAA;KACzC,CAAA;CACF;AAED,eAAO,MAAM,YAAY;;;EAIvB,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD,eAAO,MAAM,eAAe,GACzB,0BAA0B,kBAAkB,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CA2M3F,CAAA"}
package/dist/index.js CHANGED
@@ -1,9 +1,15 @@
1
- import { InvalidPullError, InvalidPushError, UnexpectedError } from '@livestore/common';
1
+ import { InvalidPullError, InvalidPushError, SyncBackend, UnknownError } from '@livestore/common';
2
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';
3
+ import { notYetImplemented } from '@livestore/utils';
4
+ import { Effect, HttpClient, HttpClientRequest, HttpClientResponse, Option, ReadonlyArray, Schedule, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
5
5
  import * as ApiSchema from "./api-schema.js";
6
+ export class InvalidOperationError extends Schema.TaggedError()('InvalidOperationError', {
7
+ operation: Schema.Literal('delete', 'update'),
8
+ message: Schema.String,
9
+ }) {
10
+ }
6
11
  export * as ApiSchema from "./api-schema.js";
12
+ export * from "./make-electric-url.js";
7
13
  /*
8
14
  Example data:
9
15
 
@@ -50,83 +56,60 @@ const LiveStoreEventGlobalFromStringRecord = Schema.Struct({
50
56
  args: Schema.parseJson(Schema.Any),
51
57
  clientId: Schema.String,
52
58
  sessionId: Schema.String,
53
- }).pipe(Schema.transform(LiveStoreEvent.AnyEncodedGlobal, {
54
- decode: (_) => _,
55
- encode: (_) => _,
56
- }));
57
- const ResponseItem = Schema.Struct({
59
+ })
60
+ .pipe(Schema.compose(LiveStoreEvent.Global.Encoded))
61
+ .annotations({ title: '@livestore/sync-electric:LiveStoreEventGlobalFromStringRecord' });
62
+ const ResponseItemInsert = Schema.Struct({
58
63
  /** Postgres path (e.g. `"public"."events_9069baf0_b3e6_42f7_980f_188416eab3fx3"/"0"`) */
59
64
  key: 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
- })),
67
- });
65
+ value: LiveStoreEventGlobalFromStringRecord,
66
+ headers: Schema.Struct({ operation: Schema.Literal('insert'), relation: Schema.Array(Schema.String) }),
67
+ }).annotations({ title: '@livestore/sync-electric:ResponseItemInsert' });
68
+ const ResponseItemInvalid = Schema.Struct({
69
+ /** Postgres path (e.g. `"public"."events_9069baf0_b3e6_42f7_980f_188416eab3fx3"/"0"`) */
70
+ key: Schema.optional(Schema.String),
71
+ value: Schema.Any,
72
+ headers: Schema.Struct({ operation: Schema.Literal('update', 'delete'), relation: Schema.Array(Schema.String) }),
73
+ }).annotations({ title: '@livestore/sync-electric:ResponseItemInvalid' });
74
+ const ResponseItemControl = Schema.Struct({
75
+ key: Schema.optional(Schema.String),
76
+ value: Schema.optional(Schema.Any),
77
+ headers: Schema.Struct({ control: Schema.String }),
78
+ }).annotations({ title: '@livestore/sync-electric:ResponseItemControl' });
79
+ const ResponseItem = Schema.Union(ResponseItemInsert, ResponseItemInvalid, ResponseItemControl);
68
80
  const ResponseHeaders = Schema.Struct({
69
81
  'electric-handle': Schema.String,
70
82
  // 'electric-schema': Schema.parseJson(Schema.Any),
71
83
  /** e.g. 26799576_0 */
72
84
  'electric-offset': Schema.String,
73
85
  });
74
- export const syncBackend = {};
75
86
  export const syncBackendOptions = (options) => options;
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
87
  export const SyncMetadata = Schema.Struct({
112
88
  offset: Schema.String,
113
89
  // TODO move this into some kind of "global" sync metadata as it's the same for each event
114
90
  handle: Schema.String,
115
91
  });
116
- export const makeSyncBackend = ({ endpoint }) => ({ storeId, payload }) => Effect.gen(function* () {
117
- const isConnected = yield* SubscriptionRef.make(true);
92
+ export const makeSyncBackend = ({ endpoint, ...options }) => ({ storeId, payload }) => Effect.gen(function* () {
93
+ const isConnected = yield* SubscriptionRef.make(false);
118
94
  const pullEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.pull;
119
95
  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 }));
96
+ const pingEndpoint = typeof endpoint === 'string' ? endpoint : endpoint.ping;
97
+ const httpClient = yield* HttpClient.HttpClient;
98
+ const runPull = (handle, { live }) => Effect.gen(function* () {
99
+ const argsJson = yield* Schema.encode(ApiSchema.ArgsSchema)(ApiSchema.PullPayload.make({ storeId, handle, payload, live }));
122
100
  const url = `${pullEndpoint}?args=${argsJson}`;
123
- const resp = yield* HttpClient.get(url);
101
+ const resp = yield* httpClient.get(url);
124
102
  if (resp.status === 401) {
125
103
  const body = yield* resp.text.pipe(Effect.catchAll(() => Effect.succeed('-')));
126
104
  return yield* InvalidPullError.make({
127
- message: `Unauthorized (401): Couldn't connect to ElectricSQL: ${body}`,
105
+ cause: new Error(`Unauthorized (401): Couldn't connect to ElectricSQL: ${body}`),
128
106
  });
129
107
  }
108
+ else if (resp.status === 400) {
109
+ // Electric returns 400 when table doesn't exist
110
+ // Return empty result for non-existent tables
111
+ return Option.some([[], Option.none()]);
112
+ }
130
113
  else if (resp.status === 409) {
131
114
  // https://electric-sql.com/openapi.html#/paths/~1v1~1shape/get
132
115
  // {
@@ -140,8 +123,9 @@ export const makeSyncBackend = ({ endpoint }) => ({ storeId, payload }) => Effec
140
123
  return notYetImplemented(`Electric shape not found`);
141
124
  }
142
125
  else if (resp.status < 200 || resp.status >= 300) {
126
+ const body = yield* resp.text;
143
127
  return yield* InvalidPullError.make({
144
- message: `Unexpected status code: ${resp.status}`,
128
+ cause: new Error(`Unexpected status code: ${resp.status}: ${body}`),
145
129
  });
146
130
  }
147
131
  const headers = yield* HttpClientResponse.schemaHeaders(ResponseHeaders)(resp);
@@ -152,39 +136,77 @@ export const makeSyncBackend = ({ endpoint }) => ({ storeId, payload }) => Effec
152
136
  // Electric completes the long-poll request after ~20 seconds with a 204 status
153
137
  // In this case we just retry where we left off
154
138
  if (resp.status === 204) {
155
- return Option.some([Chunk.empty(), Option.some(nextHandle)]);
139
+ return Option.some([[], Option.some(nextHandle)]);
156
140
  }
157
- const body = yield* HttpClientResponse.schemaBodyJson(Schema.Array(ResponseItem), {
141
+ const allItems = yield* HttpClientResponse.schemaBodyJson(Schema.Array(ResponseItem), {
158
142
  onExcessProperty: 'preserve',
159
143
  })(resp);
160
- const items = body
161
- .filter((item) => item.value !== undefined && item.headers.operation === 'insert')
162
- .map((item) => ({
144
+ // Check for delete/update operations and throw descriptive error
145
+ const invalidOperations = ReadonlyArray.filterMap(allItems, (item) => Schema.is(ResponseItemInvalid)(item) ? Option.some(item.headers.operation) : Option.none());
146
+ if (invalidOperations.length > 0) {
147
+ const operation = invalidOperations[0];
148
+ return yield* new InvalidOperationError({
149
+ operation,
150
+ message: `ElectricSQL '${operation}' event received. This results from directly mutating the event log. Append a series of events that produce the desired state instead of mutating the event log.`,
151
+ });
152
+ }
153
+ const items = allItems.filter(Schema.is(ResponseItemInsert)).map((item) => ({
163
154
  metadata: Option.some({ offset: nextHandle.offset, handle: nextHandle.handle }),
164
155
  eventEncoded: item.value,
165
156
  }));
166
- // // TODO implement proper `remaining` handling
167
- // remaining: 0,
168
- // if (listenForNew === false && items.length === 0) {
169
- // return Option.none()
170
- // }
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() })));
157
+ yield* Effect.annotateCurrentSpan({ itemsCount: items.length, nextHandle });
158
+ return Option.some([items, Option.some(nextHandle)]);
159
+ }).pipe(Effect.scoped, Effect.mapError((cause) => (cause._tag === 'InvalidPullError' ? cause : InvalidPullError.make({ cause }))), Effect.withSpan('electric-provider:runPull', { attributes: { handle, live } }));
173
160
  const pullEndpointHasSameOrigin = pullEndpoint.startsWith('/') ||
174
161
  (globalThis.location !== undefined && globalThis.location.origin === new URL(pullEndpoint).origin);
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),
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 }))),
162
+ const pingTimeout = options.ping?.requestTimeout ?? 10_000;
163
+ const ping = Effect.gen(function* () {
164
+ yield* httpClient.pipe(HttpClient.filterStatusOk).head(pingEndpoint);
165
+ yield* SubscriptionRef.set(isConnected, true);
166
+ }).pipe(UnknownError.mapToUnknownError, Effect.timeout(pingTimeout), Effect.catchTag('TimeoutException', () => SubscriptionRef.set(isConnected, false)), Effect.withSpan('electric-provider:ping'));
167
+ const pingInterval = options.ping?.requestInterval ?? 10_000;
168
+ if (options.ping?.enabled !== false) {
169
+ // Automatically ping the server to keep the connection alive
170
+ yield* ping.pipe(Effect.repeat(Schedule.spaced(pingInterval)), Effect.tapCauseLogPretty, Effect.forkScoped);
171
+ }
172
+ // If the pull endpoint has the same origin as the current page, we can assume that we already have a connection
173
+ // otherwise we send a HEAD request to speed up the connection process
174
+ const connect = pullEndpointHasSameOrigin
175
+ ? Effect.void
176
+ : ping.pipe(UnknownError.mapToUnknownError);
177
+ return SyncBackend.of({
178
+ connect,
179
+ pull: (cursor, options) => {
180
+ let hasEmittedAtLeastOnce = false;
181
+ return Stream.unfoldEffect(cursor.pipe(Option.flatMap((_) => _.metadata)), (metadataOption) => Effect.gen(function* () {
182
+ const result = yield* runPull(metadataOption, { live: options?.live ?? false });
183
+ if (Option.isNone(result))
184
+ return Option.none();
185
+ const [batch, nextMetadataOption] = result.value;
186
+ // Continue pagination if we have data
187
+ if (batch.length > 0) {
188
+ hasEmittedAtLeastOnce = true;
189
+ return Option.some([{ batch, hasMore: true }, nextMetadataOption]);
190
+ }
191
+ // Make sure we emit at least once even if there's no data or we're live-pulling
192
+ if (hasEmittedAtLeastOnce === false || options?.live) {
193
+ hasEmittedAtLeastOnce = true;
194
+ return Option.some([{ batch, hasMore: false }, nextMetadataOption]);
195
+ }
196
+ // Stop on empty batch (when not live)
197
+ return Option.none();
198
+ })).pipe(Stream.map(({ batch, hasMore }) => ({
199
+ batch,
200
+ pageInfo: hasMore ? SyncBackend.pageInfoMoreUnknown : SyncBackend.pageInfoNoMore,
201
+ })), Stream.withSpan('electric-provider:pull'));
202
+ },
182
203
  push: (batch) => Effect.gen(function* () {
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() } })));
204
+ const resp = yield* HttpClientRequest.schemaBodyJson(ApiSchema.PushPayload)(HttpClientRequest.post(pushEndpoint), ApiSchema.PushPayload.make({ storeId, batch })).pipe(Effect.andThen(httpClient.pipe(HttpClient.filterStatusOk).execute), Effect.andThen(HttpClientResponse.schemaBodyJson(Schema.Struct({ success: Schema.Boolean }))), Effect.scoped, Effect.mapError((cause) => InvalidPushError.make({ cause: UnknownError.make({ cause }) })));
184
205
  if (!resp.success) {
185
- yield* InvalidPushError.make({ reason: { _tag: 'Unexpected', message: 'Push failed' } });
206
+ return yield* InvalidPushError.make({ cause: new UnknownError({ cause: new Error('Push failed') }) });
186
207
  }
187
- }),
208
+ }).pipe(Effect.withSpan('electric-provider:push')),
209
+ ping,
188
210
  isConnected,
189
211
  metadata: {
190
212
  name: '@livestore/sync-electric',
@@ -192,16 +214,12 @@ export const makeSyncBackend = ({ endpoint }) => ({ storeId, payload }) => Effec
192
214
  protocol: 'http',
193
215
  endpoint,
194
216
  },
195
- };
217
+ supports: {
218
+ // Given Electric is heavily optimized for immutable caching, we can't know the remaining count
219
+ // until we've reached the end of the stream
220
+ pullPageInfoKnown: false,
221
+ pullLive: true,
222
+ },
223
+ });
196
224
  });
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
- };
207
225
  //# 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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"}
@@ -0,0 +1,61 @@
1
+ import { Schema } from '@livestore/utils/effect';
2
+ /**
3
+ * This function should be called in a trusted environment (e.g. a proxy server) as it
4
+ * requires access to senstive information (e.g. `apiSecret` / `sourceSecret`).
5
+ */
6
+ export declare const makeElectricUrl: ({ electricHost, searchParams: providedSearchParams, sourceId, sourceSecret, apiSecret, }: {
7
+ electricHost: string;
8
+ /**
9
+ * Needed to extract information from the search params which the `@livestore/sync-electric`
10
+ * client implementation automatically adds:
11
+ * - `handle`: the ElectricSQL handle
12
+ * - `storeId`: the Livestore storeId
13
+ */
14
+ searchParams: URLSearchParams;
15
+ /** Needed for Electric Cloud */
16
+ sourceId?: string;
17
+ /** Needed for Electric Cloud */
18
+ sourceSecret?: string;
19
+ /** For self-hosted ElectricSQL */
20
+ apiSecret?: string;
21
+ }) => {
22
+ /**
23
+ * The URL to the ElectricSQL API endpoint with needed search params.
24
+ */
25
+ url: string;
26
+ /** The Livestore storeId */
27
+ storeId: string;
28
+ /**
29
+ * Whether the Postgres table needs to be created.
30
+ */
31
+ needsInit: boolean;
32
+ /** Sync payload provided by the client */
33
+ payload: Schema.JsonValue | undefined;
34
+ };
35
+ export declare const toTableName: (storeId: string) => string;
36
+ /**
37
+ * CRITICAL: Increment this version whenever you modify the Postgres table schema structure.
38
+ *
39
+ * Bump required when:
40
+ * - Adding/removing/renaming columns in the eventlog table (see examples/web-todomvc-sync-electric/src/server/db.ts)
41
+ * - Changing column types or constraints
42
+ * - Modifying primary keys or indexes
43
+ *
44
+ * Bump NOT required when:
45
+ * - Changing query patterns or fetch logic
46
+ * - Adding new tables (as long as existing table schema remains unchanged)
47
+ * - Updating client-side implementation details
48
+ *
49
+ * Impact: Changing this version triggers a "soft reset" - new table names are created
50
+ * and old data becomes inaccessible (but remains in the database).
51
+ *
52
+ * Current schema (PostgreSQL):
53
+ * - seqNum (INTEGER PRIMARY KEY)
54
+ * - parentSeqNum (INTEGER)
55
+ * - name (TEXT NOT NULL)
56
+ * - args (JSONB NOT NULL)
57
+ * - clientId (TEXT NOT NULL)
58
+ * - sessionId (TEXT NOT NULL)
59
+ */
60
+ export declare const PERSISTENCE_FORMAT_VERSION = 6;
61
+ //# sourceMappingURL=make-electric-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-electric-url.d.ts","sourceRoot":"","sources":["../src/make-electric-url.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGtD;;;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,KAAG;IACF;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf;;OAEG;IACH,SAAS,EAAE,OAAO,CAAA;IAClB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAA;CA4CtC,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,WAe1C,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAA"}
@@ -0,0 +1,79 @@
1
+ import { shouldNeverHappen } from '@livestore/utils';
2
+ import { Hash, Schema } from '@livestore/utils/effect';
3
+ import * as ApiSchema from "./api-schema.js";
4
+ /**
5
+ * This function should be called in a trusted environment (e.g. a proxy server) as it
6
+ * requires access to senstive information (e.g. `apiSecret` / `sourceSecret`).
7
+ */
8
+ export const makeElectricUrl = ({ electricHost, searchParams: providedSearchParams, sourceId, sourceSecret, apiSecret, }) => {
9
+ const endpointUrl = `${electricHost}/v1/shape`;
10
+ const UrlParamsSchema = Schema.Struct({ args: ApiSchema.ArgsSchema });
11
+ const argsResult = Schema.decodeUnknownEither(UrlParamsSchema)(Object.fromEntries(providedSearchParams.entries()));
12
+ if (argsResult._tag === 'Left') {
13
+ return shouldNeverHappen('Invalid search params provided to makeElectricUrl', providedSearchParams, Object.fromEntries(providedSearchParams.entries()));
14
+ }
15
+ const args = argsResult.right.args;
16
+ const tableName = toTableName(args.storeId);
17
+ // TODO refactor with Effect URLSearchParams schema
18
+ // https://electric-sql.com/openapi.html
19
+ const searchParams = new URLSearchParams();
20
+ // Electric requires table names with capital letters to be quoted
21
+ // Since our table names include the storeId which may have capitals, we always quote
22
+ searchParams.set('table', `"${tableName}"`);
23
+ if (sourceId !== undefined) {
24
+ searchParams.set('source_id', sourceId);
25
+ }
26
+ if (sourceSecret !== undefined) {
27
+ searchParams.set('source_secret', sourceSecret);
28
+ }
29
+ if (apiSecret !== undefined) {
30
+ searchParams.set('api_secret', apiSecret);
31
+ }
32
+ if (args.handle._tag === 'None') {
33
+ searchParams.set('offset', '-1');
34
+ }
35
+ else {
36
+ searchParams.set('offset', args.handle.value.offset);
37
+ searchParams.set('handle', args.handle.value.handle);
38
+ searchParams.set('live', args.live ? 'true' : 'false');
39
+ }
40
+ const payload = args.payload;
41
+ const url = `${endpointUrl}?${searchParams.toString()}`;
42
+ return { url, storeId: args.storeId, needsInit: args.handle._tag === 'None', payload };
43
+ };
44
+ export const toTableName = (storeId) => {
45
+ const escapedStoreId = storeId.replaceAll(/[^a-zA-Z0-9_]/g, '_');
46
+ const tableName = `eventlog_${PERSISTENCE_FORMAT_VERSION}_${escapedStoreId}`;
47
+ if (tableName.length > 63) {
48
+ const hashedStoreId = Hash.string(storeId);
49
+ console.warn(`Table name is too long: "${tableName}". Postgres table names are limited to 63 characters. Using hashed storeId instead: "${hashedStoreId}".`);
50
+ return `eventlog_${PERSISTENCE_FORMAT_VERSION}_hash_${hashedStoreId}`;
51
+ }
52
+ return tableName;
53
+ };
54
+ /**
55
+ * CRITICAL: Increment this version whenever you modify the Postgres table schema structure.
56
+ *
57
+ * Bump required when:
58
+ * - Adding/removing/renaming columns in the eventlog table (see examples/web-todomvc-sync-electric/src/server/db.ts)
59
+ * - Changing column types or constraints
60
+ * - Modifying primary keys or indexes
61
+ *
62
+ * Bump NOT required when:
63
+ * - Changing query patterns or fetch logic
64
+ * - Adding new tables (as long as existing table schema remains unchanged)
65
+ * - Updating client-side implementation details
66
+ *
67
+ * Impact: Changing this version triggers a "soft reset" - new table names are created
68
+ * and old data becomes inaccessible (but remains in the database).
69
+ *
70
+ * Current schema (PostgreSQL):
71
+ * - seqNum (INTEGER PRIMARY KEY)
72
+ * - parentSeqNum (INTEGER)
73
+ * - name (TEXT NOT NULL)
74
+ * - args (JSONB NOT NULL)
75
+ * - clientId (TEXT NOT NULL)
76
+ * - sessionId (TEXT NOT NULL)
77
+ */
78
+ export const PERSISTENCE_FORMAT_VERSION = 6;
79
+ //# sourceMappingURL=make-electric-url.js.map