@livestore/sync-cf 0.3.0-dev.10 → 0.3.0-dev.2
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/cf-worker/durable-object.d.ts +34 -27
- package/dist/cf-worker/durable-object.d.ts.map +1 -1
- package/dist/cf-worker/durable-object.js +128 -149
- package/dist/cf-worker/durable-object.js.map +1 -1
- package/dist/cf-worker/index.d.ts +6 -1
- package/dist/cf-worker/index.d.ts.map +1 -1
- package/dist/cf-worker/index.js +64 -30
- package/dist/cf-worker/index.js.map +1 -1
- package/dist/common/ws-message-types.d.ts +207 -54
- package/dist/common/ws-message-types.d.ts.map +1 -1
- package/dist/common/ws-message-types.js +3 -3
- package/dist/common/ws-message-types.js.map +1 -1
- package/dist/sync-impl/ws-impl.d.ts +12 -3
- package/dist/sync-impl/ws-impl.d.ts.map +1 -1
- package/dist/sync-impl/ws-impl.js +4 -5
- package/dist/sync-impl/ws-impl.js.map +1 -1
- package/package.json +13 -15
- package/src/cf-worker/durable-object.ts +161 -212
- package/src/cf-worker/index.ts +84 -0
- package/src/common/ws-message-types.ts +3 -3
- package/src/sync-impl/ws-impl.ts +16 -8
- package/dist/cf-worker/make-worker.d.ts +0 -6
- package/dist/cf-worker/make-worker.d.ts.map +0 -1
- package/dist/cf-worker/make-worker.js +0 -31
- package/dist/cf-worker/make-worker.js.map +0 -1
- package/dist/cf-worker/mod.d.ts +0 -3
- package/dist/cf-worker/mod.d.ts.map +0 -1
- package/dist/cf-worker/mod.js +0 -3
- package/dist/cf-worker/mod.js.map +0 -1
- package/dist/cf-worker/types.d.ts +0 -2
- package/dist/cf-worker/types.d.ts.map +0 -1
- package/dist/cf-worker/types.js +0 -2
- package/dist/cf-worker/types.js.map +0 -1
- package/dist/cf-worker/worker.d.ts +0 -6
- package/dist/cf-worker/worker.d.ts.map +0 -1
- package/dist/cf-worker/worker.js +0 -29
- package/dist/cf-worker/worker.js.map +0 -1
- package/dist/common/mod.d.ts +0 -2
- package/dist/common/mod.d.ts.map +0 -1
- package/dist/common/mod.js +0 -2
- package/dist/common/mod.js.map +0 -1
- package/dist/sync-impl/mod.d.ts +0 -2
- package/dist/sync-impl/mod.d.ts.map +0 -1
- package/dist/sync-impl/mod.js +0 -2
- package/dist/sync-impl/mod.js.map +0 -1
- package/src/cf-worker/mod.ts +0 -2
- package/src/cf-worker/worker.ts +0 -39
- /package/src/common/{mod.ts → index.ts} +0 -0
- /package/src/sync-impl/{mod.ts → index.ts} +0 -0
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { DbSchema } from '@livestore/common/schema';
|
|
2
|
-
import {
|
|
1
|
+
import { DbSchema, type MutationEvent } from '@livestore/common/schema';
|
|
2
|
+
import { Option, Schema } from '@livestore/utils/effect';
|
|
3
3
|
import { DurableObject } from 'cloudflare:workers';
|
|
4
|
-
import {
|
|
4
|
+
import type { SyncMetadata } from '../common/ws-message-types.js';
|
|
5
5
|
export interface Env {
|
|
6
|
-
WEBSOCKET_SERVER: DurableObjectNamespace
|
|
6
|
+
WEBSOCKET_SERVER: DurableObjectNamespace<WebSocketServer>;
|
|
7
7
|
DB: D1Database;
|
|
8
8
|
ADMIN_SECRET: string;
|
|
9
9
|
}
|
|
10
|
+
type WebSocketClient = WebSocket;
|
|
10
11
|
export declare const mutationLogTable: DbSchema.TableDef<{
|
|
11
12
|
name: "__unused";
|
|
12
13
|
columns: {
|
|
13
|
-
|
|
14
|
+
idGlobal: {
|
|
14
15
|
columnType: "integer";
|
|
15
|
-
schema: Schema.Schema<number
|
|
16
|
+
schema: Schema.Schema<number, number, never>;
|
|
16
17
|
default: Option.None<never>;
|
|
17
18
|
nullable: false;
|
|
18
19
|
primaryKey: true;
|
|
19
20
|
};
|
|
20
|
-
|
|
21
|
+
parentIdGlobal: {
|
|
21
22
|
columnType: "integer";
|
|
22
|
-
schema: Schema.Schema<number
|
|
23
|
+
schema: Schema.Schema<number, number, never>;
|
|
23
24
|
default: Option.None<never>;
|
|
24
25
|
nullable: false;
|
|
25
26
|
primaryKey: false;
|
|
@@ -45,6 +46,7 @@ export declare const mutationLogTable: DbSchema.TableDef<{
|
|
|
45
46
|
nullable: false;
|
|
46
47
|
primaryKey: false;
|
|
47
48
|
};
|
|
49
|
+
id: DbSchema.SqliteDsl.ColumnDefinition<string, string>;
|
|
48
50
|
};
|
|
49
51
|
indexes?: ReadonlyArray<DbSchema.SqliteDsl.Index>;
|
|
50
52
|
ast: import("@livestore/db-schema/dist/ast/sqlite.js").Table;
|
|
@@ -53,32 +55,37 @@ export declare const mutationLogTable: DbSchema.TableDef<{
|
|
|
53
55
|
disableAutomaticIdColumn: false;
|
|
54
56
|
deriveMutations: never;
|
|
55
57
|
isSingleColumn: false;
|
|
56
|
-
requiredInsertColumnNames: "createdAt" | "
|
|
58
|
+
requiredInsertColumnNames: "createdAt" | "idGlobal" | "parentIdGlobal" | "mutation" | "args";
|
|
57
59
|
}, Schema.Schema<{
|
|
58
|
-
readonly
|
|
59
|
-
readonly
|
|
60
|
+
readonly idGlobal: number;
|
|
61
|
+
readonly parentIdGlobal: number;
|
|
60
62
|
readonly mutation: string;
|
|
61
63
|
readonly args: any;
|
|
62
64
|
readonly createdAt: string;
|
|
65
|
+
readonly id: string;
|
|
63
66
|
}, {
|
|
64
|
-
readonly
|
|
65
|
-
readonly
|
|
67
|
+
readonly idGlobal: number;
|
|
68
|
+
readonly parentIdGlobal: number;
|
|
66
69
|
readonly mutation: string;
|
|
67
70
|
readonly args: string;
|
|
68
71
|
readonly createdAt: string;
|
|
72
|
+
readonly id: string;
|
|
69
73
|
}, never>>;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
export declare class WebSocketServer extends DurableObject<Env> {
|
|
75
|
+
dbName: string;
|
|
76
|
+
storage: {
|
|
77
|
+
getLatestEvent: () => Promise<MutationEvent.Any | undefined>;
|
|
78
|
+
getEvents: (cursor: number | undefined) => Promise<ReadonlyArray<{
|
|
79
|
+
mutationEventEncoded: MutationEvent.AnyEncoded;
|
|
80
|
+
metadata: Option.Option<SyncMetadata>;
|
|
81
|
+
}>>;
|
|
82
|
+
appendEvent: (event: MutationEvent.Any, createdAt: string) => Promise<void>;
|
|
83
|
+
resetRoom: () => Promise<void>;
|
|
84
|
+
};
|
|
85
|
+
constructor(ctx: DurableObjectState, env: Env);
|
|
86
|
+
fetch: (_request: Request) => Promise<Response>;
|
|
87
|
+
webSocketMessage: (ws: WebSocketClient, message: ArrayBuffer | string) => Promise<undefined>;
|
|
88
|
+
webSocketClose: (ws: WebSocketClient, code: number, _reason: string, _wasClean: boolean) => Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
84
91
|
//# sourceMappingURL=durable-object.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../../src/cf-worker/durable-object.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../../src/cf-worker/durable-object.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAW,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAEhF,OAAO,EAA4B,MAAM,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAEjE,MAAM,WAAW,GAAG;IAClB,gBAAgB,EAAE,sBAAsB,CAAC,eAAe,CAAC,CAAA;IACzD,EAAE,EAAE,UAAU,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,KAAK,eAAe,GAAG,SAAS,CAAA;AAOhC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAO3B,CAAA;AAGF,qBAAa,eAAgB,SAAQ,aAAa,CAAC,GAAG,CAAC;IACrD,MAAM,SAA2C;IACjD,OAAO;8BA8K0B,OAAO,CAAC,aAAa,CAAC,GAAG,GAAG,SAAS,CAAC;4BAe7D,MAAM,GAAG,SAAS,KACzB,OAAO,CACR,aAAa,CAAC;YAAE,oBAAoB,EAAE,aAAa,CAAC,UAAU,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;SAAE,CAAC,CACzG;6BAsBiC,aAAa,CAAC,GAAG,aAAa,MAAM;;MAtNhB;gBAE1C,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG;IAI7C,KAAK,aAAoB,OAAO,uBAsBsB;IAEtD,gBAAgB,OAAQ,eAAe,WAAW,WAAW,GAAG,MAAM,wBAuInE;IAEH,cAAc,OAAc,eAAe,QAAQ,MAAM,WAAW,MAAM,aAAa,OAAO,mBAG7F;CACF"}
|
|
@@ -3,199 +3,178 @@ import { DbSchema, EventId } from '@livestore/common/schema';
|
|
|
3
3
|
import { shouldNeverHappen } from '@livestore/utils';
|
|
4
4
|
import { Effect, Logger, LogLevel, Option, Schema } from '@livestore/utils/effect';
|
|
5
5
|
import { DurableObject } from 'cloudflare:workers';
|
|
6
|
-
import { WSMessage } from '../common/
|
|
6
|
+
import { WSMessage } from '../common/index.js';
|
|
7
7
|
const encodeOutgoingMessage = Schema.encodeSync(Schema.parseJson(WSMessage.BackendToClientMessage));
|
|
8
8
|
const encodeIncomingMessage = Schema.encodeSync(Schema.parseJson(WSMessage.ClientToBackendMessage));
|
|
9
9
|
const decodeIncomingMessage = Schema.decodeUnknownEither(Schema.parseJson(WSMessage.ClientToBackendMessage));
|
|
10
10
|
// NOTE actual table name is determined at runtime by `WebSocketServer.dbName`
|
|
11
11
|
export const mutationLogTable = DbSchema.table('__unused', {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
idGlobal: DbSchema.integer({ primaryKey: true }),
|
|
13
|
+
parentIdGlobal: DbSchema.integer({}),
|
|
14
14
|
mutation: DbSchema.text({}),
|
|
15
15
|
args: DbSchema.text({ schema: Schema.parseJson(Schema.Any) }),
|
|
16
|
-
/** ISO date format
|
|
16
|
+
/** ISO date format */
|
|
17
17
|
createdAt: DbSchema.text({}),
|
|
18
18
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
// Durable Object
|
|
20
|
+
export class WebSocketServer extends DurableObject {
|
|
21
|
+
dbName = `mutation_log_${this.ctx.id.toString()}`;
|
|
22
|
+
storage = makeStorage(this.ctx, this.env, this.dbName);
|
|
23
|
+
constructor(ctx, env) {
|
|
24
|
+
super(ctx, env);
|
|
25
|
+
}
|
|
26
|
+
fetch = async (_request) => Effect.gen(this, function* () {
|
|
27
|
+
const { 0: client, 1: server } = new WebSocketPair();
|
|
28
|
+
// See https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server
|
|
29
|
+
this.ctx.acceptWebSocket(server);
|
|
30
|
+
this.ctx.setWebSocketAutoResponse(new WebSocketRequestResponsePair(encodeIncomingMessage(WSMessage.Ping.make({ requestId: 'ping' })), encodeOutgoingMessage(WSMessage.Pong.make({ requestId: 'ping' }))));
|
|
31
|
+
const colSpec = makeColumnSpec(mutationLogTable.sqliteDef.ast);
|
|
32
|
+
this.env.DB.exec(`CREATE TABLE IF NOT EXISTS ${this.dbName} (${colSpec}) strict`);
|
|
33
|
+
return new Response(null, {
|
|
34
|
+
status: 101,
|
|
35
|
+
webSocket: client,
|
|
36
|
+
});
|
|
37
|
+
}).pipe(Effect.tapCauseLogPretty, Effect.runPromise);
|
|
38
|
+
webSocketMessage = (ws, message) => Effect.gen(this, function* () {
|
|
39
|
+
const decodedMessageRes = decodeIncomingMessage(message);
|
|
40
|
+
if (decodedMessageRes._tag === 'Left') {
|
|
41
|
+
console.error('Invalid message received', decodedMessageRes.left);
|
|
42
|
+
return;
|
|
30
43
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
47
|
-
}).pipe(Effect.tapCauseLogPretty, Effect.runPromise);
|
|
48
|
-
webSocketMessage = (ws, message) => Effect.gen(this, function* () {
|
|
49
|
-
const decodedMessageRes = decodeIncomingMessage(message);
|
|
50
|
-
if (decodedMessageRes._tag === 'Left') {
|
|
51
|
-
console.error('Invalid message received', decodedMessageRes.left);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const decodedMessage = decodedMessageRes.right;
|
|
55
|
-
const requestId = decodedMessage.requestId;
|
|
56
|
-
const storage = this.storage;
|
|
57
|
-
if (storage === undefined) {
|
|
58
|
-
throw new Error('storage not initialized');
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
switch (decodedMessage._tag) {
|
|
62
|
-
case 'WSMessage.PullReq': {
|
|
63
|
-
if (options?.onPull) {
|
|
64
|
-
yield* Effect.tryAll(() => options.onPull(decodedMessage));
|
|
65
|
-
}
|
|
66
|
-
const cursor = decodedMessage.cursor;
|
|
67
|
-
const CHUNK_SIZE = 100;
|
|
68
|
-
// TODO use streaming
|
|
69
|
-
const remainingEvents = [...(yield* Effect.promise(() => storage.getEvents(cursor)))];
|
|
70
|
-
// NOTE we want to make sure the WS server responds at least once with `InitRes` even if `events` is empty
|
|
71
|
-
while (true) {
|
|
72
|
-
const events = remainingEvents.splice(0, CHUNK_SIZE);
|
|
73
|
-
ws.send(encodeOutgoingMessage(WSMessage.PullRes.make({ events, remaining: remainingEvents.length, requestId })));
|
|
74
|
-
if (remainingEvents.length === 0) {
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
44
|
+
const decodedMessage = decodedMessageRes.right;
|
|
45
|
+
const requestId = decodedMessage.requestId;
|
|
46
|
+
try {
|
|
47
|
+
switch (decodedMessage._tag) {
|
|
48
|
+
case 'WSMessage.PullReq': {
|
|
49
|
+
const cursor = decodedMessage.cursor;
|
|
50
|
+
const CHUNK_SIZE = 100;
|
|
51
|
+
// TODO use streaming
|
|
52
|
+
const remainingEvents = [...(yield* Effect.promise(() => this.storage.getEvents(cursor)))];
|
|
53
|
+
// NOTE we want to make sure the WS server responds at least once with `InitRes` even if `events` is empty
|
|
54
|
+
while (true) {
|
|
55
|
+
const events = remainingEvents.splice(0, CHUNK_SIZE);
|
|
56
|
+
ws.send(encodeOutgoingMessage(WSMessage.PullRes.make({ events, remaining: remainingEvents.length, requestId })));
|
|
57
|
+
if (remainingEvents.length === 0) {
|
|
58
|
+
break;
|
|
77
59
|
}
|
|
78
|
-
break;
|
|
79
60
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'WSMessage.PushReq': {
|
|
64
|
+
// TODO check whether we could use the Durable Object storage for this to speed up the lookup
|
|
65
|
+
const latestEvent = yield* Effect.promise(() => this.storage.getLatestEvent());
|
|
66
|
+
const expectedParentId = latestEvent?.id ?? EventId.ROOT;
|
|
67
|
+
let i = 0;
|
|
68
|
+
for (const mutationEventEncoded of decodedMessage.batch) {
|
|
69
|
+
if (mutationEventEncoded.parentId.global !== expectedParentId.global + i) {
|
|
70
|
+
const err = WSMessage.Error.make({
|
|
71
|
+
message: `Invalid parent id. Received ${mutationEventEncoded.parentId.global} but expected ${expectedParentId.global}`,
|
|
72
|
+
requestId,
|
|
73
|
+
});
|
|
74
|
+
yield* Effect.fail(err).pipe(Effect.ignoreLogged);
|
|
75
|
+
ws.send(encodeOutgoingMessage(err));
|
|
76
|
+
return;
|
|
83
77
|
}
|
|
84
|
-
// TODO
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// console.debug(`Broadcasting mutation event to ${this.subscribedWebSockets.size} clients`)
|
|
104
|
-
const connectedClients = this.ctx.getWebSockets();
|
|
105
|
-
if (connectedClients.length > 0) {
|
|
106
|
-
const broadcastMessage = encodeOutgoingMessage(
|
|
107
|
-
// TODO refactor to batch api
|
|
108
|
-
WSMessage.PushBroadcast.make({
|
|
109
|
-
mutationEventEncoded,
|
|
110
|
-
metadata: Option.some({ createdAt }),
|
|
111
|
-
}));
|
|
112
|
-
for (const conn of connectedClients) {
|
|
113
|
-
console.log('Broadcasting to client', conn === ws ? 'self' : 'other');
|
|
114
|
-
// if (conn !== ws) {
|
|
115
|
-
conn.send(broadcastMessage);
|
|
116
|
-
// }
|
|
117
|
-
}
|
|
78
|
+
// TODO handle clientId unique conflict
|
|
79
|
+
const createdAt = new Date().toISOString();
|
|
80
|
+
// NOTE we're currently not blocking on this to allow broadcasting right away
|
|
81
|
+
const storePromise = this.storage.appendEvent(mutationEventEncoded, createdAt);
|
|
82
|
+
ws.send(encodeOutgoingMessage(WSMessage.PushAck.make({ mutationId: mutationEventEncoded.id.global, requestId })));
|
|
83
|
+
// console.debug(`Broadcasting mutation event to ${this.subscribedWebSockets.size} clients`)
|
|
84
|
+
const connectedClients = this.ctx.getWebSockets();
|
|
85
|
+
if (connectedClients.length > 0) {
|
|
86
|
+
const broadcastMessage = encodeOutgoingMessage(
|
|
87
|
+
// TODO refactor to batch api
|
|
88
|
+
WSMessage.PushBroadcast.make({
|
|
89
|
+
mutationEventEncoded,
|
|
90
|
+
metadata: Option.some({ createdAt }),
|
|
91
|
+
}));
|
|
92
|
+
for (const conn of connectedClients) {
|
|
93
|
+
console.log('Broadcasting to client', conn === ws ? 'self' : 'other');
|
|
94
|
+
// if (conn !== ws) {
|
|
95
|
+
conn.send(broadcastMessage);
|
|
96
|
+
// }
|
|
118
97
|
}
|
|
119
|
-
yield* Effect.promise(() => storePromise);
|
|
120
|
-
i++;
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
case 'WSMessage.AdminResetRoomReq': {
|
|
125
|
-
if (decodedMessage.adminSecret !== this.env.ADMIN_SECRET) {
|
|
126
|
-
ws.send(encodeOutgoingMessage(WSMessage.Error.make({ message: 'Invalid admin secret', requestId })));
|
|
127
|
-
return;
|
|
128
98
|
}
|
|
129
|
-
yield* Effect.promise(() =>
|
|
130
|
-
|
|
131
|
-
break;
|
|
99
|
+
yield* Effect.promise(() => storePromise);
|
|
100
|
+
i++;
|
|
132
101
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
break;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'WSMessage.AdminResetRoomReq': {
|
|
105
|
+
if (decodedMessage.adminSecret !== this.env.ADMIN_SECRET) {
|
|
106
|
+
ws.send(encodeOutgoingMessage(WSMessage.Error.make({ message: 'Invalid admin secret', requestId })));
|
|
107
|
+
return;
|
|
140
108
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
109
|
+
yield* Effect.promise(() => this.storage.resetRoom());
|
|
110
|
+
ws.send(encodeOutgoingMessage(WSMessage.AdminResetRoomRes.make({ requestId })));
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case 'WSMessage.AdminInfoReq': {
|
|
114
|
+
if (decodedMessage.adminSecret !== this.env.ADMIN_SECRET) {
|
|
115
|
+
ws.send(encodeOutgoingMessage(WSMessage.Error.make({ message: 'Invalid admin secret', requestId })));
|
|
116
|
+
return;
|
|
144
117
|
}
|
|
118
|
+
ws.send(encodeOutgoingMessage(WSMessage.AdminInfoRes.make({ requestId, info: { durableObjectId: this.ctx.id.toString() } })));
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
default: {
|
|
122
|
+
console.error('unsupported message', decodedMessage);
|
|
123
|
+
return shouldNeverHappen();
|
|
145
124
|
}
|
|
146
125
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
ws.send(encodeOutgoingMessage(WSMessage.Error.make({ message: error.message, requestId })));
|
|
129
|
+
}
|
|
130
|
+
}).pipe(Effect.withSpan('@livestore/sync-cf:durable-object:webSocketMessage'), Effect.tapCauseLogPretty, Logger.withMinimumLogLevel(LogLevel.Debug), Effect.provide(Logger.pretty), Effect.runPromise);
|
|
131
|
+
webSocketClose = async (ws, code, _reason, _wasClean) => {
|
|
132
|
+
// If the client closes the connection, the runtime will invoke the webSocketClose() handler.
|
|
133
|
+
ws.close(code, 'Durable Object is closing WebSocket');
|
|
155
134
|
};
|
|
156
|
-
}
|
|
135
|
+
}
|
|
157
136
|
const makeStorage = (ctx, env, dbName) => {
|
|
158
137
|
const getLatestEvent = async () => {
|
|
159
|
-
const rawEvents = await env.DB.prepare(`SELECT * FROM ${dbName} ORDER BY
|
|
138
|
+
const rawEvents = await env.DB.prepare(`SELECT * FROM ${dbName} ORDER BY idGlobal DESC LIMIT 1`).all();
|
|
160
139
|
if (rawEvents.error) {
|
|
161
140
|
throw new Error(rawEvents.error);
|
|
162
141
|
}
|
|
163
|
-
const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results)
|
|
142
|
+
const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results).map((e) => ({
|
|
143
|
+
...e,
|
|
144
|
+
// TODO remove local ids
|
|
145
|
+
id: { global: e.idGlobal, local: 0 },
|
|
146
|
+
parentId: { global: e.parentIdGlobal, local: 0 },
|
|
147
|
+
}));
|
|
164
148
|
return events[0];
|
|
165
149
|
};
|
|
166
150
|
const getEvents = async (cursor) => {
|
|
167
|
-
const whereClause = cursor === undefined ? '' : `WHERE
|
|
168
|
-
const sql = `SELECT * FROM ${dbName} ${whereClause} ORDER BY
|
|
151
|
+
const whereClause = cursor === undefined ? '' : `WHERE idGlobal > ${cursor}`;
|
|
152
|
+
const sql = `SELECT * FROM ${dbName} ${whereClause} ORDER BY idGlobal ASC`;
|
|
169
153
|
// TODO handle case where `cursor` was not found
|
|
170
154
|
const rawEvents = await env.DB.prepare(sql).all();
|
|
171
155
|
if (rawEvents.error) {
|
|
172
156
|
throw new Error(rawEvents.error);
|
|
173
157
|
}
|
|
174
|
-
const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results).map(({ createdAt, ...
|
|
175
|
-
mutationEventEncoded
|
|
158
|
+
const events = Schema.decodeUnknownSync(Schema.Array(mutationLogTable.schema))(rawEvents.results).map(({ createdAt, ...e }) => ({
|
|
159
|
+
mutationEventEncoded: {
|
|
160
|
+
...e,
|
|
161
|
+
// TODO remove local ids
|
|
162
|
+
id: { global: e.idGlobal, local: 0 },
|
|
163
|
+
parentId: { global: e.parentIdGlobal, local: 0 },
|
|
164
|
+
},
|
|
176
165
|
metadata: Option.some({ createdAt }),
|
|
177
166
|
}));
|
|
178
167
|
return events;
|
|
179
168
|
};
|
|
180
169
|
const appendEvent = async (event, createdAt) => {
|
|
181
|
-
const sql = `INSERT INTO ${dbName} (
|
|
170
|
+
const sql = `INSERT INTO ${dbName} (idGlobal, parentIdGlobal, args, mutation, createdAt) VALUES (?, ?, ?, ?, ?)`;
|
|
182
171
|
await env.DB.prepare(sql)
|
|
183
|
-
.bind(event.id, event.parentId, JSON.stringify(event.args), event.mutation, createdAt)
|
|
172
|
+
.bind(event.id.global, event.parentId.global, JSON.stringify(event.args), event.mutation, createdAt)
|
|
184
173
|
.run();
|
|
185
174
|
};
|
|
186
175
|
const resetRoom = async () => {
|
|
187
176
|
await ctx.storage.deleteAll();
|
|
188
177
|
};
|
|
189
|
-
return {
|
|
190
|
-
};
|
|
191
|
-
const getStoreId = (request) => {
|
|
192
|
-
const url = new URL(request.url);
|
|
193
|
-
const searchParams = url.searchParams;
|
|
194
|
-
const storeId = searchParams.get('storeId');
|
|
195
|
-
if (storeId === null) {
|
|
196
|
-
throw new Error('storeId search param is required');
|
|
197
|
-
}
|
|
198
|
-
return storeId;
|
|
178
|
+
return { getLatestEvent, getEvents, appendEvent, resetRoom };
|
|
199
179
|
};
|
|
200
|
-
const toValidTableName = (str) => str.replaceAll(/[^a-zA-Z0-9]/g, '_');
|
|
201
180
|
//# sourceMappingURL=durable-object.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../../src/cf-worker/durable-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAsB,MAAM,0BAA0B,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../../src/cf-worker/durable-object.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
/// <reference no-default-lib="true"/>
|
|
2
|
-
|
|
2
|
+
import type { Env } from './durable-object.js';
|
|
3
|
+
export * from './durable-object.js';
|
|
4
|
+
declare const _default: {
|
|
5
|
+
fetch: (request: Request, env: Env, _ctx: ExecutionContext) => Promise<Response>;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
3
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":";AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AAE9C,cAAc,qBAAqB,CAAA;;qBA4CV,OAAO,OAAO,GAAG,QAAQ,gBAAgB,KAAG,OAAO,CAAC,QAAQ,CAAC;;AADtF,wBAgCC"}
|
package/dist/cf-worker/index.js
CHANGED
|
@@ -1,33 +1,67 @@
|
|
|
1
1
|
/// <reference no-default-lib="true"/>
|
|
2
2
|
/// <reference lib="esnext" />
|
|
3
|
-
export
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// },
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
3
|
+
export * from './durable-object.js';
|
|
4
|
+
// const handleRequest = (request: Request, env: Env) =>
|
|
5
|
+
// HttpServer.router.empty.pipe(
|
|
6
|
+
// HttpServer.router.get(
|
|
7
|
+
// '/websocket',
|
|
8
|
+
// Effect.gen(function* () {
|
|
9
|
+
// // This example will refer to the same Durable Object instance,
|
|
10
|
+
// // since the name "foo" is hardcoded.
|
|
11
|
+
// const id = env.WEBSOCKET_SERVER.idFromName('foo')
|
|
12
|
+
// const durableObject = env.WEBSOCKET_SERVER.get(id)
|
|
13
|
+
// HttpServer.
|
|
14
|
+
// // Expect to receive a WebSocket Upgrade request.
|
|
15
|
+
// // If there is one, accept the request and return a WebSocket Response.
|
|
16
|
+
// const headerRes = yield* HttpServer.request
|
|
17
|
+
// .schemaHeaders(
|
|
18
|
+
// Schema.Struct({
|
|
19
|
+
// Upgrade: Schema.Literal('websocket'),
|
|
20
|
+
// }),
|
|
21
|
+
// )
|
|
22
|
+
// .pipe(Effect.either)
|
|
23
|
+
// if (headerRes._tag === 'Left') {
|
|
24
|
+
// // return new Response('Durable Object expected Upgrade: websocket', { status: 426 })
|
|
25
|
+
// return yield* HttpServer.response.text('Durable Object expected Upgrade: websocket', { status: 426 })
|
|
26
|
+
// }
|
|
27
|
+
// HttpServer.response.empty
|
|
28
|
+
// return yield* Effect.promise(() => durableObject.fetch(request))
|
|
29
|
+
// }),
|
|
30
|
+
// ),
|
|
31
|
+
// HttpServer.router.catchAll((e) => {
|
|
32
|
+
// console.log(e)
|
|
33
|
+
// return HttpServer.response.empty({ status: 400 })
|
|
34
|
+
// }),
|
|
35
|
+
// (_) => HttpServer.app.toWebHandler(_)(request),
|
|
36
|
+
// // request
|
|
37
|
+
// )
|
|
38
|
+
// Worker
|
|
39
|
+
export default {
|
|
40
|
+
fetch: async (request, env, _ctx) => {
|
|
41
|
+
const url = new URL(request.url);
|
|
42
|
+
const searchParams = url.searchParams;
|
|
43
|
+
const roomId = searchParams.get('room');
|
|
44
|
+
if (roomId === null) {
|
|
45
|
+
return new Response('Room ID is required', { status: 400 });
|
|
46
|
+
}
|
|
47
|
+
// This example will refer to the same Durable Object instance,
|
|
48
|
+
// since the name "foo" is hardcoded.
|
|
49
|
+
const id = env.WEBSOCKET_SERVER.idFromName(roomId);
|
|
50
|
+
const durableObject = env.WEBSOCKET_SERVER.get(id);
|
|
51
|
+
if (url.pathname.endsWith('/websocket')) {
|
|
52
|
+
const upgradeHeader = request.headers.get('Upgrade');
|
|
53
|
+
if (!upgradeHeader || upgradeHeader !== 'websocket') {
|
|
54
|
+
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
|
|
55
|
+
}
|
|
56
|
+
return durableObject.fetch(request);
|
|
57
|
+
}
|
|
58
|
+
return new Response(null, {
|
|
59
|
+
status: 400,
|
|
60
|
+
statusText: 'Bad Request',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': 'text/plain',
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
};
|
|
33
67
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,8BAA8B
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cf-worker/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,8BAA8B;AAO9B,cAAc,qBAAqB,CAAA;AAEnC,wDAAwD;AACxD,kCAAkC;AAClC,6BAA6B;AAC7B,sBAAsB;AACtB,kCAAkC;AAClC,0EAA0E;AAC1E,gDAAgD;AAChD,4DAA4D;AAC5D,6DAA6D;AAE7D,sBAAsB;AAEtB,4DAA4D;AAC5D,kFAAkF;AAClF,sDAAsD;AACtD,4BAA4B;AAC5B,8BAA8B;AAC9B,sDAAsD;AACtD,kBAAkB;AAClB,cAAc;AACd,iCAAiC;AAEjC,2CAA2C;AAC3C,kGAAkG;AAClG,kHAAkH;AAClH,YAAY;AAEZ,oCAAoC;AAEpC,2EAA2E;AAC3E,YAAY;AACZ,SAAS;AACT,0CAA0C;AAC1C,uBAAuB;AACvB,0DAA0D;AAC1D,UAAU;AACV,sDAAsD;AACtD,iBAAiB;AACjB,MAAM;AAEN,SAAS;AACT,eAAe;IACb,KAAK,EAAE,KAAK,EAAE,OAAgB,EAAE,GAAQ,EAAE,IAAsB,EAAqB,EAAE;QACrF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAA;QACrC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAEvC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,QAAQ,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC7D,CAAC;QAED,+DAA+D;QAC/D,qCAAqC;QACrC,MAAM,EAAE,GAAG,GAAG,CAAC,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAClD,MAAM,aAAa,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAElD,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACxC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACpD,IAAI,CAAC,aAAa,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;gBACpD,OAAO,IAAI,QAAQ,CAAC,4CAA4C,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YACpF,CAAC;YAED,OAAO,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC;QAED,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;YACxB,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,aAAa;YACzB,OAAO,EAAE;gBACP,cAAc,EAAE,YAAY;aAC7B;SACF,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|