@livestore/sync-cf 0.4.0-dev.8 → 0.4.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/README.md +7 -8
- package/dist/.tsbuildinfo +1 -1
- package/dist/cf-worker/do/durable-object.d.ts +1 -1
- package/dist/cf-worker/do/durable-object.d.ts.map +1 -1
- package/dist/cf-worker/do/durable-object.js +15 -14
- package/dist/cf-worker/do/durable-object.js.map +1 -1
- package/dist/cf-worker/do/layer.d.ts +6 -6
- package/dist/cf-worker/do/layer.d.ts.map +1 -1
- package/dist/cf-worker/do/layer.js +32 -9
- package/dist/cf-worker/do/layer.js.map +1 -1
- package/dist/cf-worker/do/pull.d.ts +8 -3
- package/dist/cf-worker/do/pull.d.ts.map +1 -1
- package/dist/cf-worker/do/pull.js +22 -10
- package/dist/cf-worker/do/pull.js.map +1 -1
- package/dist/cf-worker/do/push.d.ts +5 -4
- package/dist/cf-worker/do/push.d.ts.map +1 -1
- package/dist/cf-worker/do/push.js +80 -41
- package/dist/cf-worker/do/push.js.map +1 -1
- package/dist/cf-worker/do/sqlite.d.ts +10 -1
- package/dist/cf-worker/do/sqlite.d.ts.map +1 -1
- package/dist/cf-worker/do/sqlite.js +13 -4
- package/dist/cf-worker/do/sqlite.js.map +1 -1
- package/dist/cf-worker/do/sync-storage.d.ts +14 -9
- package/dist/cf-worker/do/sync-storage.d.ts.map +1 -1
- package/dist/cf-worker/do/sync-storage.js +92 -18
- package/dist/cf-worker/do/sync-storage.js.map +1 -1
- package/dist/cf-worker/do/transport/do-rpc-server.d.ts +2 -1
- package/dist/cf-worker/do/transport/do-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/do-rpc-server.js +13 -7
- package/dist/cf-worker/do/transport/do-rpc-server.js.map +1 -1
- package/dist/cf-worker/do/transport/http-rpc-server.d.ts +3 -1
- package/dist/cf-worker/do/transport/http-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/http-rpc-server.js +24 -15
- package/dist/cf-worker/do/transport/http-rpc-server.js.map +1 -1
- package/dist/cf-worker/do/transport/ws-rpc-server.d.ts +2 -1
- package/dist/cf-worker/do/transport/ws-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/ws-rpc-server.js +30 -8
- package/dist/cf-worker/do/transport/ws-rpc-server.js.map +1 -1
- package/dist/cf-worker/shared.d.ts +123 -30
- package/dist/cf-worker/shared.d.ts.map +1 -1
- package/dist/cf-worker/shared.js +50 -6
- package/dist/cf-worker/shared.js.map +1 -1
- package/dist/cf-worker/worker.d.ts +64 -71
- package/dist/cf-worker/worker.d.ts.map +1 -1
- package/dist/cf-worker/worker.js +70 -48
- package/dist/cf-worker/worker.js.map +1 -1
- package/dist/client/transport/do-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/do-rpc-client.js +27 -10
- package/dist/client/transport/do-rpc-client.js.map +1 -1
- package/dist/client/transport/http-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/http-rpc-client.js +29 -9
- package/dist/client/transport/http-rpc-client.js.map +1 -1
- package/dist/client/transport/ws-rpc-client.d.ts +2 -1
- package/dist/client/transport/ws-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/ws-rpc-client.js +31 -17
- package/dist/client/transport/ws-rpc-client.js.map +1 -1
- package/dist/common/constants.d.ts +7 -0
- package/dist/common/constants.d.ts.map +1 -0
- package/dist/common/constants.js +17 -0
- package/dist/common/constants.js.map +1 -0
- package/dist/common/do-rpc-schema.d.ts +6 -6
- package/dist/common/do-rpc-schema.d.ts.map +1 -1
- package/dist/common/do-rpc-schema.js +4 -4
- package/dist/common/do-rpc-schema.js.map +1 -1
- package/dist/common/http-rpc-schema.d.ts +4 -4
- package/dist/common/http-rpc-schema.d.ts.map +1 -1
- package/dist/common/http-rpc-schema.js +4 -4
- package/dist/common/http-rpc-schema.js.map +1 -1
- package/dist/common/mod.d.ts +4 -1
- package/dist/common/mod.d.ts.map +1 -1
- package/dist/common/mod.js +4 -1
- package/dist/common/mod.js.map +1 -1
- package/dist/common/sync-message-types.d.ts +2 -2
- package/dist/common/sync-message-types.js +3 -3
- package/dist/common/sync-message-types.js.map +1 -1
- package/dist/common/ws-rpc-schema.d.ts +3 -3
- package/dist/common/ws-rpc-schema.d.ts.map +1 -1
- package/dist/common/ws-rpc-schema.js +3 -3
- package/dist/common/ws-rpc-schema.js.map +1 -1
- package/package.json +72 -14
- package/src/cf-worker/do/durable-object.ts +23 -18
- package/src/cf-worker/do/layer.ts +35 -13
- package/src/cf-worker/do/pull.ts +43 -14
- package/src/cf-worker/do/push.ts +107 -46
- package/src/cf-worker/do/sqlite.ts +14 -4
- package/src/cf-worker/do/sync-storage.ts +151 -31
- package/src/cf-worker/do/transport/do-rpc-server.ts +22 -9
- package/src/cf-worker/do/transport/http-rpc-server.ts +33 -13
- package/src/cf-worker/do/transport/ws-rpc-server.ts +40 -12
- package/src/cf-worker/shared.ts +149 -25
- package/src/cf-worker/worker.ts +138 -108
- package/src/client/transport/do-rpc-client.ts +41 -17
- package/src/client/transport/http-rpc-client.ts +43 -17
- package/src/client/transport/ws-rpc-client.ts +42 -19
- package/src/common/constants.ts +18 -0
- package/src/common/do-rpc-schema.ts +5 -4
- package/src/common/http-rpc-schema.ts +5 -4
- package/src/common/mod.ts +4 -2
- package/src/common/sync-message-types.ts +3 -3
- package/src/common/ws-rpc-schema.ts +4 -3
|
@@ -1,23 +1,78 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UnknownError } from '@livestore/common';
|
|
2
2
|
import type { CfTypes } from '@livestore/common-cf';
|
|
3
|
-
import { Effect,
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { Effect, Schema } from '@livestore/utils/effect';
|
|
4
|
+
import type { SearchParams } from '../common/mod.ts';
|
|
5
|
+
import { SyncMessage } from '../common/mod.ts';
|
|
6
|
+
export type Env = {};
|
|
7
|
+
/** Headers forwarded from the request to callbacks */
|
|
8
|
+
export type ForwardedHeaders = ReadonlyMap<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for forwarding request headers to DO callbacks.
|
|
11
|
+
* - `string[]`: List of header names to forward (case-insensitive)
|
|
12
|
+
* - `(request) => Record<string, string>`: Custom extraction function (sync)
|
|
13
|
+
*/
|
|
14
|
+
export type ForwardHeadersOption = readonly string[] | ((request: CfTypes.Request) => Record<string, string>);
|
|
15
|
+
/** Context passed to onPush/onPull callbacks */
|
|
16
|
+
export type CallbackContext = {
|
|
17
|
+
storeId: StoreId;
|
|
18
|
+
payload?: Schema.JsonValue;
|
|
19
|
+
/** Headers forwarded from the request (only present if `forwardHeaders` is configured) */
|
|
20
|
+
headers?: ForwardedHeaders;
|
|
21
|
+
};
|
|
10
22
|
export type MakeDurableObjectClassOptions = {
|
|
11
|
-
onPush?: (message: SyncMessage.PushRequest, context:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
onPush?: (message: SyncMessage.PushRequest, context: CallbackContext) => Effect.SyncOrPromiseOrEffect<void>;
|
|
24
|
+
onPushRes?: (message: SyncMessage.PushAck | UnknownError) => Effect.SyncOrPromiseOrEffect<void>;
|
|
25
|
+
onPull?: (message: SyncMessage.PullRequest, context: CallbackContext) => Effect.SyncOrPromiseOrEffect<void>;
|
|
26
|
+
onPullRes?: (message: SyncMessage.PullResponse | UnknownError) => Effect.SyncOrPromiseOrEffect<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Forward request headers to `onPush`/`onPull` callbacks for authentication.
|
|
29
|
+
*
|
|
30
|
+
* This enables cookie-based or header-based authentication patterns where
|
|
31
|
+
* you need access to request headers inside the Durable Object.
|
|
32
|
+
*
|
|
33
|
+
* @example Forward specific headers by name (case-insensitive)
|
|
34
|
+
* ```ts
|
|
35
|
+
* makeDurableObject({
|
|
36
|
+
* forwardHeaders: ['cookie', 'authorization'],
|
|
37
|
+
* onPush: async (message, { headers }) => {
|
|
38
|
+
* const cookie = headers?.get('cookie')
|
|
39
|
+
* const session = await validateSession(cookie)
|
|
40
|
+
* },
|
|
41
|
+
* })
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Custom extraction function for derived values
|
|
45
|
+
* ```ts
|
|
46
|
+
* makeDurableObject({
|
|
47
|
+
* forwardHeaders: (request) => ({
|
|
48
|
+
* 'x-user-id': request.headers.get('x-user-id') ?? '',
|
|
49
|
+
* 'x-session': request.headers.get('cookie')?.split('session=')[1]?.split(';')[0] ?? '',
|
|
50
|
+
* }),
|
|
51
|
+
* onPush: async (message, { headers }) => {
|
|
52
|
+
* const userId = headers?.get('x-user-id')
|
|
53
|
+
* },
|
|
54
|
+
* })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
forwardHeaders?: ForwardHeadersOption;
|
|
58
|
+
/**
|
|
59
|
+
* Storage engine for event persistence.
|
|
60
|
+
* - Default: `{ _tag: 'do-sqlite' }` (Durable Object SQLite)
|
|
61
|
+
* - D1: `{ _tag: 'd1', binding: string }` where `binding` is the D1 binding name in wrangler.toml.
|
|
62
|
+
*
|
|
63
|
+
* If omitted, the runtime defaults to DO SQLite. For backwards-compatibility, if an env binding named
|
|
64
|
+
* `DB` exists and looks like a D1Database, D1 will be used.
|
|
65
|
+
*
|
|
66
|
+
* Trade-offs:
|
|
67
|
+
* - DO SQLite: simpler deploy, data co-located with DO, not externally queryable
|
|
68
|
+
* - D1: centralized DB, inspectable with DB tools, extra network hop and JSON size limits
|
|
69
|
+
*/
|
|
70
|
+
storage?: {
|
|
71
|
+
_tag: 'do-sqlite';
|
|
72
|
+
} | {
|
|
73
|
+
_tag: 'd1';
|
|
74
|
+
binding: string;
|
|
75
|
+
};
|
|
21
76
|
/**
|
|
22
77
|
* Enabled transports for sync backend
|
|
23
78
|
* - `http`: HTTP JSON-RPC
|
|
@@ -27,6 +82,25 @@ export type MakeDurableObjectClassOptions = {
|
|
|
27
82
|
* @default Set(['http', 'ws', 'do-rpc'])
|
|
28
83
|
*/
|
|
29
84
|
enabledTransports?: Set<'http' | 'ws' | 'do-rpc'>;
|
|
85
|
+
/**
|
|
86
|
+
* Custom HTTP response headers for HTTP transport
|
|
87
|
+
* These headers will be added to all HTTP RPC responses (Pull, Push, Ping)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* {
|
|
92
|
+
* http: {
|
|
93
|
+
* responseHeaders: {
|
|
94
|
+
* 'Access-Control-Allow-Origin': '*',
|
|
95
|
+
* 'Cache-Control': 'no-cache'
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
http?: {
|
|
102
|
+
responseHeaders?: Record<string, string>;
|
|
103
|
+
};
|
|
30
104
|
otel?: {
|
|
31
105
|
baseUrl?: string;
|
|
32
106
|
serviceName?: string;
|
|
@@ -35,24 +109,34 @@ export type MakeDurableObjectClassOptions = {
|
|
|
35
109
|
export type StoreId = string;
|
|
36
110
|
export type DurableObjectId = string;
|
|
37
111
|
/**
|
|
38
|
-
*
|
|
112
|
+
* CRITICAL: Increment this version whenever you modify the database schema structure.
|
|
113
|
+
*
|
|
114
|
+
* Bump required when:
|
|
115
|
+
* - Adding/removing/renaming columns in eventlogTable or contextTable (see sqlite.ts)
|
|
116
|
+
* - Changing column types or constraints
|
|
117
|
+
* - Modifying primary keys or indexes
|
|
39
118
|
*
|
|
40
|
-
*
|
|
119
|
+
* Bump NOT required when:
|
|
120
|
+
* - Changing query patterns, pagination logic, or streaming behavior
|
|
121
|
+
* - Adding new tables (as long as existing table schemas remain unchanged)
|
|
122
|
+
* - Updating implementation details in sync-storage.ts
|
|
123
|
+
*
|
|
124
|
+
* Impact: Changing this version triggers a "soft reset" - new table names are created
|
|
125
|
+
* and old data becomes inaccessible (but remains in storage).
|
|
41
126
|
*/
|
|
42
127
|
export declare const PERSISTENCE_FORMAT_VERSION = 7;
|
|
43
|
-
export declare const DEFAULT_SYNC_DURABLE_OBJECT_NAME = "SYNC_BACKEND_DO";
|
|
44
128
|
export declare const encodeOutgoingMessage: (a: {
|
|
45
129
|
readonly backendId: string;
|
|
46
130
|
readonly batch: readonly {
|
|
47
|
-
readonly metadata: Option.Option<{
|
|
131
|
+
readonly metadata: import("effect/Option").Option<{
|
|
48
132
|
readonly createdAt: string;
|
|
49
133
|
readonly _tag: "SyncMessage.SyncMetadata";
|
|
50
134
|
}>;
|
|
51
135
|
readonly eventEncoded: {
|
|
52
136
|
readonly name: string;
|
|
53
137
|
readonly args: any;
|
|
54
|
-
readonly seqNum:
|
|
55
|
-
readonly parentSeqNum:
|
|
138
|
+
readonly seqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
|
|
139
|
+
readonly parentSeqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
|
|
56
140
|
readonly clientId: string;
|
|
57
141
|
readonly sessionId: string;
|
|
58
142
|
};
|
|
@@ -76,17 +160,17 @@ export declare const encodeOutgoingMessage: (a: {
|
|
|
76
160
|
readonly _tag: "SyncMessage.AdminInfoResponse";
|
|
77
161
|
}, overrideOptions?: import("effect/SchemaAST").ParseOptions) => string;
|
|
78
162
|
export declare const encodeIncomingMessage: (a: {
|
|
79
|
-
readonly cursor: Option.Option<{
|
|
163
|
+
readonly cursor: import("effect/Option").Option<{
|
|
80
164
|
readonly backendId: string;
|
|
81
165
|
readonly eventSequenceNumber: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
|
|
82
166
|
}>;
|
|
83
167
|
} | {
|
|
84
|
-
readonly backendId: Option.Option<string>;
|
|
168
|
+
readonly backendId: import("effect/Option").Option<string>;
|
|
85
169
|
readonly batch: readonly {
|
|
86
170
|
readonly name: string;
|
|
87
171
|
readonly args: any;
|
|
88
|
-
readonly seqNum:
|
|
89
|
-
readonly parentSeqNum:
|
|
172
|
+
readonly seqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
|
|
173
|
+
readonly parentSeqNum: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
|
|
90
174
|
readonly clientId: string;
|
|
91
175
|
readonly sessionId: string;
|
|
92
176
|
}[];
|
|
@@ -99,8 +183,12 @@ export declare const encodeIncomingMessage: (a: {
|
|
|
99
183
|
readonly _tag: "SyncMessage.AdminInfoRequest";
|
|
100
184
|
readonly adminSecret: string;
|
|
101
185
|
}, overrideOptions?: import("effect/SchemaAST").ParseOptions) => string;
|
|
102
|
-
|
|
103
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Extracts the LiveStore sync search parameters from a request. Returns
|
|
188
|
+
* `undefined` when the request does not carry valid sync metadata so callers
|
|
189
|
+
* can fall back to custom routing.
|
|
190
|
+
*/
|
|
191
|
+
export declare const matchSyncRequest: (request: CfTypes.Request) => SearchParams | undefined;
|
|
104
192
|
export type RpcSubscription = {
|
|
105
193
|
storeId: StoreId;
|
|
106
194
|
payload?: Schema.JsonValue;
|
|
@@ -123,5 +211,10 @@ export declare const WebSocketAttachmentSchema: Schema.transform<Schema.SchemaCl
|
|
|
123
211
|
storeId: typeof Schema.String;
|
|
124
212
|
payload: Schema.optional<Schema.Schema<Schema.JsonValue, Schema.JsonValue, never>>;
|
|
125
213
|
pullRequestIds: Schema.Array$<typeof Schema.String>;
|
|
214
|
+
headers: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.String>>;
|
|
126
215
|
}>>;
|
|
216
|
+
/** Helper to extract headers from a request based on the forwardHeaders option */
|
|
217
|
+
export declare const extractForwardedHeaders: (request: CfTypes.Request, forwardHeaders: ForwardHeadersOption | undefined) => Record<string, string> | undefined;
|
|
218
|
+
/** Convert a headers record to a ReadonlyMap */
|
|
219
|
+
export declare const headersRecordToMap: (headers: Record<string, string> | undefined) => ForwardedHeaders | undefined;
|
|
127
220
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/cf-worker/shared.js
CHANGED
|
@@ -1,26 +1,70 @@
|
|
|
1
1
|
import { Effect, Schema, UrlParams } from '@livestore/utils/effect';
|
|
2
2
|
import { SearchParamsSchema, SyncMessage } from "../common/mod.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* CRITICAL: Increment this version whenever you modify the database schema structure.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Bump required when:
|
|
7
|
+
* - Adding/removing/renaming columns in eventlogTable or contextTable (see sqlite.ts)
|
|
8
|
+
* - Changing column types or constraints
|
|
9
|
+
* - Modifying primary keys or indexes
|
|
10
|
+
*
|
|
11
|
+
* Bump NOT required when:
|
|
12
|
+
* - Changing query patterns, pagination logic, or streaming behavior
|
|
13
|
+
* - Adding new tables (as long as existing table schemas remain unchanged)
|
|
14
|
+
* - Updating implementation details in sync-storage.ts
|
|
15
|
+
*
|
|
16
|
+
* Impact: Changing this version triggers a "soft reset" - new table names are created
|
|
17
|
+
* and old data becomes inaccessible (but remains in storage).
|
|
7
18
|
*/
|
|
8
19
|
export const PERSISTENCE_FORMAT_VERSION = 7;
|
|
9
|
-
export const DEFAULT_SYNC_DURABLE_OBJECT_NAME = 'SYNC_BACKEND_DO';
|
|
10
20
|
export const encodeOutgoingMessage = Schema.encodeSync(Schema.parseJson(SyncMessage.BackendToClientMessage));
|
|
11
21
|
export const encodeIncomingMessage = Schema.encodeSync(Schema.parseJson(SyncMessage.ClientToBackendMessage));
|
|
12
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Extracts the LiveStore sync search parameters from a request. Returns
|
|
24
|
+
* `undefined` when the request does not carry valid sync metadata so callers
|
|
25
|
+
* can fall back to custom routing.
|
|
26
|
+
*/
|
|
27
|
+
export const matchSyncRequest = (request) => {
|
|
13
28
|
const url = new URL(request.url);
|
|
14
29
|
const urlParams = UrlParams.fromInput(url.searchParams);
|
|
15
30
|
const paramsResult = UrlParams.schemaStruct(SearchParamsSchema)(urlParams).pipe(Effect.option, Effect.runSync);
|
|
16
|
-
|
|
31
|
+
if (paramsResult._tag === 'None') {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return paramsResult.value;
|
|
17
35
|
};
|
|
18
|
-
export const PULL_CHUNK_SIZE = 100;
|
|
19
36
|
export const WebSocketAttachmentSchema = Schema.parseJson(Schema.Struct({
|
|
20
37
|
// Same across all websocket connections
|
|
21
38
|
storeId: Schema.String,
|
|
22
39
|
// Different for each websocket connection
|
|
23
40
|
payload: Schema.optional(Schema.JsonValue),
|
|
24
41
|
pullRequestIds: Schema.Array(Schema.String),
|
|
42
|
+
// Headers forwarded from the initial request (via forwardHeaders option)
|
|
43
|
+
headers: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.String })),
|
|
25
44
|
}));
|
|
45
|
+
/** Helper to extract headers from a request based on the forwardHeaders option */
|
|
46
|
+
export const extractForwardedHeaders = (request, forwardHeaders) => {
|
|
47
|
+
if (forwardHeaders === undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (typeof forwardHeaders === 'function') {
|
|
51
|
+
return forwardHeaders(request);
|
|
52
|
+
}
|
|
53
|
+
// Array of header names - extract them case-insensitively
|
|
54
|
+
const result = {};
|
|
55
|
+
for (const name of forwardHeaders) {
|
|
56
|
+
const value = request.headers.get(name);
|
|
57
|
+
if (value !== null) {
|
|
58
|
+
result[name.toLowerCase()] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
62
|
+
};
|
|
63
|
+
/** Convert a headers record to a ReadonlyMap */
|
|
64
|
+
export const headersRecordToMap = (headers) => {
|
|
65
|
+
if (headers === undefined) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return new Map(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]));
|
|
69
|
+
};
|
|
26
70
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,100 +1,93 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HelperTypes } from '@livestore/common-cf';
|
|
2
|
+
import { Schema } from '@livestore/utils/effect';
|
|
2
3
|
import type { CfTypes, SearchParams } from '../common/mod.ts';
|
|
3
|
-
import { type Env } from './shared.ts';
|
|
4
|
-
export declare namespace HelperTypes {
|
|
5
|
-
type AnyDON = CfTypes.DurableObjectNamespace<undefined>;
|
|
6
|
-
type DOKeys<T> = {
|
|
7
|
-
[K in keyof T]-?: T[K] extends AnyDON ? K : never;
|
|
8
|
-
}[keyof T];
|
|
9
|
-
type NonBuiltins<T> = Omit<T, keyof Env>;
|
|
10
|
-
/**
|
|
11
|
-
* Helper type to extract DurableObject keys from Env to give consumer type safety.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* type PlatformEnv = {
|
|
16
|
-
* DB: D1Database
|
|
17
|
-
* ADMIN_TOKEN: string
|
|
18
|
-
* SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendDO>
|
|
19
|
-
* }
|
|
20
|
-
* export default makeWorker<PlatformEnv>({
|
|
21
|
-
* durableObject: { name: "SYNC_BACKEND_DO" },
|
|
22
|
-
* // ^ (property) name?: "SYNC_BACKEND_DO" | undefined
|
|
23
|
-
* });
|
|
24
|
-
*/
|
|
25
|
-
export type ExtractDurableObjectKeys<TEnv = Env> = DOKeys<NonBuiltins<TEnv>> extends never ? string : DOKeys<NonBuiltins<TEnv>>;
|
|
26
|
-
export {};
|
|
27
|
-
}
|
|
4
|
+
import { type Env, type ForwardedHeaders } from './shared.ts';
|
|
28
5
|
export type CFWorker<TEnv extends Env = Env, _T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined> = {
|
|
29
6
|
fetch: <CFHostMetada = unknown>(request: CfTypes.Request<CFHostMetada>, env: TEnv, ctx: CfTypes.ExecutionContext) => Promise<CfTypes.Response>;
|
|
30
7
|
};
|
|
31
|
-
|
|
8
|
+
/** Context passed to validatePayload callback */
|
|
9
|
+
export type ValidatePayloadContext = {
|
|
10
|
+
storeId: string;
|
|
11
|
+
/** Request headers (raw, not filtered by forwardHeaders) */
|
|
12
|
+
headers: ForwardedHeaders;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Options accepted by {@link makeWorker}. The Durable Object binding has to be
|
|
16
|
+
* supplied explicitly so we never fall back to deprecated defaults when Cloudflare config changes.
|
|
17
|
+
*/
|
|
18
|
+
export type MakeWorkerOptions<TEnv extends Env = Env, TSyncPayload = Schema.JsonValue> = {
|
|
19
|
+
/**
|
|
20
|
+
* Binding name of the sync Durable Object declared in wrangler config.
|
|
21
|
+
*/
|
|
22
|
+
syncBackendBinding: HelperTypes.ExtractDurableObjectKeys<TEnv>;
|
|
32
23
|
/**
|
|
33
|
-
*
|
|
24
|
+
* Optionally pass a schema to decode the client-provided payload into a typed object
|
|
25
|
+
* before calling {@link validatePayload}. If omitted, the raw JSON value is forwarded.
|
|
26
|
+
*/
|
|
27
|
+
syncPayloadSchema?: Schema.Schema<TSyncPayload>;
|
|
28
|
+
/**
|
|
29
|
+
* Validates the (optionally decoded) payload during WebSocket connection establishment.
|
|
30
|
+
* If {@link syncPayloadSchema} is provided, `payload` will be of the schema's inferred type.
|
|
31
|
+
*
|
|
32
|
+
* The context includes request headers for cookie-based or header-based authentication.
|
|
33
|
+
*
|
|
34
|
+
* @example Cookie-based authentication
|
|
35
|
+
* ```ts
|
|
36
|
+
* validatePayload: async (payload, { storeId, headers }) => {
|
|
37
|
+
* const cookie = headers.get('cookie')
|
|
38
|
+
* const session = await validateSessionFromCookie(cookie)
|
|
39
|
+
* if (!session) throw new Error('Unauthorized')
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
34
43
|
* Note: This runs only at connection time, not for individual push events.
|
|
35
|
-
* For push event validation, use the `onPush` callback in the
|
|
44
|
+
* For push event validation, use the `onPush` callback in the Durable Object.
|
|
36
45
|
*/
|
|
37
|
-
validatePayload?: (payload:
|
|
38
|
-
storeId: string;
|
|
39
|
-
}) => void | Promise<void>;
|
|
46
|
+
validatePayload?: (payload: TSyncPayload, context: ValidatePayloadContext) => void | Promise<void>;
|
|
40
47
|
/** @default false */
|
|
41
48
|
enableCORS?: boolean;
|
|
42
|
-
durableObject?: {
|
|
43
|
-
/**
|
|
44
|
-
* Needs to match the binding name from the wrangler config
|
|
45
|
-
*
|
|
46
|
-
* @default 'SYNC_BACKEND_DO'
|
|
47
|
-
*/
|
|
48
|
-
name?: HelperTypes.ExtractDurableObjectKeys<TEnv>;
|
|
49
|
-
};
|
|
50
49
|
};
|
|
51
|
-
export declare const makeWorker: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>(options?: MakeWorkerOptions<TEnv>) => CFWorker<TEnv, TDurableObjectRpc>;
|
|
52
50
|
/**
|
|
53
|
-
*
|
|
51
|
+
* Produces a Cloudflare Worker `fetch` handler that delegates sync traffic to the
|
|
52
|
+
* Durable Object identified by `syncBackendBinding`.
|
|
53
|
+
*
|
|
54
|
+
* For more complex setups prefer implementing a custom `fetch` and call {@link handleSyncRequest}
|
|
55
|
+
* from the branch that handles LiveStore sync requests.
|
|
56
|
+
*/
|
|
57
|
+
export declare const makeWorker: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined, TSyncPayload = Schema.JsonValue>(options: MakeWorkerOptions<TEnv, TSyncPayload>) => CFWorker<TEnv, TDurableObjectRpc>;
|
|
58
|
+
/**
|
|
59
|
+
* Handles LiveStore sync requests (e.g. with search params `?storeId=...&transport=...`).
|
|
54
60
|
*
|
|
55
|
-
* @example
|
|
61
|
+
* @example Token-based authentication
|
|
56
62
|
* ```ts
|
|
57
63
|
* const validatePayload = (payload: Schema.JsonValue | undefined, context: { storeId: string }) => {
|
|
58
|
-
* console.log(`Validating connection for store: ${context.storeId}`)
|
|
59
64
|
* if (payload?.authToken !== 'insecure-token-change-me') {
|
|
60
65
|
* throw new Error('Invalid auth token')
|
|
61
66
|
* }
|
|
62
67
|
* }
|
|
68
|
+
* ```
|
|
63
69
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* return handleSyncRequest({
|
|
71
|
-
* request,
|
|
72
|
-
* searchParams: requestParamsResult.value,
|
|
73
|
-
* env,
|
|
74
|
-
* ctx,
|
|
75
|
-
* options: { headers: {}, validatePayload }
|
|
76
|
-
* })
|
|
77
|
-
* }
|
|
78
|
-
*
|
|
79
|
-
* return new Response('Invalid path', { status: 400 })
|
|
80
|
-
* }
|
|
70
|
+
* @example Cookie-based authentication
|
|
71
|
+
* ```ts
|
|
72
|
+
* const validatePayload = async (payload: Schema.JsonValue | undefined, { storeId, headers }) => {
|
|
73
|
+
* const cookie = headers.get('cookie')
|
|
74
|
+
* const session = await validateSessionFromCookie(cookie)
|
|
75
|
+
* if (!session) throw new Error('Unauthorized')
|
|
81
76
|
* }
|
|
82
77
|
* ```
|
|
83
78
|
*
|
|
84
|
-
* @throws {
|
|
79
|
+
* @throws {UnknownError} If the payload is invalid
|
|
85
80
|
*/
|
|
86
|
-
export declare const handleSyncRequest: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined, CFHostMetada = unknown>({ request, searchParams, env,
|
|
81
|
+
export declare const handleSyncRequest: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined, CFHostMetada = unknown, TSyncPayload = Schema.JsonValue>({ request, searchParams: { storeId, payload, transport }, env: explicitlyProvidedEnv, syncBackendBinding, headers, validatePayload, syncPayloadSchema, }: {
|
|
87
82
|
request: CfTypes.Request<CFHostMetada>;
|
|
88
83
|
searchParams: SearchParams;
|
|
89
|
-
env
|
|
84
|
+
env?: TEnv | undefined;
|
|
90
85
|
/** Only there for type-level reasons */
|
|
91
86
|
ctx: CfTypes.ExecutionContext;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}) => void | Promise<void>;
|
|
98
|
-
};
|
|
87
|
+
/** Binding name of the sync backend Durable Object */
|
|
88
|
+
syncBackendBinding: MakeWorkerOptions<TEnv, TSyncPayload>["syncBackendBinding"];
|
|
89
|
+
headers?: CfTypes.HeadersInit | undefined;
|
|
90
|
+
validatePayload?: MakeWorkerOptions<TEnv, TSyncPayload>["validatePayload"];
|
|
91
|
+
syncPayloadSchema?: MakeWorkerOptions<TEnv, TSyncPayload>["syncPayloadSchema"];
|
|
99
92
|
}) => Promise<CfTypes.Response>;
|
|
100
93
|
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
|