@verdant-web/server 1.7.8 → 1.7.10
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/cjs/Baselines.d.ts +14 -14
- package/dist/cjs/Baselines.js +77 -77
- package/dist/cjs/ClientConnection.d.ts +18 -18
- package/dist/cjs/ClientConnection.js +105 -105
- package/dist/cjs/MessageSender.d.ts +5 -5
- package/dist/cjs/MessageSender.js +2 -2
- package/dist/cjs/OperationHistory.d.ts +34 -34
- package/dist/cjs/OperationHistory.js +108 -108
- package/dist/cjs/Presence.d.ts +15 -15
- package/dist/cjs/Presence.js +59 -59
- package/dist/cjs/Profiles.d.ts +10 -10
- package/dist/cjs/Profiles.js +19 -19
- package/dist/cjs/ReplicaKeepaliveTimers.d.ts +17 -17
- package/dist/cjs/ReplicaKeepaliveTimers.js +30 -30
- package/dist/cjs/Replicas.d.ts +23 -23
- package/dist/cjs/Replicas.js +132 -132
- package/dist/cjs/Server.d.ts +121 -121
- package/dist/cjs/Server.js +385 -377
- package/dist/cjs/Server.js.map +1 -1
- package/dist/cjs/ServerLibrary.d.ts +63 -63
- package/dist/cjs/ServerLibrary.js +467 -467
- package/dist/cjs/TokenProvider.d.ts +16 -16
- package/dist/cjs/TokenProvider.js +26 -26
- package/dist/cjs/TokenVerifier.d.ts +16 -16
- package/dist/cjs/TokenVerifier.js +28 -28
- package/dist/cjs/files/FileMetadata.d.ts +28 -28
- package/dist/cjs/files/FileMetadata.js +46 -46
- package/dist/cjs/files/FileStorage.d.ts +35 -35
- package/dist/cjs/files/FileStorage.js +71 -71
- package/dist/cjs/index.d.ts +9 -9
- package/dist/cjs/index.js +11 -11
- package/dist/cjs/migrations/v0.sql.d.ts +2 -2
- package/dist/cjs/migrations/v0.sql.js +3 -3
- package/dist/cjs/migrations/v1.sql.d.ts +2 -2
- package/dist/cjs/migrations/v1.sql.js +3 -3
- package/dist/cjs/migrations/v2.sql.d.ts +2 -2
- package/dist/cjs/migrations/v2.sql.js +4 -4
- package/dist/cjs/migrations/v3.sql.d.ts +2 -2
- package/dist/cjs/migrations/v3.sql.js +4 -4
- package/dist/cjs/migrations/v4.sql.d.ts +2 -2
- package/dist/cjs/migrations/v4.sql.js +4 -4
- package/dist/cjs/migrations.d.ts +2 -2
- package/dist/cjs/migrations.js +32 -32
- package/dist/cjs/types.d.ts +22 -22
- package/dist/cjs/types.js +2 -2
- package/dist/esm/Baselines.d.ts +14 -14
- package/dist/esm/Baselines.js +73 -73
- package/dist/esm/ClientConnection.d.ts +18 -18
- package/dist/esm/ClientConnection.js +101 -101
- package/dist/esm/MessageSender.d.ts +5 -5
- package/dist/esm/MessageSender.js +1 -1
- package/dist/esm/OperationHistory.d.ts +34 -34
- package/dist/esm/OperationHistory.js +104 -104
- package/dist/esm/Presence.d.ts +15 -15
- package/dist/esm/Presence.js +52 -52
- package/dist/esm/Profiles.d.ts +10 -10
- package/dist/esm/Profiles.js +15 -15
- package/dist/esm/ReplicaKeepaliveTimers.d.ts +17 -17
- package/dist/esm/ReplicaKeepaliveTimers.js +26 -26
- package/dist/esm/Replicas.d.ts +23 -23
- package/dist/esm/Replicas.js +128 -128
- package/dist/esm/Server.d.ts +121 -121
- package/dist/esm/Server.js +378 -370
- package/dist/esm/Server.js.map +1 -1
- package/dist/esm/ServerLibrary.d.ts +63 -63
- package/dist/esm/ServerLibrary.js +463 -463
- package/dist/esm/TokenProvider.d.ts +16 -16
- package/dist/esm/TokenProvider.js +19 -19
- package/dist/esm/TokenVerifier.d.ts +16 -16
- package/dist/esm/TokenVerifier.js +21 -21
- package/dist/esm/files/FileMetadata.d.ts +28 -28
- package/dist/esm/files/FileMetadata.js +42 -42
- package/dist/esm/files/FileStorage.d.ts +35 -35
- package/dist/esm/files/FileStorage.js +44 -44
- package/dist/esm/index.d.ts +9 -9
- package/dist/esm/index.js +4 -4
- package/dist/esm/migrations/v0.sql.d.ts +2 -2
- package/dist/esm/migrations/v0.sql.js +1 -1
- package/dist/esm/migrations/v1.sql.d.ts +2 -2
- package/dist/esm/migrations/v1.sql.js +1 -1
- package/dist/esm/migrations/v2.sql.d.ts +2 -2
- package/dist/esm/migrations/v2.sql.js +2 -2
- package/dist/esm/migrations/v3.sql.d.ts +2 -2
- package/dist/esm/migrations/v3.sql.js +2 -2
- package/dist/esm/migrations/v4.sql.d.ts +2 -2
- package/dist/esm/migrations/v4.sql.js +2 -2
- package/dist/esm/migrations.d.ts +2 -2
- package/dist/esm/migrations.js +25 -25
- package/dist/esm/types.d.ts +22 -22
- package/dist/esm/types.js +1 -1
- package/dist/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/Server.ts +9 -2
- package/dist/cjs/ServerStorage.d.ts +0 -35
- package/dist/cjs/ServerStorage.js +0 -60
- package/dist/cjs/ServerStorage.js.map +0 -1
- package/dist/esm/ServerStorage.d.ts +0 -44
- package/dist/esm/ServerStorage.js +0 -58
- package/dist/esm/ServerStorage.js.map +0 -1
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
class ClientConnection {
|
|
2
|
-
constructor(key) {
|
|
3
|
-
this.key = key;
|
|
4
|
-
}
|
|
5
|
-
}
|
|
6
|
-
class RequestClientConnection extends ClientConnection {
|
|
7
|
-
constructor(key, req, res, info) {
|
|
8
|
-
super(key);
|
|
9
|
-
this.req = req;
|
|
10
|
-
this.res = res;
|
|
11
|
-
this.info = info;
|
|
12
|
-
this.type = 'request';
|
|
13
|
-
this.responses = [];
|
|
14
|
-
this.respond = (message) => {
|
|
15
|
-
this.responses.push(message);
|
|
16
|
-
};
|
|
17
|
-
this.end = () => {
|
|
18
|
-
this.res.writeHead(200, {
|
|
19
|
-
'Content-Type': 'application/json',
|
|
20
|
-
});
|
|
21
|
-
this.res.write(JSON.stringify({
|
|
22
|
-
messages: this.responses,
|
|
23
|
-
}));
|
|
24
|
-
this.res.end();
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
class WebSocketClientConnection extends ClientConnection {
|
|
29
|
-
constructor(key, ws, info) {
|
|
30
|
-
super(key);
|
|
31
|
-
this.ws = ws;
|
|
32
|
-
this.info = info;
|
|
33
|
-
this.type = 'websocket';
|
|
34
|
-
this.respond = (message) => {
|
|
35
|
-
this.ws.send(JSON.stringify(message));
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export class ClientConnectionManager {
|
|
40
|
-
constructor() {
|
|
41
|
-
this.connections = {};
|
|
42
|
-
this.getLibraryConnections = (libraryId) => {
|
|
43
|
-
if (!this.connections[libraryId]) {
|
|
44
|
-
this.connections[libraryId] = new Map();
|
|
45
|
-
}
|
|
46
|
-
return this.connections[libraryId];
|
|
47
|
-
};
|
|
48
|
-
this.addSocket = (libraryId, key, socket, info) => {
|
|
49
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
50
|
-
const connection = new WebSocketClientConnection(key, socket, info);
|
|
51
|
-
lib.set(key, connection);
|
|
52
|
-
socket.on('close', () => {
|
|
53
|
-
lib.delete(key);
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
this.addRequest = (libraryId, key, request, response, info) => {
|
|
57
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
58
|
-
const connection = new RequestClientConnection(key, request, response, info);
|
|
59
|
-
lib.set(key, connection);
|
|
60
|
-
return () => {
|
|
61
|
-
connection.end();
|
|
62
|
-
lib.delete(key);
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
this.remove = (libraryId, key) => {
|
|
66
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
67
|
-
lib.delete(key);
|
|
68
|
-
};
|
|
69
|
-
this.respond = (libraryId, key, message) => {
|
|
70
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
71
|
-
const connection = lib.get(key);
|
|
72
|
-
if (connection) {
|
|
73
|
-
connection.respond(message);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
throw new Error(`No connection found for library ${libraryId}, key ${key}`);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* Broadcasts a message to all live-connected clients in a library.
|
|
81
|
-
* This does not reach push/pull clients.
|
|
82
|
-
*/
|
|
83
|
-
this.broadcast = (libraryId, message, omitKeys = []) => {
|
|
84
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
85
|
-
for (const [key, connection] of lib) {
|
|
86
|
-
if (!omitKeys.includes(key)) {
|
|
87
|
-
connection.respond(message);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
this.disconnectAll = (libraryId) => {
|
|
92
|
-
const lib = this.getLibraryConnections(libraryId);
|
|
93
|
-
for (const connection of lib.values()) {
|
|
94
|
-
if (connection instanceof WebSocketClientConnection) {
|
|
95
|
-
connection.ws.close();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
lib.clear();
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
1
|
+
class ClientConnection {
|
|
2
|
+
constructor(key) {
|
|
3
|
+
this.key = key;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
class RequestClientConnection extends ClientConnection {
|
|
7
|
+
constructor(key, req, res, info) {
|
|
8
|
+
super(key);
|
|
9
|
+
this.req = req;
|
|
10
|
+
this.res = res;
|
|
11
|
+
this.info = info;
|
|
12
|
+
this.type = 'request';
|
|
13
|
+
this.responses = [];
|
|
14
|
+
this.respond = (message) => {
|
|
15
|
+
this.responses.push(message);
|
|
16
|
+
};
|
|
17
|
+
this.end = () => {
|
|
18
|
+
this.res.writeHead(200, {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
});
|
|
21
|
+
this.res.write(JSON.stringify({
|
|
22
|
+
messages: this.responses,
|
|
23
|
+
}));
|
|
24
|
+
this.res.end();
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class WebSocketClientConnection extends ClientConnection {
|
|
29
|
+
constructor(key, ws, info) {
|
|
30
|
+
super(key);
|
|
31
|
+
this.ws = ws;
|
|
32
|
+
this.info = info;
|
|
33
|
+
this.type = 'websocket';
|
|
34
|
+
this.respond = (message) => {
|
|
35
|
+
this.ws.send(JSON.stringify(message));
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class ClientConnectionManager {
|
|
40
|
+
constructor() {
|
|
41
|
+
this.connections = {};
|
|
42
|
+
this.getLibraryConnections = (libraryId) => {
|
|
43
|
+
if (!this.connections[libraryId]) {
|
|
44
|
+
this.connections[libraryId] = new Map();
|
|
45
|
+
}
|
|
46
|
+
return this.connections[libraryId];
|
|
47
|
+
};
|
|
48
|
+
this.addSocket = (libraryId, key, socket, info) => {
|
|
49
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
50
|
+
const connection = new WebSocketClientConnection(key, socket, info);
|
|
51
|
+
lib.set(key, connection);
|
|
52
|
+
socket.on('close', () => {
|
|
53
|
+
lib.delete(key);
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
this.addRequest = (libraryId, key, request, response, info) => {
|
|
57
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
58
|
+
const connection = new RequestClientConnection(key, request, response, info);
|
|
59
|
+
lib.set(key, connection);
|
|
60
|
+
return () => {
|
|
61
|
+
connection.end();
|
|
62
|
+
lib.delete(key);
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
this.remove = (libraryId, key) => {
|
|
66
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
67
|
+
lib.delete(key);
|
|
68
|
+
};
|
|
69
|
+
this.respond = (libraryId, key, message) => {
|
|
70
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
71
|
+
const connection = lib.get(key);
|
|
72
|
+
if (connection) {
|
|
73
|
+
connection.respond(message);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
throw new Error(`No connection found for library ${libraryId}, key ${key}`);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Broadcasts a message to all live-connected clients in a library.
|
|
81
|
+
* This does not reach push/pull clients.
|
|
82
|
+
*/
|
|
83
|
+
this.broadcast = (libraryId, message, omitKeys = []) => {
|
|
84
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
85
|
+
for (const [key, connection] of lib) {
|
|
86
|
+
if (!omitKeys.includes(key)) {
|
|
87
|
+
connection.respond(message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
this.disconnectAll = (libraryId) => {
|
|
92
|
+
const lib = this.getLibraryConnections(libraryId);
|
|
93
|
+
for (const connection of lib.values()) {
|
|
94
|
+
if (connection instanceof WebSocketClientConnection) {
|
|
95
|
+
connection.ws.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
lib.clear();
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
102
|
//# sourceMappingURL=ClientConnection.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ServerMessage } from '@verdant-web/common';
|
|
2
|
-
export interface MessageSender {
|
|
3
|
-
broadcast(libraryId: string, message: ServerMessage, omitKeys?: string[]): void;
|
|
4
|
-
send(libraryId: string, clientKey: string, message: ServerMessage): void;
|
|
5
|
-
}
|
|
1
|
+
import { ServerMessage } from '@verdant-web/common';
|
|
2
|
+
export interface MessageSender {
|
|
3
|
+
broadcast(libraryId: string, message: ServerMessage, omitKeys?: string[]): void;
|
|
4
|
+
send(libraryId: string, clientKey: string, message: ServerMessage): void;
|
|
5
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=MessageSender.js.map
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { Operation } from '@verdant-web/common';
|
|
2
|
-
import { Database } from 'better-sqlite3';
|
|
3
|
-
import { OperationSpec } from './types.js';
|
|
4
|
-
export declare class OperationHistory {
|
|
5
|
-
private db;
|
|
6
|
-
constructor(db: Database);
|
|
7
|
-
private hydratePatch;
|
|
8
|
-
getAllFor: (libraryId: string, oid: string) => OperationSpec[];
|
|
9
|
-
getEarliest: (libraryId: string, count: number) => OperationSpec[];
|
|
10
|
-
getAfter: (libraryId: string, timestamp?: string | null) => OperationSpec[];
|
|
11
|
-
/**
|
|
12
|
-
* Returns all operations before the given timestamp
|
|
13
|
-
* in ascending chronological order
|
|
14
|
-
*/
|
|
15
|
-
getBefore: (libraryId: string, before: string) => OperationSpec[];
|
|
16
|
-
/**
|
|
17
|
-
* Returns all operations after a given server order. Useful
|
|
18
|
-
* for retrieving operations that were created after a client
|
|
19
|
-
* last synced.
|
|
20
|
-
*/
|
|
21
|
-
getFromServerOrder: (libraryId: string, serverOrder: number) => OperationSpec[];
|
|
22
|
-
/**
|
|
23
|
-
* Adds a new operation or replaces an existing one.
|
|
24
|
-
* The server order will be set to the current max + 1
|
|
25
|
-
*/
|
|
26
|
-
insert: (libraryId: string, replicaId: string, item: Operation) => import("better-sqlite3").RunResult;
|
|
27
|
-
/**
|
|
28
|
-
* Inserts all operations and updates the server
|
|
29
|
-
* order for this library
|
|
30
|
-
*/
|
|
31
|
-
insertAll: (libraryId: string, replicaId: string, items: Operation[]) => Promise<void>;
|
|
32
|
-
dropAll: (libraryId: string, items: Pick<OperationSpec, 'replicaId' | 'oid' | 'timestamp'>[]) => Promise<void>;
|
|
33
|
-
deleteAll: (libraryId: string) => void;
|
|
34
|
-
}
|
|
1
|
+
import { Operation } from '@verdant-web/common';
|
|
2
|
+
import { Database } from 'better-sqlite3';
|
|
3
|
+
import { OperationSpec } from './types.js';
|
|
4
|
+
export declare class OperationHistory {
|
|
5
|
+
private db;
|
|
6
|
+
constructor(db: Database);
|
|
7
|
+
private hydratePatch;
|
|
8
|
+
getAllFor: (libraryId: string, oid: string) => OperationSpec[];
|
|
9
|
+
getEarliest: (libraryId: string, count: number) => OperationSpec[];
|
|
10
|
+
getAfter: (libraryId: string, timestamp?: string | null) => OperationSpec[];
|
|
11
|
+
/**
|
|
12
|
+
* Returns all operations before the given timestamp
|
|
13
|
+
* in ascending chronological order
|
|
14
|
+
*/
|
|
15
|
+
getBefore: (libraryId: string, before: string) => OperationSpec[];
|
|
16
|
+
/**
|
|
17
|
+
* Returns all operations after a given server order. Useful
|
|
18
|
+
* for retrieving operations that were created after a client
|
|
19
|
+
* last synced.
|
|
20
|
+
*/
|
|
21
|
+
getFromServerOrder: (libraryId: string, serverOrder: number) => OperationSpec[];
|
|
22
|
+
/**
|
|
23
|
+
* Adds a new operation or replaces an existing one.
|
|
24
|
+
* The server order will be set to the current max + 1
|
|
25
|
+
*/
|
|
26
|
+
insert: (libraryId: string, replicaId: string, item: Operation) => import("better-sqlite3").RunResult;
|
|
27
|
+
/**
|
|
28
|
+
* Inserts all operations and updates the server
|
|
29
|
+
* order for this library
|
|
30
|
+
*/
|
|
31
|
+
insertAll: (libraryId: string, replicaId: string, items: Operation[]) => Promise<void>;
|
|
32
|
+
dropAll: (libraryId: string, items: Pick<OperationSpec, 'replicaId' | 'oid' | 'timestamp'>[]) => Promise<void>;
|
|
33
|
+
deleteAll: (libraryId: string) => void;
|
|
34
|
+
}
|
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
export class OperationHistory {
|
|
13
|
-
constructor(db) {
|
|
14
|
-
this.db = db;
|
|
15
|
-
this.hydratePatch = (_a) => {
|
|
16
|
-
var { libraryId: _, data } = _a, rest = __rest(_a, ["libraryId", "data"]);
|
|
17
|
-
return Object.assign(Object.assign({}, rest), { data: JSON.parse(data) });
|
|
18
|
-
};
|
|
19
|
-
this.getAllFor = (libraryId, oid) => {
|
|
20
|
-
return this.db
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
export class OperationHistory {
|
|
13
|
+
constructor(db) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
this.hydratePatch = (_a) => {
|
|
16
|
+
var { libraryId: _, data } = _a, rest = __rest(_a, ["libraryId", "data"]);
|
|
17
|
+
return Object.assign(Object.assign({}, rest), { data: JSON.parse(data) });
|
|
18
|
+
};
|
|
19
|
+
this.getAllFor = (libraryId, oid) => {
|
|
20
|
+
return this.db
|
|
21
21
|
.prepare(`
|
|
22
22
|
SELECT * FROM OperationHistory
|
|
23
23
|
WHERE libraryId = ? AND oid = ?
|
|
24
24
|
ORDER BY timestamp ASC
|
|
25
|
-
`)
|
|
26
|
-
.all(libraryId, oid)
|
|
27
|
-
.map(this.hydratePatch);
|
|
28
|
-
};
|
|
29
|
-
this.getEarliest = (libraryId, count) => {
|
|
30
|
-
return this.db
|
|
25
|
+
`)
|
|
26
|
+
.all(libraryId, oid)
|
|
27
|
+
.map(this.hydratePatch);
|
|
28
|
+
};
|
|
29
|
+
this.getEarliest = (libraryId, count) => {
|
|
30
|
+
return this.db
|
|
31
31
|
.prepare(`
|
|
32
32
|
SELECT * FROM OperationHistory
|
|
33
33
|
WHERE libraryId = ?
|
|
34
34
|
ORDER BY timestamp ASC
|
|
35
35
|
LIMIT ?
|
|
36
|
-
`)
|
|
37
|
-
.all(libraryId, count)
|
|
38
|
-
.map(this.hydratePatch);
|
|
39
|
-
};
|
|
40
|
-
this.getAfter = (libraryId, timestamp = null) => {
|
|
41
|
-
if (timestamp === null) {
|
|
42
|
-
return this.db
|
|
36
|
+
`)
|
|
37
|
+
.all(libraryId, count)
|
|
38
|
+
.map(this.hydratePatch);
|
|
39
|
+
};
|
|
40
|
+
this.getAfter = (libraryId, timestamp = null) => {
|
|
41
|
+
if (timestamp === null) {
|
|
42
|
+
return this.db
|
|
43
43
|
.prepare(`
|
|
44
44
|
SELECT * FROM OperationHistory
|
|
45
45
|
WHERE libraryId = ?
|
|
46
46
|
ORDER BY timestamp ASC
|
|
47
|
-
`)
|
|
48
|
-
.all(libraryId)
|
|
49
|
-
.map(this.hydratePatch);
|
|
50
|
-
}
|
|
51
|
-
return this.db
|
|
47
|
+
`)
|
|
48
|
+
.all(libraryId)
|
|
49
|
+
.map(this.hydratePatch);
|
|
50
|
+
}
|
|
51
|
+
return this.db
|
|
52
52
|
.prepare(`
|
|
53
53
|
SELECT * FROM OperationHistory
|
|
54
54
|
WHERE libraryId = ? AND timestamp > ?
|
|
55
55
|
ORDER BY timestamp ASC
|
|
56
|
-
`)
|
|
57
|
-
.all(libraryId, timestamp)
|
|
58
|
-
.map(this.hydratePatch);
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Returns all operations before the given timestamp
|
|
62
|
-
* in ascending chronological order
|
|
63
|
-
*/
|
|
64
|
-
this.getBefore = (libraryId, before) => {
|
|
65
|
-
return this.db
|
|
56
|
+
`)
|
|
57
|
+
.all(libraryId, timestamp)
|
|
58
|
+
.map(this.hydratePatch);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Returns all operations before the given timestamp
|
|
62
|
+
* in ascending chronological order
|
|
63
|
+
*/
|
|
64
|
+
this.getBefore = (libraryId, before) => {
|
|
65
|
+
return this.db
|
|
66
66
|
.prepare(`
|
|
67
67
|
SELECT * FROM OperationHistory
|
|
68
68
|
WHERE libraryId = ? AND timestamp < ?
|
|
69
69
|
ORDER BY timestamp ASC
|
|
70
|
-
`)
|
|
71
|
-
.all(libraryId, before)
|
|
72
|
-
.map(this.hydratePatch);
|
|
73
|
-
};
|
|
74
|
-
/**
|
|
75
|
-
* Returns all operations after a given server order. Useful
|
|
76
|
-
* for retrieving operations that were created after a client
|
|
77
|
-
* last synced.
|
|
78
|
-
*/
|
|
79
|
-
this.getFromServerOrder = (libraryId, serverOrder) => {
|
|
80
|
-
const result = this.db
|
|
70
|
+
`)
|
|
71
|
+
.all(libraryId, before)
|
|
72
|
+
.map(this.hydratePatch);
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Returns all operations after a given server order. Useful
|
|
76
|
+
* for retrieving operations that were created after a client
|
|
77
|
+
* last synced.
|
|
78
|
+
*/
|
|
79
|
+
this.getFromServerOrder = (libraryId, serverOrder) => {
|
|
80
|
+
const result = this.db
|
|
81
81
|
.prepare(`
|
|
82
82
|
SELECT * FROM OperationHistory
|
|
83
83
|
WHERE libraryId = ? AND serverOrder > ?
|
|
84
|
-
`)
|
|
85
|
-
.all(libraryId, serverOrder);
|
|
86
|
-
return (result || []).map(this.hydratePatch);
|
|
87
|
-
};
|
|
88
|
-
/**
|
|
89
|
-
* Adds a new operation or replaces an existing one.
|
|
90
|
-
* The server order will be set to the current max + 1
|
|
91
|
-
*/
|
|
92
|
-
this.insert = (libraryId, replicaId, item) => {
|
|
93
|
-
return this.db
|
|
84
|
+
`)
|
|
85
|
+
.all(libraryId, serverOrder);
|
|
86
|
+
return (result || []).map(this.hydratePatch);
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Adds a new operation or replaces an existing one.
|
|
90
|
+
* The server order will be set to the current max + 1
|
|
91
|
+
*/
|
|
92
|
+
this.insert = (libraryId, replicaId, item) => {
|
|
93
|
+
return this.db
|
|
94
94
|
.prepare(`
|
|
95
95
|
INSERT OR REPLACE INTO OperationHistory (libraryId, oid, data, timestamp, replicaId, serverOrder)
|
|
96
96
|
VALUES (?, ?, ?, ?, ?, (SELECT COALESCE(MAX(serverOrder), 0) FROM OperationHistory WHERE libraryId = ?) + 1)
|
|
97
|
-
`)
|
|
98
|
-
.run(libraryId, item.oid, JSON.stringify(item.data), item.timestamp, replicaId);
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Inserts all operations and updates the server
|
|
102
|
-
* order for this library
|
|
103
|
-
*/
|
|
104
|
-
this.insertAll = async (libraryId, replicaId, items) => {
|
|
105
|
-
const tx = this.db.transaction(() => {
|
|
106
|
-
let orderResult = this.db
|
|
97
|
+
`)
|
|
98
|
+
.run(libraryId, item.oid, JSON.stringify(item.data), item.timestamp, replicaId);
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Inserts all operations and updates the server
|
|
102
|
+
* order for this library
|
|
103
|
+
*/
|
|
104
|
+
this.insertAll = async (libraryId, replicaId, items) => {
|
|
105
|
+
const tx = this.db.transaction(() => {
|
|
106
|
+
let orderResult = this.db
|
|
107
107
|
.prepare(`
|
|
108
108
|
SELECT COALESCE(MAX(serverOrder), 0) AS serverOrder FROM OperationHistory WHERE libraryId = ?
|
|
109
|
-
`)
|
|
110
|
-
.get(libraryId);
|
|
111
|
-
let currentServerOrder = orderResult.serverOrder || 0;
|
|
109
|
+
`)
|
|
110
|
+
.get(libraryId);
|
|
111
|
+
let currentServerOrder = orderResult.serverOrder || 0;
|
|
112
112
|
const insertStatement = this.db.prepare(`
|
|
113
113
|
INSERT OR REPLACE INTO OperationHistory (libraryId, oid, data, timestamp, replicaId, serverOrder)
|
|
114
114
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
115
|
-
`);
|
|
116
|
-
for (const item of items) {
|
|
117
|
-
insertStatement.run(libraryId, item.oid, JSON.stringify(item.data), item.timestamp, replicaId, ++currentServerOrder);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
tx();
|
|
121
|
-
};
|
|
122
|
-
this.dropAll = async (libraryId, items) => {
|
|
115
|
+
`);
|
|
116
|
+
for (const item of items) {
|
|
117
|
+
insertStatement.run(libraryId, item.oid, JSON.stringify(item.data), item.timestamp, replicaId, ++currentServerOrder);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
tx();
|
|
121
|
+
};
|
|
122
|
+
this.dropAll = async (libraryId, items) => {
|
|
123
123
|
const deleteStatement = this.db.prepare(`
|
|
124
124
|
DELETE FROM OperationHistory
|
|
125
125
|
WHERE libraryId = ? AND replicaId = ? AND oid = ? AND timestamp = ?
|
|
126
|
-
`);
|
|
127
|
-
this.db.transaction(() => {
|
|
128
|
-
for (const item of items) {
|
|
129
|
-
deleteStatement.run(libraryId, item.replicaId, item.oid, item.timestamp);
|
|
130
|
-
}
|
|
131
|
-
})();
|
|
132
|
-
};
|
|
133
|
-
this.deleteAll = (libraryId) => {
|
|
134
|
-
this.db
|
|
126
|
+
`);
|
|
127
|
+
this.db.transaction(() => {
|
|
128
|
+
for (const item of items) {
|
|
129
|
+
deleteStatement.run(libraryId, item.replicaId, item.oid, item.timestamp);
|
|
130
|
+
}
|
|
131
|
+
})();
|
|
132
|
+
};
|
|
133
|
+
this.deleteAll = (libraryId) => {
|
|
134
|
+
this.db
|
|
135
135
|
.prepare(`
|
|
136
136
|
DELETE FROM OperationHistory
|
|
137
137
|
WHERE libraryId = ?
|
|
138
|
-
`)
|
|
139
|
-
.run(libraryId);
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
138
|
+
`)
|
|
139
|
+
.run(libraryId);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
143
|
//# sourceMappingURL=OperationHistory.js.map
|
package/dist/esm/Presence.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { UserInfo } from '@verdant-web/common';
|
|
3
|
-
import EventEmitter from 'events';
|
|
4
|
-
/**
|
|
5
|
-
* Stores client presence in-memory for connected
|
|
6
|
-
* clients
|
|
7
|
-
*/
|
|
8
|
-
export declare class Presence extends EventEmitter {
|
|
9
|
-
private presences;
|
|
10
|
-
private getLibrary;
|
|
11
|
-
set: (libraryId: string, userId: string, presence: UserInfo<any, any>) => void;
|
|
12
|
-
removeReplica: (libraryId: string, replicaId: string) => void;
|
|
13
|
-
all: (libraryId: string) => Record<string, UserInfo<any, any>>;
|
|
14
|
-
clear: (libraryId: string) => void;
|
|
15
|
-
}
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { UserInfo } from '@verdant-web/common';
|
|
3
|
+
import EventEmitter from 'events';
|
|
4
|
+
/**
|
|
5
|
+
* Stores client presence in-memory for connected
|
|
6
|
+
* clients
|
|
7
|
+
*/
|
|
8
|
+
export declare class Presence extends EventEmitter {
|
|
9
|
+
private presences;
|
|
10
|
+
private getLibrary;
|
|
11
|
+
set: (libraryId: string, userId: string, presence: UserInfo<any, any>) => void;
|
|
12
|
+
removeReplica: (libraryId: string, replicaId: string) => void;
|
|
13
|
+
all: (libraryId: string) => Record<string, UserInfo<any, any>>;
|
|
14
|
+
clear: (libraryId: string) => void;
|
|
15
|
+
}
|