@quereus/sync-coordinator 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/bin/sync-coordinator.d.ts +6 -0
- package/dist/src/bin/sync-coordinator.d.ts.map +1 -0
- package/dist/src/bin/sync-coordinator.js +85 -0
- package/dist/src/bin/sync-coordinator.js.map +1 -0
- package/dist/src/common/index.d.ts +5 -0
- package/dist/src/common/index.d.ts.map +1 -0
- package/dist/src/common/index.js +5 -0
- package/dist/src/common/index.js.map +1 -0
- package/dist/src/common/logger.d.ts +20 -0
- package/dist/src/common/logger.d.ts.map +1 -0
- package/dist/src/common/logger.js +24 -0
- package/dist/src/common/logger.js.map +1 -0
- package/dist/src/config/index.d.ts +6 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +6 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/config/loader.d.ts +27 -0
- package/dist/src/config/loader.d.ts.map +1 -0
- package/dist/src/config/loader.js +144 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/config/types.d.ts +74 -0
- package/dist/src/config/types.d.ts.map +1 -0
- package/dist/src/config/types.js +27 -0
- package/dist/src/config/types.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +26 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/metrics/coordinator-metrics.d.ts +27 -0
- package/dist/src/metrics/coordinator-metrics.d.ts.map +1 -0
- package/dist/src/metrics/coordinator-metrics.js +57 -0
- package/dist/src/metrics/coordinator-metrics.js.map +1 -0
- package/dist/src/metrics/index.d.ts +7 -0
- package/dist/src/metrics/index.d.ts.map +1 -0
- package/dist/src/metrics/index.js +7 -0
- package/dist/src/metrics/index.js.map +1 -0
- package/dist/src/metrics/registry.d.ts +53 -0
- package/dist/src/metrics/registry.d.ts.map +1 -0
- package/dist/src/metrics/registry.js +158 -0
- package/dist/src/metrics/registry.js.map +1 -0
- package/dist/src/metrics/types.d.ts +62 -0
- package/dist/src/metrics/types.d.ts.map +1 -0
- package/dist/src/metrics/types.js +16 -0
- package/dist/src/metrics/types.js.map +1 -0
- package/dist/src/server/index.d.ts +7 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +7 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/routes.d.ts +10 -0
- package/dist/src/server/routes.d.ts.map +1 -0
- package/dist/src/server/routes.js +174 -0
- package/dist/src/server/routes.js.map +1 -0
- package/dist/src/server/server.d.ts +34 -0
- package/dist/src/server/server.d.ts.map +1 -0
- package/dist/src/server/server.js +57 -0
- package/dist/src/server/server.js.map +1 -0
- package/dist/src/server/websocket.d.ts +10 -0
- package/dist/src/server/websocket.d.ts.map +1 -0
- package/dist/src/server/websocket.js +167 -0
- package/dist/src/server/websocket.js.map +1 -0
- package/dist/src/service/coordinator-service.d.ts +122 -0
- package/dist/src/service/coordinator-service.d.ts.map +1 -0
- package/dist/src/service/coordinator-service.js +436 -0
- package/dist/src/service/coordinator-service.js.map +1 -0
- package/dist/src/service/database-ids.d.ts +58 -0
- package/dist/src/service/database-ids.d.ts.map +1 -0
- package/dist/src/service/database-ids.js +128 -0
- package/dist/src/service/database-ids.js.map +1 -0
- package/dist/src/service/index.d.ts +8 -0
- package/dist/src/service/index.d.ts.map +1 -0
- package/dist/src/service/index.js +7 -0
- package/dist/src/service/index.js.map +1 -0
- package/dist/src/service/store-manager.d.ts +85 -0
- package/dist/src/service/store-manager.d.ts.map +1 -0
- package/dist/src/service/store-manager.js +194 -0
- package/dist/src/service/store-manager.js.map +1 -0
- package/dist/src/service/types.d.ts +146 -0
- package/dist/src/service/types.d.ts.map +1 -0
- package/dist/src/service/types.js +5 -0
- package/dist/src/service/types.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fastify server setup for sync-coordinator.
|
|
3
|
+
*/
|
|
4
|
+
import { type FastifyInstance } from 'fastify';
|
|
5
|
+
import type { CoordinatorConfig } from '../config/types.js';
|
|
6
|
+
import { CoordinatorService } from '../service/coordinator-service.js';
|
|
7
|
+
import type { CoordinatorHooks } from '../service/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a coordinator server.
|
|
10
|
+
*/
|
|
11
|
+
export interface CoordinatorServerOptions {
|
|
12
|
+
/** Full configuration */
|
|
13
|
+
config: CoordinatorConfig;
|
|
14
|
+
/** Custom hooks for validation/auth */
|
|
15
|
+
hooks?: CoordinatorHooks;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Coordinator server instance.
|
|
19
|
+
*/
|
|
20
|
+
export interface CoordinatorServer {
|
|
21
|
+
/** The Fastify instance */
|
|
22
|
+
app: FastifyInstance;
|
|
23
|
+
/** The coordinator service */
|
|
24
|
+
service: CoordinatorService;
|
|
25
|
+
/** Start the server */
|
|
26
|
+
start(): Promise<void>;
|
|
27
|
+
/** Stop the server */
|
|
28
|
+
stop(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a coordinator server.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createCoordinatorServer(options: CoordinatorServerOptions): Promise<CoordinatorServer>;
|
|
34
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAkC,MAAM,mCAAmC,CAAC;AACvG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAK5D;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,yBAAyB;IACzB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,uCAAuC;IACvC,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,GAAG,EAAE,eAAe,CAAC;IACrB,8BAA8B;IAC9B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,uBAAuB;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,sBAAsB;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAqD5B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fastify server setup for sync-coordinator.
|
|
3
|
+
*/
|
|
4
|
+
import Fastify from 'fastify';
|
|
5
|
+
import fastifyCors from '@fastify/cors';
|
|
6
|
+
import fastifyWebsocket from '@fastify/websocket';
|
|
7
|
+
import { CoordinatorService } from '../service/coordinator-service.js';
|
|
8
|
+
import { registerRoutes } from './routes.js';
|
|
9
|
+
import { registerWebSocket } from './websocket.js';
|
|
10
|
+
import { serverLog } from '../common/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create a coordinator server.
|
|
13
|
+
*/
|
|
14
|
+
export async function createCoordinatorServer(options) {
|
|
15
|
+
const { config, hooks } = options;
|
|
16
|
+
serverLog('Creating coordinator server');
|
|
17
|
+
// Create Fastify instance
|
|
18
|
+
const app = Fastify({
|
|
19
|
+
logger: config.logging.level === 'debug',
|
|
20
|
+
});
|
|
21
|
+
// Register CORS
|
|
22
|
+
await app.register(fastifyCors, {
|
|
23
|
+
origin: config.cors.origin,
|
|
24
|
+
credentials: config.cors.credentials,
|
|
25
|
+
});
|
|
26
|
+
// Register WebSocket support
|
|
27
|
+
await app.register(fastifyWebsocket);
|
|
28
|
+
// Create service
|
|
29
|
+
const serviceOptions = {
|
|
30
|
+
config,
|
|
31
|
+
hooks,
|
|
32
|
+
};
|
|
33
|
+
const service = new CoordinatorService(serviceOptions);
|
|
34
|
+
// Initialize service
|
|
35
|
+
await service.initialize();
|
|
36
|
+
// Register routes
|
|
37
|
+
registerRoutes(app, service, config.basePath);
|
|
38
|
+
registerWebSocket(app, service, config.basePath);
|
|
39
|
+
serverLog('Routes registered at %s', config.basePath);
|
|
40
|
+
// Server control
|
|
41
|
+
const start = async () => {
|
|
42
|
+
const address = await app.listen({
|
|
43
|
+
host: config.host,
|
|
44
|
+
port: config.port,
|
|
45
|
+
});
|
|
46
|
+
serverLog('Server listening at %s', address);
|
|
47
|
+
console.log(`Sync coordinator listening at ${address}${config.basePath}`);
|
|
48
|
+
};
|
|
49
|
+
const stop = async () => {
|
|
50
|
+
serverLog('Stopping server');
|
|
51
|
+
await app.close();
|
|
52
|
+
await service.shutdown();
|
|
53
|
+
serverLog('Server stopped');
|
|
54
|
+
};
|
|
55
|
+
return { app, service, start, stop };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,OAAiC,MAAM,SAAS,CAAC;AACxD,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAkC,MAAM,mCAAmC,CAAC;AAEvG,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AA0BhD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAiC;IAEjC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAElC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAEzC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO;KACzC,CAAC,CAAC;IAEH,gBAAgB;IAChB,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE;QAC9B,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;QAC1B,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW;KACrC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAErC,iBAAiB;IACjB,MAAM,cAAc,GAA8B;QAChD,MAAM;QACN,KAAK;KACN,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAEvD,qBAAqB;IACrB,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAE3B,kBAAkB;IAClB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEjD,SAAS,CAAC,yBAAyB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEtD,iBAAiB;IACjB,MAAM,KAAK,GAAG,KAAK,IAAI,EAAE;QACvB,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC,CAAC;QACH,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,iCAAiC,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5E,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC7B,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzB,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handler for real-time sync.
|
|
3
|
+
*/
|
|
4
|
+
import type { FastifyInstance } from 'fastify';
|
|
5
|
+
import type { CoordinatorService } from '../service/coordinator-service.js';
|
|
6
|
+
/**
|
|
7
|
+
* Register WebSocket handler.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerWebSocket(app: FastifyInstance, service: CoordinatorService, basePath: string): void;
|
|
10
|
+
//# sourceMappingURL=websocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../../src/server/websocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAW/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAoD5E;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,GACf,IAAI,CA+IN"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handler for real-time sync.
|
|
3
|
+
*/
|
|
4
|
+
import { siteIdFromBase64, siteIdToBase64, deserializeHLC, serializeHLC, } from '@quereus/sync';
|
|
5
|
+
import { wsLog } from '../common/logger.js';
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// WebSocket Handler
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Register WebSocket handler.
|
|
11
|
+
*/
|
|
12
|
+
export function registerWebSocket(app, service, basePath) {
|
|
13
|
+
app.get(`${basePath}/ws`, { websocket: true }, (socket, request) => {
|
|
14
|
+
wsLog('New WebSocket connection from %s', request.ip);
|
|
15
|
+
let session = null;
|
|
16
|
+
const sendError = (code, message) => {
|
|
17
|
+
socket.send(JSON.stringify({ type: 'error', code, message }));
|
|
18
|
+
};
|
|
19
|
+
const sendMessage = (msg) => {
|
|
20
|
+
socket.send(JSON.stringify(msg));
|
|
21
|
+
};
|
|
22
|
+
socket.on('message', async (data) => {
|
|
23
|
+
try {
|
|
24
|
+
const message = JSON.parse(data.toString());
|
|
25
|
+
wsLog('Received message: %s', message.type);
|
|
26
|
+
switch (message.type) {
|
|
27
|
+
case 'handshake':
|
|
28
|
+
await handleHandshake(message);
|
|
29
|
+
break;
|
|
30
|
+
case 'get_changes':
|
|
31
|
+
await handleGetChanges(message);
|
|
32
|
+
break;
|
|
33
|
+
case 'apply_changes':
|
|
34
|
+
await handleApplyChanges(message);
|
|
35
|
+
break;
|
|
36
|
+
case 'get_snapshot':
|
|
37
|
+
await handleGetSnapshot();
|
|
38
|
+
break;
|
|
39
|
+
case 'ping':
|
|
40
|
+
sendMessage({ type: 'pong' });
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
sendError('UNKNOWN_MESSAGE', `Unknown message type: ${message.type}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
const msg = err instanceof Error ? err.message : 'Message processing failed';
|
|
48
|
+
wsLog('Message error: %s', msg);
|
|
49
|
+
sendError('MESSAGE_ERROR', msg);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
socket.on('close', () => {
|
|
53
|
+
wsLog('WebSocket closed: %s', session?.connectionId?.slice(0, 8) || 'no-session');
|
|
54
|
+
if (session) {
|
|
55
|
+
service.unregisterSession(session.connectionId);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
socket.on('error', (err) => {
|
|
59
|
+
wsLog('WebSocket error: %O', err);
|
|
60
|
+
});
|
|
61
|
+
// Handler functions
|
|
62
|
+
async function handleHandshake(msg) {
|
|
63
|
+
if (session) {
|
|
64
|
+
sendError('ALREADY_AUTHENTICATED', 'Already authenticated');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!msg.databaseId) {
|
|
68
|
+
sendError('MISSING_DATABASE_ID', 'databaseId is required');
|
|
69
|
+
socket.close(4002, 'Missing databaseId');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const identity = await service.authenticate({
|
|
74
|
+
databaseId: msg.databaseId,
|
|
75
|
+
token: msg.token,
|
|
76
|
+
siteIdRaw: msg.siteId,
|
|
77
|
+
siteId: siteIdFromBase64(msg.siteId),
|
|
78
|
+
socket,
|
|
79
|
+
});
|
|
80
|
+
session = await service.registerSession(msg.databaseId, socket, identity);
|
|
81
|
+
const serverSiteId = await service.getSiteId(msg.databaseId);
|
|
82
|
+
sendMessage({
|
|
83
|
+
type: 'handshake_ack',
|
|
84
|
+
databaseId: msg.databaseId,
|
|
85
|
+
serverSiteId: siteIdToBase64(serverSiteId),
|
|
86
|
+
connectionId: session.connectionId,
|
|
87
|
+
});
|
|
88
|
+
wsLog('Handshake complete: %s (db: %s)', session.connectionId.slice(0, 8), msg.databaseId);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const errMsg = err instanceof Error ? err.message : 'Authentication failed';
|
|
92
|
+
sendError('AUTH_FAILED', errMsg);
|
|
93
|
+
socket.close(4001, 'Authentication failed');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function handleGetChanges(msg) {
|
|
97
|
+
if (!session) {
|
|
98
|
+
sendError('NOT_AUTHENTICATED', 'Must handshake first');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let sinceHLC;
|
|
102
|
+
if (msg.sinceHLC) {
|
|
103
|
+
sinceHLC = deserializeHLC(Buffer.from(msg.sinceHLC, 'base64'));
|
|
104
|
+
}
|
|
105
|
+
const changes = await service.getChangesSince(session.databaseId, session.identity, sinceHLC);
|
|
106
|
+
// Serialize for JSON transport
|
|
107
|
+
const serializedChanges = changes.map(cs => serializeChangeSet(cs));
|
|
108
|
+
sendMessage({ type: 'changes', changeSets: serializedChanges });
|
|
109
|
+
}
|
|
110
|
+
async function handleApplyChanges(msg) {
|
|
111
|
+
if (!session) {
|
|
112
|
+
sendError('NOT_AUTHENTICATED', 'Must handshake first');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Deserialize from JSON transport
|
|
116
|
+
const changes = msg.changes.map(cs => deserializeChangeSet(cs));
|
|
117
|
+
const result = await service.applyChanges(session.databaseId, session.identity, changes);
|
|
118
|
+
sendMessage({ type: 'apply_result', ...result });
|
|
119
|
+
}
|
|
120
|
+
async function handleGetSnapshot() {
|
|
121
|
+
if (!session) {
|
|
122
|
+
sendError('NOT_AUTHENTICATED', 'Must handshake first');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Stream snapshot chunks
|
|
126
|
+
for await (const chunk of service.getSnapshotStream(session.databaseId, session.identity)) {
|
|
127
|
+
sendMessage({ ...chunk, type: 'snapshot_chunk' });
|
|
128
|
+
}
|
|
129
|
+
sendMessage({ type: 'snapshot_complete' });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Serialization Helpers
|
|
135
|
+
// ============================================================================
|
|
136
|
+
function serializeChangeSet(cs) {
|
|
137
|
+
return {
|
|
138
|
+
siteId: siteIdToBase64(cs.siteId),
|
|
139
|
+
transactionId: cs.transactionId,
|
|
140
|
+
hlc: Buffer.from(serializeHLC(cs.hlc)).toString('base64'),
|
|
141
|
+
changes: cs.changes.map(c => ({
|
|
142
|
+
...c,
|
|
143
|
+
hlc: Buffer.from(serializeHLC(c.hlc)).toString('base64'),
|
|
144
|
+
})),
|
|
145
|
+
schemaMigrations: cs.schemaMigrations.map(m => ({
|
|
146
|
+
...m,
|
|
147
|
+
hlc: Buffer.from(serializeHLC(m.hlc)).toString('base64'),
|
|
148
|
+
})),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function deserializeChangeSet(cs) {
|
|
152
|
+
const obj = cs;
|
|
153
|
+
return {
|
|
154
|
+
siteId: siteIdFromBase64(obj.siteId),
|
|
155
|
+
transactionId: obj.transactionId,
|
|
156
|
+
hlc: deserializeHLC(Buffer.from(obj.hlc, 'base64')),
|
|
157
|
+
changes: obj.changes.map(c => ({
|
|
158
|
+
...c,
|
|
159
|
+
hlc: deserializeHLC(Buffer.from(c.hlc, 'base64')),
|
|
160
|
+
})),
|
|
161
|
+
schemaMigrations: (obj.schemaMigrations || []).map(m => ({
|
|
162
|
+
...m,
|
|
163
|
+
hlc: deserializeHLC(Buffer.from(m.hlc, 'base64')),
|
|
164
|
+
})),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/server/websocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,YAAY,GAIb,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AA8C5C,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAoB,EACpB,OAA2B,EAC3B,QAAgB;IAEhB,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAiB,EAAE,OAAuB,EAAE,EAAE;QAC5F,KAAK,CAAC,kCAAkC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAEtD,IAAI,OAAO,GAAyB,IAAI,CAAC;QAEzC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,EAAE;YAClD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC;QAEF,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,EAAE;YAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QAEF,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;YAC3C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAkB,CAAC;gBAC7D,KAAK,CAAC,sBAAsB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAE5C,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;oBACrB,KAAK,WAAW;wBACd,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;wBAC/B,MAAM;oBACR,KAAK,aAAa;wBAChB,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;wBAChC,MAAM;oBACR,KAAK,eAAe;wBAClB,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;wBAClC,MAAM;oBACR,KAAK,cAAc;wBACjB,MAAM,iBAAiB,EAAE,CAAC;wBAC1B,MAAM;oBACR,KAAK,MAAM;wBACT,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;wBAC9B,MAAM;oBACR;wBACE,SAAS,CAAC,iBAAiB,EAAE,yBAA0B,OAA4B,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChG,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;gBAC7E,KAAK,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;gBAChC,SAAS,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,KAAK,CAAC,sBAAsB,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC;YAClF,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAClD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,KAAK,UAAU,eAAe,CAAC,GAAqB;YAClD,IAAI,OAAO,EAAE,CAAC;gBACZ,SAAS,CAAC,uBAAuB,EAAE,uBAAuB,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;gBACpB,SAAS,CAAC,qBAAqB,EAAE,wBAAwB,CAAC,CAAC;gBAC3D,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAmB,MAAM,OAAO,CAAC,YAAY,CAAC;oBAC1D,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,SAAS,EAAE,GAAG,CAAC,MAAM;oBACrB,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC;oBACpC,MAAM;iBACP,CAAC,CAAC;gBAEH,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAE1E,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAC7D,WAAW,CAAC;oBACV,IAAI,EAAE,eAAe;oBACrB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,YAAY,EAAE,cAAc,CAAC,YAAY,CAAC;oBAC1C,YAAY,EAAE,OAAO,CAAC,YAAY;iBACnC,CAAC,CAAC;gBAEH,KAAK,CAAC,iCAAiC,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;gBAC5E,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,KAAK,UAAU,gBAAgB,CAAC,GAAsB;YACpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,IAAI,QAAyB,CAAC;YAC9B,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACjB,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAE9F,+BAA+B;YAC/B,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC;YAEpE,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,KAAK,UAAU,kBAAkB,CAAC,GAAwB;YACxD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,kCAAkC;YAClC,MAAM,OAAO,GAAgB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;YAE7E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAEzF,WAAW,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,KAAK,UAAU,iBAAiB;YAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;YAED,yBAAyB;YACzB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1F,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;YACpD,CAAC;YAED,WAAW,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E,SAAS,kBAAkB,CAAC,EAAa;IACvC,OAAO;QACL,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC;QACjC,aAAa,EAAE,EAAE,CAAC,aAAa;QAC/B,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzD,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,GAAG,CAAC;YACJ,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;SACzD,CAAC,CAAC;QACH,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9C,GAAG,CAAC;YACJ,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;SACzD,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAW;IACvC,MAAM,GAAG,GAAG,EAA6B,CAAC;IAC1C,OAAO;QACL,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAgB,CAAC;QAC9C,aAAa,EAAE,GAAG,CAAC,aAAuB;QAC1C,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAa,EAAE,QAAQ,CAAC,CAAC;QAC7D,OAAO,EAAG,GAAG,CAAC,OAAqC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5D,GAAG,CAAC;YACJ,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAa,EAAE,QAAQ,CAAC,CAAC;SAC5D,CAAC,CAAC;QACH,gBAAgB,EAAE,CAAE,GAAG,CAAC,gBAA8C,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtF,GAAG,CAAC;YACJ,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAa,EAAE,QAAQ,CAAC,CAAC;SAC5D,CAAC,CAAC;KACS,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoordinatorService - Main service layer for multi-tenant sync coordination.
|
|
3
|
+
*
|
|
4
|
+
* Manages multiple database stores with lazy loading and provides
|
|
5
|
+
* sync operations with validation hooks and client session management.
|
|
6
|
+
*/
|
|
7
|
+
import type { WebSocket } from 'ws';
|
|
8
|
+
import { type HLC, type SiteId, type ChangeSet, type ApplyResult, type SnapshotChunk } from '@quereus/sync';
|
|
9
|
+
import type { CoordinatorConfig } from '../config/types.js';
|
|
10
|
+
import { type CoordinatorMetrics } from '../metrics/index.js';
|
|
11
|
+
import type { ClientIdentity, ClientSession, AuthContext, SyncOperation, CoordinatorHooks } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Options for creating a CoordinatorService.
|
|
14
|
+
*/
|
|
15
|
+
export interface CoordinatorServiceOptions {
|
|
16
|
+
/** Full configuration */
|
|
17
|
+
config: CoordinatorConfig;
|
|
18
|
+
/** Custom hooks for validation/auth */
|
|
19
|
+
hooks?: CoordinatorHooks;
|
|
20
|
+
/** Custom metrics (uses global registry if not provided) */
|
|
21
|
+
metrics?: CoordinatorMetrics;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Multi-tenant coordinator service that manages sync operations with hooks.
|
|
25
|
+
*/
|
|
26
|
+
export declare class CoordinatorService {
|
|
27
|
+
private readonly config;
|
|
28
|
+
private readonly hooks;
|
|
29
|
+
private readonly metrics;
|
|
30
|
+
private readonly storeManager;
|
|
31
|
+
/** Active WebSocket sessions by connection ID */
|
|
32
|
+
private readonly sessions;
|
|
33
|
+
/** Connection IDs by database ID for broadcasting */
|
|
34
|
+
private readonly databaseToConnections;
|
|
35
|
+
private initialized;
|
|
36
|
+
constructor(options: CoordinatorServiceOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the service.
|
|
39
|
+
*/
|
|
40
|
+
initialize(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Shutdown the service.
|
|
43
|
+
*/
|
|
44
|
+
shutdown(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Get a store entry for a database, acquiring if needed.
|
|
47
|
+
*/
|
|
48
|
+
private getStore;
|
|
49
|
+
/**
|
|
50
|
+
* Release a store reference.
|
|
51
|
+
*/
|
|
52
|
+
private releaseStore;
|
|
53
|
+
/**
|
|
54
|
+
* Authenticate a request/connection.
|
|
55
|
+
*/
|
|
56
|
+
authenticate(context: AuthContext): Promise<ClientIdentity>;
|
|
57
|
+
/**
|
|
58
|
+
* Authorize an operation for a client.
|
|
59
|
+
*/
|
|
60
|
+
authorize(client: ClientIdentity, operation: SyncOperation): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Get the coordinator's site ID for a specific database.
|
|
63
|
+
*/
|
|
64
|
+
getSiteId(databaseId: string): Promise<SiteId>;
|
|
65
|
+
/**
|
|
66
|
+
* Get current HLC for a specific database.
|
|
67
|
+
*/
|
|
68
|
+
getCurrentHLC(databaseId: string): Promise<HLC>;
|
|
69
|
+
/**
|
|
70
|
+
* Get changes since a given HLC for a client.
|
|
71
|
+
*/
|
|
72
|
+
getChangesSince(databaseId: string, client: ClientIdentity, sinceHLC?: HLC): Promise<ChangeSet[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Apply changes from a client.
|
|
75
|
+
*/
|
|
76
|
+
applyChanges(databaseId: string, client: ClientIdentity, changes: ChangeSet[]): Promise<ApplyResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Stream a full snapshot.
|
|
79
|
+
*/
|
|
80
|
+
getSnapshotStream(databaseId: string, client: ClientIdentity, chunkSize?: number): AsyncIterable<SnapshotChunk>;
|
|
81
|
+
/**
|
|
82
|
+
* Check if delta sync is possible.
|
|
83
|
+
*/
|
|
84
|
+
canDeltaSync(databaseId: string, client: ClientIdentity, sinceHLC: HLC): Promise<boolean>;
|
|
85
|
+
/**
|
|
86
|
+
* Register a new WebSocket client session.
|
|
87
|
+
*/
|
|
88
|
+
registerSession(databaseId: string, socket: WebSocket, identity: ClientIdentity): Promise<ClientSession>;
|
|
89
|
+
/**
|
|
90
|
+
* Unregister a WebSocket client session.
|
|
91
|
+
*/
|
|
92
|
+
unregisterSession(connectionId: string): void;
|
|
93
|
+
/**
|
|
94
|
+
* Get a session by connection ID.
|
|
95
|
+
*/
|
|
96
|
+
getSession(connectionId: string): ClientSession | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Update the last sync HLC for a session.
|
|
99
|
+
*/
|
|
100
|
+
updateSessionSyncState(connectionId: string, hlc: HLC): void;
|
|
101
|
+
/**
|
|
102
|
+
* Broadcast changes to all connected clients on the same database except the sender.
|
|
103
|
+
*/
|
|
104
|
+
private broadcastChanges;
|
|
105
|
+
/**
|
|
106
|
+
* Serialize a ChangeSet for JSON transport.
|
|
107
|
+
*/
|
|
108
|
+
private serializeChangeSet;
|
|
109
|
+
/**
|
|
110
|
+
* Get server status and stats.
|
|
111
|
+
*/
|
|
112
|
+
getStatus(): {
|
|
113
|
+
openStores: number;
|
|
114
|
+
connectedClients: number;
|
|
115
|
+
uptime: number;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Get the metrics registry for this service.
|
|
119
|
+
*/
|
|
120
|
+
getMetrics(): CoordinatorMetrics;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=coordinator-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator-service.d.ts","sourceRoot":"","sources":["../../../src/service/coordinator-service.ts"],"names":[],"mappings":"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"}
|