@verdant-web/server 3.3.11 → 4.0.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/bin/server.mjs +110 -107
- package/dist/esm/TokenVerifier.d.ts +1 -0
- package/dist/esm/TokenVerifier.js +3 -0
- package/dist/esm/TokenVerifier.js.map +1 -1
- package/dist/esm/adapters/node/errorHandler.d.ts +2 -0
- package/dist/esm/adapters/node/errorHandler.js +12 -0
- package/dist/esm/adapters/node/errorHandler.js.map +1 -0
- package/dist/esm/adapters/node/getRequestToken.d.ts +1 -0
- package/dist/esm/adapters/node/getRequestToken.js +25 -0
- package/dist/esm/adapters/node/getRequestToken.js.map +1 -0
- package/dist/esm/adapters/node/httpRouter.d.ts +47 -0
- package/dist/esm/adapters/node/httpRouter.js +88 -0
- package/dist/esm/adapters/node/httpRouter.js.map +1 -0
- package/dist/esm/adapters/node/index.d.ts +5 -0
- package/dist/esm/adapters/node/index.js +6 -0
- package/dist/esm/adapters/node/index.js.map +1 -0
- package/dist/esm/adapters/node/tokenMiddleware.d.ts +7 -0
- package/dist/esm/adapters/node/tokenMiddleware.js +22 -0
- package/dist/esm/adapters/node/tokenMiddleware.js.map +1 -0
- package/dist/esm/adapters/node/websocketHandler.d.ts +4 -0
- package/dist/esm/adapters/node/websocketHandler.js +54 -0
- package/dist/esm/adapters/node/websocketHandler.js.map +1 -0
- package/dist/esm/connections/ClientConnection.d.ts +25 -0
- package/dist/esm/{ClientConnection.js → connections/ClientConnection.js} +47 -38
- package/dist/esm/connections/ClientConnection.js.map +1 -0
- package/dist/esm/connections/MessageSender.d.ts +5 -0
- package/dist/esm/connections/MessageSender.js.map +1 -0
- package/dist/esm/connections/Presence.d.ts +23 -0
- package/dist/esm/connections/Presence.js +65 -0
- package/dist/esm/connections/Presence.js.map +1 -0
- package/dist/esm/core.d.ts +15 -0
- package/dist/esm/core.js +15 -0
- package/dist/esm/core.js.map +1 -0
- package/dist/esm/defaults.d.ts +2 -0
- package/dist/esm/defaults.js +3 -0
- package/dist/esm/defaults.js.map +1 -0
- package/dist/esm/files/FileStorage.d.ts +12 -3
- package/dist/esm/files/FileStorage.js +20 -0
- package/dist/esm/files/FileStorage.js.map +1 -1
- package/dist/esm/index.d.ts +7 -7
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internals.d.ts +14 -0
- package/dist/esm/internals.js +12 -0
- package/dist/esm/internals.js.map +1 -0
- package/dist/esm/libraries/Library.d.ts +78 -0
- package/dist/esm/{ServerLibrary.js → libraries/Library.js} +153 -144
- package/dist/esm/libraries/Library.js.map +1 -0
- package/dist/esm/{ServerLibrary.test.js → libraries/Library.test.js} +42 -33
- package/dist/esm/libraries/Library.test.js.map +1 -0
- package/dist/esm/libraries/generic.d.ts +8 -0
- package/dist/esm/libraries/generic.js +2 -0
- package/dist/esm/libraries/generic.js.map +1 -0
- package/dist/esm/libraries/singleNode.d.ts +53 -0
- package/dist/esm/libraries/singleNode.js +88 -0
- package/dist/esm/libraries/singleNode.js.map +1 -0
- package/dist/esm/logger.d.ts +1 -0
- package/dist/esm/logger.js +2 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/storage/Storage.d.ts +39 -38
- package/dist/esm/storage/StorageManager.d.ts +11 -0
- package/dist/esm/storage/StorageManager.js +32 -0
- package/dist/esm/storage/StorageManager.js.map +1 -0
- package/dist/esm/storage/index.d.ts +1 -2
- package/dist/esm/storage/index.js +1 -2
- package/dist/esm/storage/index.js.map +1 -1
- package/dist/esm/storage/sqlShard/Databases.d.ts +5 -3
- package/dist/esm/storage/sqlShard/Databases.js +11 -7
- package/dist/esm/storage/sqlShard/Databases.js.map +1 -1
- package/dist/esm/storage/sqlShard/SqlBaselines.d.ts +16 -17
- package/dist/esm/storage/sqlShard/SqlBaselines.js +55 -59
- package/dist/esm/storage/sqlShard/SqlBaselines.js.map +1 -1
- package/dist/esm/storage/sqlShard/SqlFileMetadata.d.ts +13 -13
- package/dist/esm/storage/sqlShard/SqlFileMetadata.js +44 -57
- package/dist/esm/storage/sqlShard/SqlFileMetadata.js.map +1 -1
- package/dist/esm/storage/sqlShard/SqlOperations.d.ts +12 -12
- package/dist/esm/storage/sqlShard/SqlOperations.js +38 -73
- package/dist/esm/storage/sqlShard/SqlOperations.js.map +1 -1
- package/dist/esm/storage/sqlShard/SqlReplicas.d.ts +18 -17
- package/dist/esm/storage/sqlShard/SqlReplicas.js +63 -100
- package/dist/esm/storage/sqlShard/SqlReplicas.js.map +1 -1
- package/dist/esm/storage/sqlShard/database.d.ts +25 -5
- package/dist/esm/storage/sqlShard/database.js +47 -15
- package/dist/esm/storage/sqlShard/database.js.map +1 -1
- package/dist/esm/storage/sqlShard/migrations/v1.d.ts +2 -3
- package/dist/esm/storage/sqlShard/migrations/v1.js +42 -47
- package/dist/esm/storage/sqlShard/migrations/v1.js.map +1 -1
- package/dist/esm/storage/sqlShard/migrations/v2.d.ts +2 -3
- package/dist/esm/storage/sqlShard/migrations/v2.js +5 -15
- package/dist/esm/storage/sqlShard/migrations/v2.js.map +1 -1
- package/dist/esm/storage/sqlShard/migrations.d.ts +5 -7
- package/dist/esm/storage/sqlShard/migrations.js +48 -1
- package/dist/esm/storage/sqlShard/migrations.js.map +1 -1
- package/dist/esm/storage/sqlShard/sqlShardStorage.d.ts +25 -4
- package/dist/esm/storage/sqlShard/sqlShardStorage.js +43 -40
- package/dist/esm/storage/sqlShard/sqlShardStorage.js.map +1 -1
- package/dist/esm/storage/sqlShard/tables.d.ts +9 -6
- package/dist/esm/types.d.ts +1 -2
- package/package.json +24 -13
- package/src/TokenVerifier.ts +4 -0
- package/src/adapters/node/errorHandler.ts +18 -0
- package/src/adapters/node/getRequestToken.ts +34 -0
- package/src/adapters/node/httpRouter.ts +139 -0
- package/src/adapters/node/index.ts +5 -0
- package/src/adapters/node/tokenMiddleware.ts +32 -0
- package/src/adapters/node/websocketHandler.ts +79 -0
- package/src/{ClientConnection.ts → connections/ClientConnection.ts} +64 -57
- package/src/connections/MessageSender.ts +6 -0
- package/src/connections/Presence.ts +95 -0
- package/src/core.ts +36 -0
- package/src/defaults.ts +2 -0
- package/src/files/FileStorage.ts +36 -3
- package/src/index.ts +7 -7
- package/src/internals.ts +14 -0
- package/src/{ServerLibrary.test.ts → libraries/Library.test.ts} +51 -49
- package/src/{ServerLibrary.ts → libraries/Library.ts} +203 -206
- package/src/libraries/generic.ts +9 -0
- package/src/libraries/singleNode.ts +145 -0
- package/src/logger.ts +4 -0
- package/src/storage/Storage.ts +37 -66
- package/src/storage/StorageManager.ts +39 -0
- package/src/storage/index.ts +1 -2
- package/src/storage/sqlShard/Databases.ts +26 -13
- package/src/storage/sqlShard/SqlBaselines.ts +58 -67
- package/src/storage/sqlShard/SqlFileMetadata.ts +51 -72
- package/src/storage/sqlShard/SqlOperations.ts +57 -81
- package/src/storage/sqlShard/SqlReplicas.ts +80 -121
- package/src/storage/sqlShard/database.ts +82 -18
- package/src/storage/sqlShard/migrations/v1.ts +42 -52
- package/src/storage/sqlShard/migrations/v2.ts +5 -19
- package/src/storage/sqlShard/migrations.ts +66 -1
- package/src/storage/sqlShard/sqlShardStorage.ts +56 -55
- package/src/storage/sqlShard/tables.ts +6 -6
- package/src/types.ts +1 -2
- package/dist/esm/ClientConnection.d.ts +0 -19
- package/dist/esm/ClientConnection.js.map +0 -1
- package/dist/esm/MessageSender.d.ts +0 -5
- package/dist/esm/MessageSender.js.map +0 -1
- package/dist/esm/Presence.d.ts +0 -18
- package/dist/esm/Presence.js +0 -65
- package/dist/esm/Presence.js.map +0 -1
- package/dist/esm/ReplicaKeepaliveTimers.d.ts +0 -17
- package/dist/esm/ReplicaKeepaliveTimers.js +0 -27
- package/dist/esm/ReplicaKeepaliveTimers.js.map +0 -1
- package/dist/esm/Server.d.ts +0 -166
- package/dist/esm/Server.js +0 -572
- package/dist/esm/Server.js.map +0 -1
- package/dist/esm/ServerLibrary.d.ts +0 -64
- package/dist/esm/ServerLibrary.js.map +0 -1
- package/dist/esm/ServerLibrary.test.js.map +0 -1
- package/dist/esm/storage/sql/SqlBaselines.d.ts +0 -22
- package/dist/esm/storage/sql/SqlBaselines.js +0 -107
- package/dist/esm/storage/sql/SqlBaselines.js.map +0 -1
- package/dist/esm/storage/sql/SqlFileMetadata.d.ts +0 -18
- package/dist/esm/storage/sql/SqlFileMetadata.js +0 -69
- package/dist/esm/storage/sql/SqlFileMetadata.js.map +0 -1
- package/dist/esm/storage/sql/SqlOperations.d.ts +0 -19
- package/dist/esm/storage/sql/SqlOperations.js +0 -122
- package/dist/esm/storage/sql/SqlOperations.js.map +0 -1
- package/dist/esm/storage/sql/SqlReplicas.d.ts +0 -32
- package/dist/esm/storage/sql/SqlReplicas.js +0 -163
- package/dist/esm/storage/sql/SqlReplicas.js.map +0 -1
- package/dist/esm/storage/sql/database.d.ts +0 -9
- package/dist/esm/storage/sql/database.js +0 -24
- package/dist/esm/storage/sql/database.js.map +0 -1
- package/dist/esm/storage/sql/migrations/v1.d.ts +0 -3
- package/dist/esm/storage/sql/migrations/v1.js +0 -59
- package/dist/esm/storage/sql/migrations/v1.js.map +0 -1
- package/dist/esm/storage/sql/migrations/v2.d.ts +0 -3
- package/dist/esm/storage/sql/migrations/v2.js +0 -16
- package/dist/esm/storage/sql/migrations/v2.js.map +0 -1
- package/dist/esm/storage/sql/migrations.d.ts +0 -7
- package/dist/esm/storage/sql/migrations.js +0 -4
- package/dist/esm/storage/sql/migrations.js.map +0 -1
- package/dist/esm/storage/sql/sqlStorage.d.ts +0 -6
- package/dist/esm/storage/sql/sqlStorage.js +0 -35
- package/dist/esm/storage/sql/sqlStorage.js.map +0 -1
- package/dist/esm/storage/sql/tables.d.ts +0 -44
- package/dist/esm/storage/sql/tables.js +0 -2
- package/dist/esm/storage/sql/tables.js.map +0 -1
- package/dist/esm/storage/sqlShard/transfer.d.ts +0 -7
- package/dist/esm/storage/sqlShard/transfer.js +0 -90
- package/dist/esm/storage/sqlShard/transfer.js.map +0 -1
- package/dist/esm/storage/sqlShard/transfer.test.d.ts +0 -1
- package/dist/esm/storage/sqlShard/transfer.test.js +0 -109
- package/dist/esm/storage/sqlShard/transfer.test.js.map +0 -1
- package/src/MessageSender.ts +0 -10
- package/src/Presence.ts +0 -86
- package/src/ReplicaKeepaliveTimers.ts +0 -34
- package/src/Server.ts +0 -859
- package/src/storage/sql/SqlBaselines.ts +0 -147
- package/src/storage/sql/SqlFileMetadata.ts +0 -94
- package/src/storage/sql/SqlOperations.ts +0 -160
- package/src/storage/sql/SqlReplicas.ts +0 -234
- package/src/storage/sql/database.ts +0 -32
- package/src/storage/sql/migrations/v1.ts +0 -64
- package/src/storage/sql/migrations/v2.ts +0 -20
- package/src/storage/sql/migrations.ts +0 -4
- package/src/storage/sql/sqlStorage.ts +0 -57
- package/src/storage/sql/tables.ts +0 -51
- package/src/storage/sqlShard/transfer.test.ts +0 -149
- package/src/storage/sqlShard/transfer.ts +0 -123
- /package/dist/esm/{MessageSender.js → connections/MessageSender.js} +0 -0
- /package/dist/esm/{ServerLibrary.test.d.ts → libraries/Library.test.d.ts} +0 -0
|
@@ -1,18 +1,67 @@
|
|
|
1
|
-
import { Kysely, SqliteDialect } from 'kysely';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { Database as DatabaseTypes } from './tables.js';
|
|
4
1
|
import Database from 'better-sqlite3';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { Logger } from '../../logger.js';
|
|
4
|
+
import { migrateToLatest } from './migrations.js';
|
|
5
|
+
|
|
6
|
+
export interface SqliteExecutor {
|
|
7
|
+
query: <O extends Record<string, any>>(
|
|
8
|
+
sql: string,
|
|
9
|
+
parameters?: readonly unknown[],
|
|
10
|
+
) => O[];
|
|
11
|
+
first: <O extends Record<string, any>>(
|
|
12
|
+
sql: string,
|
|
13
|
+
parameters?: readonly unknown[],
|
|
14
|
+
) => O | null;
|
|
15
|
+
exec: (sql: string, parameters?: readonly unknown[]) => void;
|
|
16
|
+
migrate: () => void;
|
|
17
|
+
close: () => void;
|
|
18
|
+
transaction: <T>(cb: (tx: SqliteExecutor) => T) => T | Promise<T>;
|
|
19
|
+
migrated: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class SqliteExecutor {
|
|
23
|
+
private log;
|
|
24
|
+
constructor(
|
|
25
|
+
partial: Pick<SqliteExecutor, 'query' | 'exec' | 'close'> & {
|
|
26
|
+
createTransaction: (
|
|
27
|
+
exec: SqliteExecutor,
|
|
28
|
+
) => <T>(cb: (tx: SqliteExecutor) => T) => T | Promise<T>;
|
|
29
|
+
},
|
|
30
|
+
{ log }: { log?: Logger } = {},
|
|
31
|
+
) {
|
|
32
|
+
this.log = log || (() => {});
|
|
33
|
+
this.query = partial.query.bind(this) as any;
|
|
34
|
+
this.exec = partial.exec.bind(this);
|
|
35
|
+
this.close = partial.close.bind(this);
|
|
36
|
+
this.transaction = partial.createTransaction(this);
|
|
37
|
+
}
|
|
7
38
|
|
|
8
|
-
|
|
39
|
+
migrate = () => {
|
|
40
|
+
return migrateToLatest(this, this.log);
|
|
41
|
+
};
|
|
42
|
+
first = <O extends Record<string, any>>(
|
|
43
|
+
sql: string,
|
|
44
|
+
parameters?: readonly unknown[],
|
|
45
|
+
): O | null => {
|
|
46
|
+
const results = this.query<O>(sql, parameters);
|
|
47
|
+
return results[0] ?? null;
|
|
48
|
+
};
|
|
49
|
+
migrated = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function openDatabase(executor: SqliteExecutor) {
|
|
53
|
+
executor.migrate();
|
|
54
|
+
return executor;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function createFilesystemExecutor(
|
|
9
58
|
directory: string,
|
|
10
59
|
libraryId: string,
|
|
11
60
|
options: {
|
|
12
|
-
skipMigrations?: boolean;
|
|
13
61
|
disableWal?: boolean;
|
|
62
|
+
log?: Logger;
|
|
14
63
|
} = {},
|
|
15
|
-
) {
|
|
64
|
+
): SqliteExecutor {
|
|
16
65
|
const label = `openDatabase ${libraryId}`;
|
|
17
66
|
console.time(label);
|
|
18
67
|
const filePath =
|
|
@@ -23,15 +72,30 @@ export async function openDatabase(
|
|
|
23
72
|
if (!options.disableWal) {
|
|
24
73
|
internalDb.pragma('journal_mode = WAL');
|
|
25
74
|
}
|
|
26
|
-
const db = new Kysely<DatabaseTypes>({
|
|
27
|
-
dialect: new SqliteDialect({
|
|
28
|
-
database: internalDb,
|
|
29
|
-
}),
|
|
30
|
-
});
|
|
31
|
-
// only migrate on first open
|
|
32
|
-
if (!options.skipMigrations) {
|
|
33
|
-
await migrateToLatest(db, migrations);
|
|
34
|
-
}
|
|
35
75
|
console.timeEnd(label);
|
|
36
|
-
|
|
76
|
+
|
|
77
|
+
return new SqliteExecutor(
|
|
78
|
+
{
|
|
79
|
+
query: function (sql, parameters = []) {
|
|
80
|
+
const stmt = internalDb.prepare(sql);
|
|
81
|
+
return stmt.all(...parameters) as any;
|
|
82
|
+
},
|
|
83
|
+
exec: function (sql, parameters = []) {
|
|
84
|
+
const stmt = internalDb.prepare(sql);
|
|
85
|
+
stmt.run(...parameters);
|
|
86
|
+
},
|
|
87
|
+
close: function () {
|
|
88
|
+
internalDb.close();
|
|
89
|
+
},
|
|
90
|
+
createTransaction: (exec) => (cb) => {
|
|
91
|
+
const tx = internalDb.transaction(() => {
|
|
92
|
+
return cb(exec);
|
|
93
|
+
});
|
|
94
|
+
return tx();
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
log: options.log ?? (() => {}),
|
|
99
|
+
},
|
|
100
|
+
);
|
|
37
101
|
}
|
|
@@ -1,53 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
export const version = 1;
|
|
2
2
|
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.addColumn('pendingDeleteAt', 'integer')
|
|
45
|
-
.execute();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function down(db: Kysely<any>) {
|
|
49
|
-
await db.schema.dropTable('DocumentBaseline').execute();
|
|
50
|
-
await db.schema.dropTable('OperationHistory').execute();
|
|
51
|
-
await db.schema.dropTable('ReplicaInfo').execute();
|
|
52
|
-
await db.schema.dropTable('FileMetadata').execute();
|
|
53
|
-
}
|
|
3
|
+
export const up = [
|
|
4
|
+
`
|
|
5
|
+
CREATE TABLE IF NOT EXISTS "_Migrations" (
|
|
6
|
+
"id" INTEGER PRIMARY KEY,
|
|
7
|
+
"appliedAt" TEXT NOT NULL
|
|
8
|
+
);`,
|
|
9
|
+
`
|
|
10
|
+
CREATE TABLE IF NOT EXISTS "DocumentBaseline" (
|
|
11
|
+
"oid" TEXT PRIMARY KEY,
|
|
12
|
+
"snapshot" TEXT,
|
|
13
|
+
"timestamp" TEXT NOT NULL
|
|
14
|
+
);
|
|
15
|
+
`,
|
|
16
|
+
`
|
|
17
|
+
CREATE TABLE IF NOT EXISTS "OperationHistory" (
|
|
18
|
+
"oid" TEXT NOT NULL,
|
|
19
|
+
"timestamp" TEXT NOT NULL,
|
|
20
|
+
"data" TEXT NOT NULL,
|
|
21
|
+
"serverOrder" INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
"replicaId" TEXT NOT NULL,
|
|
23
|
+
PRIMARY KEY ("replicaId", "oid", "timestamp")
|
|
24
|
+
);
|
|
25
|
+
`,
|
|
26
|
+
`
|
|
27
|
+
CREATE TABLE IF NOT EXISTS "ReplicaInfo" (
|
|
28
|
+
"id" TEXT PRIMARY KEY,
|
|
29
|
+
"clientId" TEXT NOT NULL,
|
|
30
|
+
"lastSeenWallClockTime" INTEGER,
|
|
31
|
+
"ackedLogicalTime" TEXT,
|
|
32
|
+
"type" INTEGER NOT NULL DEFAULT 0,
|
|
33
|
+
"ackedServerOrder" INTEGER NOT NULL DEFAULT 0
|
|
34
|
+
);`,
|
|
35
|
+
`
|
|
36
|
+
CREATE TABLE IF NOT EXISTS "FileMetadata" (
|
|
37
|
+
"fileId" TEXT PRIMARY KEY,
|
|
38
|
+
"name" TEXT NOT NULL,
|
|
39
|
+
"type" TEXT NOT NULL,
|
|
40
|
+
"pendingDeleteAt" INTEGER
|
|
41
|
+
);
|
|
42
|
+
`,
|
|
43
|
+
];
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
export const version = 2;
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
.addColumn('authz', 'text', (cb) => cb.defaultTo(null))
|
|
8
|
-
.execute();
|
|
9
|
-
|
|
10
|
-
await db.schema
|
|
11
|
-
.alterTable('DocumentBaseline')
|
|
12
|
-
.addColumn('authz', 'text', (cb) => cb.defaultTo(null))
|
|
13
|
-
.execute();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function down(db: Kysely<any>) {
|
|
17
|
-
await db.schema.alterTable('OperationHistory').dropColumn('authz').execute();
|
|
18
|
-
|
|
19
|
-
await db.schema.alterTable('DocumentBaseline').dropColumn('authz').execute();
|
|
20
|
-
}
|
|
3
|
+
export const up = [
|
|
4
|
+
`ALTER TABLE "OperationHistory" ADD COLUMN "authz" TEXT DEFAULT NULL;`,
|
|
5
|
+
`ALTER TABLE "DocumentBaseline" ADD COLUMN "authz" TEXT DEFAULT NULL;`,
|
|
6
|
+
];
|
|
@@ -1,4 +1,69 @@
|
|
|
1
|
+
import { Logger } from '../../logger.js';
|
|
2
|
+
import { SqliteExecutor } from './database.js';
|
|
1
3
|
import * as v1 from './migrations/v1.js';
|
|
2
4
|
import * as v2 from './migrations/v2.js';
|
|
3
5
|
|
|
4
|
-
export
|
|
6
|
+
export function getMigrationVersion(run: SqliteExecutor['query']) {
|
|
7
|
+
try {
|
|
8
|
+
const result = run(
|
|
9
|
+
`SELECT id FROM _Migrations
|
|
10
|
+
ORDER BY id DESC
|
|
11
|
+
LIMIT 1;`,
|
|
12
|
+
);
|
|
13
|
+
const value = result[0]?.id ?? 0;
|
|
14
|
+
return value;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
if (
|
|
17
|
+
e instanceof Error &&
|
|
18
|
+
e.message.includes('no such table: _Migrations')
|
|
19
|
+
) {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
throw e;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function updateMigrationVersion(
|
|
27
|
+
run: SqliteExecutor['exec'],
|
|
28
|
+
version: number,
|
|
29
|
+
) {
|
|
30
|
+
run(`INSERT INTO _Migrations (id, appliedAt) VALUES (?, ?)`, [
|
|
31
|
+
version,
|
|
32
|
+
Date.now(),
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function migrateToLatest(
|
|
37
|
+
e: Pick<SqliteExecutor, 'exec' | 'query' | 'migrated'>,
|
|
38
|
+
log: Logger,
|
|
39
|
+
) {
|
|
40
|
+
const allMigrations = [v1, v2];
|
|
41
|
+
|
|
42
|
+
const currentVersion = getMigrationVersion(e.query);
|
|
43
|
+
|
|
44
|
+
const pendingMigrations = allMigrations.slice(currentVersion);
|
|
45
|
+
if (pendingMigrations.length === 0) {
|
|
46
|
+
e.migrated = true;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
log('info', `Applying ${pendingMigrations.length} pending migrations...`);
|
|
50
|
+
for (const migration of pendingMigrations) {
|
|
51
|
+
for (const step of migration.up) {
|
|
52
|
+
try {
|
|
53
|
+
e.exec(step);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
log('error', `Error applying migration v${migration.version}:`, err);
|
|
56
|
+
log('error', `SQL:`, step);
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
log('info', `Applied migration v${migration.version}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
updateMigrationVersion(
|
|
64
|
+
e.exec,
|
|
65
|
+
allMigrations[allMigrations.length - 1].version,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
e.migrated = true;
|
|
69
|
+
}
|
|
@@ -1,81 +1,82 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import {
|
|
3
|
+
defaultFileExpirationDays,
|
|
4
|
+
defaultReplicaTruancyMinutes,
|
|
5
|
+
} from '../../defaults.js';
|
|
6
|
+
import { Logger } from '../../logger.js';
|
|
7
|
+
import { Storage, StorageFactory, StorageOptions } from '../Storage.js';
|
|
8
|
+
import { Databases } from './Databases.js';
|
|
4
9
|
import { SqlBaselines } from './SqlBaselines.js';
|
|
10
|
+
import { SqlFileMetadata } from './SqlFileMetadata.js';
|
|
5
11
|
import { SqlOperations } from './SqlOperations.js';
|
|
6
12
|
import { SqlReplicas } from './SqlReplicas.js';
|
|
7
|
-
import {
|
|
8
|
-
import { SqlFileMetadata } from './SqlFileMetadata.js';
|
|
9
|
-
import { migrateToLatest } from '@a-type/kysely';
|
|
10
|
-
import migrations from './migrations.js';
|
|
11
|
-
import { Databases } from './Databases.js';
|
|
12
|
-
import { transferToShards } from './transfer.js';
|
|
13
|
-
import { existsSync, mkdirSync, readdirSync } from 'fs';
|
|
13
|
+
import { SqliteExecutor } from './database.js';
|
|
14
14
|
|
|
15
15
|
export const sqlShardStorage = ({
|
|
16
16
|
databasesDirectory,
|
|
17
|
-
transferFromUnifiedDatabaseFile,
|
|
18
17
|
disableWal,
|
|
19
18
|
closeTimeout,
|
|
19
|
+
fileDeleteExpirationDays = defaultFileExpirationDays,
|
|
20
|
+
replicaTruancyMinutes = defaultReplicaTruancyMinutes,
|
|
21
|
+
log,
|
|
20
22
|
}: {
|
|
21
23
|
databasesDirectory: string;
|
|
22
|
-
transferFromUnifiedDatabaseFile?: string;
|
|
23
24
|
disableWal?: boolean;
|
|
24
25
|
closeTimeout?: number;
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
databases?: Databases;
|
|
27
|
+
log?: Logger;
|
|
28
|
+
} & StorageOptions): StorageFactory => {
|
|
27
29
|
if (databasesDirectory !== ':memory:' && !existsSync(databasesDirectory)) {
|
|
28
30
|
mkdirSync(databasesDirectory);
|
|
29
31
|
console.info(`Created databases directory: ${databasesDirectory}`);
|
|
30
32
|
}
|
|
31
|
-
if (transferFromUnifiedDatabaseFile) {
|
|
32
|
-
// check if directory is empty
|
|
33
|
-
const files =
|
|
34
|
-
databasesDirectory === ':memory:' ? [] : readdirSync(databasesDirectory);
|
|
35
|
-
if (files.length > 0) {
|
|
36
|
-
console.error(
|
|
37
|
-
`Cannot transfer from unified database to non-empty directory: ${databasesDirectory}. This might mean the transfer has already happened and you're free to turn off the transferFromUnifiedDatabaseFile option.`,
|
|
38
|
-
);
|
|
39
|
-
} else {
|
|
40
|
-
ready = transferToShards({
|
|
41
|
-
file: transferFromUnifiedDatabaseFile,
|
|
42
|
-
directory: databasesDirectory,
|
|
43
|
-
}).then();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
33
|
const dbs = new Databases({
|
|
47
34
|
directory: databasesDirectory,
|
|
48
35
|
disableWal,
|
|
49
36
|
closeTimeout,
|
|
37
|
+
log,
|
|
50
38
|
});
|
|
51
|
-
return (
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
return async (libraryId) => {
|
|
40
|
+
const db = await dbs.get(libraryId);
|
|
41
|
+
return new SqlShardStorage(db, {
|
|
42
|
+
fileDeleteExpirationDays,
|
|
43
|
+
replicaTruancyMinutes,
|
|
44
|
+
libraryId,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export class SqlShardStorage implements Storage {
|
|
50
|
+
baselines;
|
|
51
|
+
operations;
|
|
52
|
+
replicas;
|
|
53
|
+
fileMetadata;
|
|
54
|
+
|
|
55
|
+
#open = true;
|
|
56
|
+
get open() {
|
|
57
|
+
return this.#open;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
constructor(
|
|
61
|
+
private db: SqliteExecutor,
|
|
62
|
+
options: Required<StorageOptions> & { libraryId: string },
|
|
63
|
+
) {
|
|
64
|
+
this.baselines = new SqlBaselines(db, options.libraryId);
|
|
65
|
+
this.operations = new SqlOperations(db, options.libraryId);
|
|
66
|
+
this.replicas = new SqlReplicas(
|
|
67
|
+
db,
|
|
68
|
+
options.libraryId,
|
|
56
69
|
options.replicaTruancyMinutes,
|
|
57
|
-
'sqlite',
|
|
58
70
|
);
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
this.fileMetadata = new SqlFileMetadata(
|
|
72
|
+
db,
|
|
73
|
+
options.libraryId,
|
|
61
74
|
options.fileDeleteExpirationDays,
|
|
62
|
-
'sqlite',
|
|
63
75
|
);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
baselines,
|
|
70
|
-
operations,
|
|
71
|
-
replicas,
|
|
72
|
-
fileMetadata,
|
|
73
|
-
close,
|
|
74
|
-
open: false,
|
|
75
|
-
ready: ready.then(() => {
|
|
76
|
-
storage.open = true;
|
|
77
|
-
}),
|
|
78
|
-
};
|
|
79
|
-
return storage;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
close = async () => {
|
|
79
|
+
this.#open = false;
|
|
80
|
+
await this.db.close();
|
|
80
81
|
};
|
|
81
|
-
}
|
|
82
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ReplicaType } from '@verdant-web/common';
|
|
2
|
-
import { Generated, Selectable } from 'kysely';
|
|
3
2
|
|
|
4
3
|
export interface Database {
|
|
5
4
|
OperationHistory: OperationHistoryTable;
|
|
6
5
|
DocumentBaseline: DocumentBaselineTable;
|
|
7
6
|
ReplicaInfo: ReplicaInfoTable;
|
|
8
7
|
FileMetadata: FileMetadataTable;
|
|
8
|
+
_Migrations: { id: number; appliedAt: string };
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface OperationHistoryTable {
|
|
@@ -16,7 +16,7 @@ export interface OperationHistoryTable {
|
|
|
16
16
|
replicaId: string;
|
|
17
17
|
authz: string | null;
|
|
18
18
|
}
|
|
19
|
-
export type OperationHistoryRow =
|
|
19
|
+
export type OperationHistoryRow = OperationHistoryTable;
|
|
20
20
|
|
|
21
21
|
export interface DocumentBaselineTable {
|
|
22
22
|
oid: string;
|
|
@@ -24,7 +24,7 @@ export interface DocumentBaselineTable {
|
|
|
24
24
|
timestamp: string;
|
|
25
25
|
authz: string | null;
|
|
26
26
|
}
|
|
27
|
-
export type DocumentBaselineRow =
|
|
27
|
+
export type DocumentBaselineRow = DocumentBaselineTable;
|
|
28
28
|
|
|
29
29
|
export interface ReplicaInfoTable {
|
|
30
30
|
id: string;
|
|
@@ -32,10 +32,10 @@ export interface ReplicaInfoTable {
|
|
|
32
32
|
lastSeenWallClockTime: number | null;
|
|
33
33
|
ackedLogicalTime: string | null;
|
|
34
34
|
type: ReplicaType;
|
|
35
|
-
ackedServerOrder:
|
|
35
|
+
ackedServerOrder: number;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export type ReplicaInfoRow =
|
|
38
|
+
export type ReplicaInfoRow = ReplicaInfoTable;
|
|
39
39
|
|
|
40
40
|
export interface FileMetadataTable {
|
|
41
41
|
fileId: string;
|
|
@@ -44,4 +44,4 @@ export interface FileMetadataTable {
|
|
|
44
44
|
pendingDeleteAt: number | null;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export type FileMetadataRow =
|
|
47
|
+
export type FileMetadataRow = FileMetadataTable;
|
package/src/types.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface StoredReplicaInfo extends ReplicaInfo {
|
|
|
30
30
|
ackedServerOrder: number;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export type LibraryInfo
|
|
33
|
+
export type LibraryInfo = {
|
|
34
34
|
id: string;
|
|
35
35
|
replicas: {
|
|
36
36
|
id: string;
|
|
@@ -38,7 +38,6 @@ export type LibraryInfo<Profile = unknown> = {
|
|
|
38
38
|
ackedServerOrder: number;
|
|
39
39
|
type: ReplicaType;
|
|
40
40
|
truant: boolean;
|
|
41
|
-
profile: Profile;
|
|
42
41
|
}[];
|
|
43
42
|
latestServerOrder: number;
|
|
44
43
|
operationsCount: number;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { ServerMessage } from '@verdant-web/common';
|
|
2
|
-
import { IncomingMessage, ServerResponse } from 'http';
|
|
3
|
-
import { WebSocket } from 'ws';
|
|
4
|
-
import { TokenInfo } from './TokenVerifier.js';
|
|
5
|
-
export declare class ClientConnectionManager {
|
|
6
|
-
private readonly connections;
|
|
7
|
-
private getLibraryConnections;
|
|
8
|
-
addSocket: (libraryId: string, key: string, socket: WebSocket, info: TokenInfo) => void;
|
|
9
|
-
addRequest: (libraryId: string, key: string, request: IncomingMessage, response: ServerResponse, info: TokenInfo) => () => void;
|
|
10
|
-
addFetch: (libraryId: string, key: string, req: Request, info: TokenInfo) => (() => Response);
|
|
11
|
-
remove: (libraryId: string, key: string) => void;
|
|
12
|
-
respond: (libraryId: string, key: string, message: ServerMessage) => void;
|
|
13
|
-
/**
|
|
14
|
-
* Broadcasts a message to all live-connected clients in a library.
|
|
15
|
-
* This does not reach push/pull clients.
|
|
16
|
-
*/
|
|
17
|
-
broadcast: (libraryId: string, message: ServerMessage, omitKeys?: string[]) => void;
|
|
18
|
-
disconnectAll: (libraryId: string) => void;
|
|
19
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClientConnection.js","sourceRoot":"","sources":["../../src/ClientConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA4B,MAAM,qBAAqB,CAAC;AAKtE,MAAe,gBAAgB;IAC9B,YACU,GAAW,EACD,IAAe;QADzB,QAAG,GAAH,GAAG,CAAQ;QACD,SAAI,GAAJ,IAAI,CAAW;QAInC,YAAO,GAAG,CAAC,OAAsB,EAAE,EAAE;YACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC;QAEM,mBAAc,GAAG,CAAC,OAAsB,EAAiB,EAAE;;YAClE,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACtB,KAAK,OAAO,CAAC,CAAC,CAAC;oBACd,uCACI,OAAO,KACV,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAChE,SAAS,EAAE,MAAA,OAAO,CAAC,SAAS,0CAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAC9D;gBACH,CAAC;gBACD,KAAK,WAAW,CAAC,CAAC,CAAC;oBAClB,uCACI,OAAO,KACV,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAChE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAC7D;gBACH,CAAC;gBACD;oBACC,OAAO,OAAO,CAAC;YACjB,CAAC;QACF,CAAC,CAAC;QAEM,yBAAoB,GAAG,CAAC,SAA6B,EAAE,EAAE;YAChE,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBACrB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC9C,gDAAgD;gBAChD,OAAO,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC,CAAC;IAnCC,CAAC;CAoCJ;AAED,MAAM,uBAAwB,SAAQ,gBAAgB;IAKrD,YACC,GAAW,EACM,GAAoB,EACpB,GAAmB,EACpC,IAAe;QAEf,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAJA,QAAG,GAAH,GAAG,CAAiB;QACpB,QAAG,GAAH,GAAG,CAAgB;QAP5B,SAAI,GAAG,SAAS,CAAC;QAElB,cAAS,GAAoB,EAAE,CAAC;QAWxC,kBAAa,GAAG,CAAC,OAAsB,EAAE,EAAE;YAC1C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAC;QAEF,QAAG,GAAG,GAAG,EAAE;YACV,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBACvB,cAAc,EAAE,kBAAkB;aAClC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,KAAK,CACb,IAAI,CAAC,SAAS,CAAC;gBACd,QAAQ,EAAE,IAAI,CAAC,SAAS;aACxB,CAAC,CACF,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC,CAAC;IAhBF,CAAC;CAiBD;AAED,MAAM,qBAAsB,SAAQ,gBAAgB;IAMnD,YACC,GAAW,EACM,GAAY,EAC7B,IAAe;QAEf,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAHA,QAAG,GAAH,GAAG,CAAS;QAPrB,SAAI,GAAG,OAAO,CAAC;QAEhB,cAAS,GAAoB,EAAE,CAAC;QACxC,QAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAUxC,kBAAa,GAAG,CAAC,OAAsB,EAAE,EAAE;YAC1C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAC;QAEF,QAAG,GAAG,GAAG,EAAE;YACV,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CACtB,IAAI,CAAC,SAAS,CAAC;gBACd,QAAQ,EAAE,IAAI,CAAC,SAAS;aACxB,CAAC,EACF;gBACC,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;iBAClC;aACD,CACD,CAAC;QACH,CAAC,CAAC;IAlBF,CAAC;CAmBD;AAED,MAAM,yBAA0B,SAAQ,gBAAgB;IAGvD,YACC,GAAW,EACF,EAAa,EACtB,IAAe;QAEf,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAHR,OAAE,GAAF,EAAE,CAAW;QAJd,SAAI,GAAG,WAAW,CAAC;QAU5B,kBAAa,GAAG,CAAC,OAAsB,EAAE,EAAE;YAC1C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC;IAJF,CAAC;CAKD;AAED,MAAM,OAAO,uBAAuB;IAApC;QACkB,gBAAW,GAC3B,EAAE,CAAC;QAEI,0BAAqB,GAAG,CAAC,SAAiB,EAAE,EAAE;YACrD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YACzC,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAE,CAAC;QACrC,CAAC,CAAC;QAEF,cAAS,GAAG,CACX,SAAiB,EACjB,GAAW,EACX,MAAiB,EACjB,IAAe,EACd,EAAE;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAElD,MAAM,UAAU,GAAG,IAAI,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAEpE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAEzB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACvB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF,eAAU,GAAG,CACZ,SAAiB,EACjB,GAAW,EACX,OAAwB,EACxB,QAAwB,EACxB,IAAe,EACd,EAAE;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAElD,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAC7C,GAAG,EACH,OAAO,EACP,QAAQ,EACR,IAAI,CACJ,CAAC;YAEF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAEzB,OAAO,GAAG,EAAE;gBACX,UAAU,CAAC,GAAG,EAAE,CAAC;gBACjB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC,CAAC;QACH,CAAC,CAAC;QAEF,aAAQ,GAAG,CACV,SAAiB,EACjB,GAAW,EACX,GAAY,EACZ,IAAe,EACI,EAAE;YACrB,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAElD,MAAM,UAAU,GAAG,IAAI,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAE7D,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAEzB,OAAO,GAAG,EAAE;gBACX,UAAU,CAAC,GAAG,EAAE,CAAC;gBACjB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO,UAAU,CAAC,GAAG,CAAC;YACvB,CAAC,CAAC;QACH,CAAC,CAAC;QAEF,WAAM,GAAG,CAAC,SAAiB,EAAE,GAAW,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAClD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC,CAAC;QAEF,YAAO,GAAG,CAAC,SAAiB,EAAE,GAAW,EAAE,OAAsB,EAAE,EAAE;YACpE,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,UAAU,EAAE,CAAC;gBAChB,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CACd,mCAAmC,SAAS,SAAS,GAAG,EAAE,CAC1D,CAAC;YACH,CAAC;QACF,CAAC,CAAC;QAEF;;;WAGG;QACH,cAAS,GAAG,CACX,SAAiB,EACjB,OAAsB,EACtB,WAAqB,EAAE,EACtB,EAAE;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAClD,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,GAAG,EAAE,CAAC;gBACrC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7B,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC7B,CAAC;YACF,CAAC;QACF,CAAC,CAAC;QAEF,kBAAa,GAAG,CAAC,SAAiB,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAClD,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvC,IAAI,UAAU,YAAY,yBAAyB,EAAE,CAAC;oBACrD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;gBACvB,CAAC;YACF,CAAC;YACD,GAAG,CAAC,KAAK,EAAE,CAAC;QACb,CAAC,CAAC;IACH,CAAC;CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MessageSender.js","sourceRoot":"","sources":["../../src/MessageSender.ts"],"names":[],"mappings":""}
|
package/dist/esm/Presence.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { UserInfo, UserInfoUpdate } from '@verdant-web/common';
|
|
2
|
-
import EventEmitter from 'events';
|
|
3
|
-
import { UserProfiles } from './Profiles.js';
|
|
4
|
-
/**
|
|
5
|
-
* Stores client presence in-memory for connected
|
|
6
|
-
* clients
|
|
7
|
-
*/
|
|
8
|
-
export declare class Presence extends EventEmitter {
|
|
9
|
-
private profiles;
|
|
10
|
-
private presences;
|
|
11
|
-
constructor(profiles: UserProfiles<any>);
|
|
12
|
-
private getLibrary;
|
|
13
|
-
set: (libraryId: string, userId: string, userInfo: UserInfoUpdate) => Promise<UserInfo<any, any>>;
|
|
14
|
-
get: (libraryId: string, userId: string) => UserInfo<any, any> | undefined;
|
|
15
|
-
removeReplica: (libraryId: string, replicaId: string) => void;
|
|
16
|
-
all: (libraryId: string) => Record<string, UserInfo<any, any>>;
|
|
17
|
-
clear: (libraryId: string) => void;
|
|
18
|
-
}
|
package/dist/esm/Presence.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { initialInternalPresence, } from '@verdant-web/common';
|
|
2
|
-
import EventEmitter from 'events';
|
|
3
|
-
/**
|
|
4
|
-
* Stores client presence in-memory for connected
|
|
5
|
-
* clients
|
|
6
|
-
*/
|
|
7
|
-
export class Presence extends EventEmitter {
|
|
8
|
-
constructor(profiles) {
|
|
9
|
-
super();
|
|
10
|
-
this.profiles = profiles;
|
|
11
|
-
this.presences = new Map();
|
|
12
|
-
this.getLibrary = (libraryId) => {
|
|
13
|
-
let map = this.presences.get(libraryId);
|
|
14
|
-
if (!map) {
|
|
15
|
-
map = {
|
|
16
|
-
presences: {},
|
|
17
|
-
replicaToUser: {},
|
|
18
|
-
userToReplica: {},
|
|
19
|
-
};
|
|
20
|
-
this.presences.set(libraryId, map);
|
|
21
|
-
}
|
|
22
|
-
return map;
|
|
23
|
-
};
|
|
24
|
-
this.set = async (libraryId, userId, userInfo) => {
|
|
25
|
-
const lib = this.getLibrary(libraryId);
|
|
26
|
-
if (!lib.presences[userId]) {
|
|
27
|
-
lib.presences[userId] = Object.assign(Object.assign({}, userInfo), { profile: await this.profiles.get(userId), internal: userInfo.internal || initialInternalPresence });
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
Object.assign(lib.presences[userId], userInfo);
|
|
31
|
-
}
|
|
32
|
-
lib.replicaToUser[userInfo.replicaId] = userId;
|
|
33
|
-
lib.userToReplica[userId] = lib.userToReplica[userId] || new Set();
|
|
34
|
-
lib.userToReplica[userId].add(userInfo.replicaId);
|
|
35
|
-
return lib.presences[userId];
|
|
36
|
-
};
|
|
37
|
-
this.get = (libraryId, userId) => {
|
|
38
|
-
var _a;
|
|
39
|
-
return (_a = this.presences.get(libraryId)) === null || _a === void 0 ? void 0 : _a.presences[userId];
|
|
40
|
-
};
|
|
41
|
-
this.removeReplica = (libraryId, replicaId) => {
|
|
42
|
-
const lib = this.getLibrary(libraryId);
|
|
43
|
-
const userId = lib.replicaToUser[replicaId];
|
|
44
|
-
if (!userId)
|
|
45
|
-
return;
|
|
46
|
-
lib.userToReplica[userId].delete(replicaId);
|
|
47
|
-
if (lib.userToReplica[userId].size === 0) {
|
|
48
|
-
delete lib.presences[userId];
|
|
49
|
-
this.emit('lost', libraryId, replicaId, userId);
|
|
50
|
-
// memory cleanup
|
|
51
|
-
if (Object.keys(lib.presences).length === 0) {
|
|
52
|
-
this.clear(libraryId);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
this.all = (libraryId) => {
|
|
57
|
-
var _a;
|
|
58
|
-
return ((_a = this.presences.get(libraryId)) === null || _a === void 0 ? void 0 : _a.presences) || {};
|
|
59
|
-
};
|
|
60
|
-
this.clear = (libraryId) => {
|
|
61
|
-
this.presences.delete(libraryId);
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=Presence.js.map
|
package/dist/esm/Presence.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Presence.js","sourceRoot":"","sources":["../../src/Presence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { EventSubscriber } from '@verdant-web/common';
|
|
2
|
-
/**
|
|
3
|
-
* A set of timers per-replica which are
|
|
4
|
-
* refreshed whenever the replica sends
|
|
5
|
-
* a message to the server. If a timer expires,
|
|
6
|
-
* the replica is removed from presence. This
|
|
7
|
-
* is a failsafe for socket-based replicas but
|
|
8
|
-
* essential for pull-based replicas.
|
|
9
|
-
*/
|
|
10
|
-
export declare class ReplicaKeepaliveTimers extends EventSubscriber<{
|
|
11
|
-
lost: (libraryId: string, replicaId: string) => void;
|
|
12
|
-
}> {
|
|
13
|
-
private timeout;
|
|
14
|
-
private timers;
|
|
15
|
-
constructor(timeout?: number);
|
|
16
|
-
refresh: (libraryId: string, replicaId: string) => void;
|
|
17
|
-
}
|