leafrelay 0.2.5 → 0.2.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/dist/{chunk-OZ4FLSVP.js → chunk-3TTRDNHP.js} +195 -46
- package/dist/chunk-3TTRDNHP.js.map +1 -0
- package/dist/{chunk-IOX2PULH.js → chunk-VXZVIMCG.js} +182 -37
- package/dist/chunk-VXZVIMCG.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/daemon.js +27 -6
- package/dist/daemon.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-IOX2PULH.js.map +0 -1
- package/dist/chunk-OZ4FLSVP.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
daemonStatus,
|
|
6
6
|
daemonStop,
|
|
7
7
|
serve
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VXZVIMCG.js";
|
|
9
9
|
import {
|
|
10
10
|
configPath,
|
|
11
11
|
normalizeServerUrl
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3TTRDNHP.js";
|
|
13
13
|
|
|
14
14
|
// src/cli.ts
|
|
15
15
|
import { Command } from "commander";
|
|
@@ -48,7 +48,7 @@ async function login(server, options) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// src/cli.ts
|
|
51
|
-
var program = new Command().name("leafrelay").description("Keep a local directory synchronized with an Overleaf project.").version("0.2.
|
|
51
|
+
var program = new Command().name("leafrelay").description("Keep a local directory synchronized with an Overleaf project.").version("0.2.7");
|
|
52
52
|
program.command("login").description("Authenticate to Overleaf and save the session in ~/.leafrelay/config.json.").argument("[server]", "Overleaf server URL", "https://www.overleaf.com/").option("--cookie <cookie>", "Overleaf browser cookie").option("--email <email>", "Overleaf account email").option("--password <password>", "Overleaf account password").action(login);
|
|
53
53
|
program.command("serve").description("Synchronize the current directory with its configured Overleaf project.").argument("[directory]", "Local replica directory", process.cwd()).action(serve);
|
|
54
54
|
var daemon = program.command("daemon").description("Inspect or control the shared LeafRelay daemon.");
|
package/dist/daemon.js
CHANGED
|
@@ -12,13 +12,15 @@ import {
|
|
|
12
12
|
saveKnownServer,
|
|
13
13
|
saveServerSession,
|
|
14
14
|
serverKey,
|
|
15
|
+
setLogSink,
|
|
15
16
|
startServe
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-3TTRDNHP.js";
|
|
17
18
|
|
|
18
19
|
// ../daemon/src/server.ts
|
|
19
20
|
import { randomBytes, randomUUID as randomUUID2 } from "crypto";
|
|
20
21
|
import { appendFile, chmod, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
21
22
|
import { createServer } from "net";
|
|
23
|
+
import { formatWithOptions } from "util";
|
|
22
24
|
|
|
23
25
|
// ../protocol/dist/index.js
|
|
24
26
|
var LEAFRELAY_PROTOCOL_VERSION = 1;
|
|
@@ -491,9 +493,17 @@ var ReplicaRegistry = class {
|
|
|
491
493
|
const status = { state: "starting" };
|
|
492
494
|
let entry;
|
|
493
495
|
this.events.status(owners, { replicaId: id, status });
|
|
496
|
+
this.events.log(`[${settings.projectName}] Starting synchronization for ${root}.`);
|
|
494
497
|
try {
|
|
495
498
|
const running = await this.start(root, {
|
|
496
499
|
cookie: params.cookie,
|
|
500
|
+
onSyncError: (message) => {
|
|
501
|
+
if (!entry) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
entry.status = message ? { state: "error", message } : entry.running.conflicts().length ? { state: "paused" } : { state: "active" };
|
|
505
|
+
this.events.status(entry.owners, { replicaId: id, status: entry.status });
|
|
506
|
+
},
|
|
497
507
|
log: (message) => this.events.log(`[${settings.projectName}] ${message}`),
|
|
498
508
|
onConflict: (path, reason) => {
|
|
499
509
|
if (!entry) {
|
|
@@ -523,7 +533,7 @@ var ReplicaRegistry = class {
|
|
|
523
533
|
projectName: settings.projectName,
|
|
524
534
|
owners,
|
|
525
535
|
running,
|
|
526
|
-
status: running.conflicts().length === 0 ? { state: "active" } : { state: "paused" }
|
|
536
|
+
status: running.syncError() ? { state: "error", message: running.syncError() } : running.conflicts().length === 0 ? { state: "active" } : { state: "paused" }
|
|
527
537
|
};
|
|
528
538
|
this.byId.set(id, entry);
|
|
529
539
|
this.byRoot.set(root, entry);
|
|
@@ -558,13 +568,13 @@ var ReplicaRegistry = class {
|
|
|
558
568
|
async resolveConflict(replicaId, path, winner) {
|
|
559
569
|
const entry = this.require(replicaId);
|
|
560
570
|
await entry.running.resolveConflict(path, winner);
|
|
561
|
-
entry.status = entry.running.conflicts().length === 0 ? { state: "active" } : { state: "paused" };
|
|
571
|
+
entry.status = entry.running.syncError() ? { state: "error", message: entry.running.syncError() } : entry.running.conflicts().length === 0 ? { state: "active" } : { state: "paused" };
|
|
562
572
|
this.events.status(entry.owners, { replicaId, status: entry.status });
|
|
563
573
|
}
|
|
564
574
|
async retry(replicaId, path) {
|
|
565
575
|
const entry = this.require(replicaId);
|
|
566
576
|
await entry.running.retry(path);
|
|
567
|
-
entry.status = entry.running.conflicts().length === 0 ? { state: "active" } : { state: "paused" };
|
|
577
|
+
entry.status = entry.running.syncError() ? { state: "error", message: entry.running.syncError() } : entry.running.conflicts().length === 0 ? { state: "active" } : { state: "paused" };
|
|
568
578
|
this.events.status(entry.owners, { replicaId, status: entry.status });
|
|
569
579
|
}
|
|
570
580
|
list() {
|
|
@@ -672,7 +682,7 @@ function createSocketRpcConnection(socket) {
|
|
|
672
682
|
// ../daemon/src/server.ts
|
|
673
683
|
var IDLE_EXIT_MS = 6e4;
|
|
674
684
|
var REPLICA_ALREADY_ACTIVE = -32010;
|
|
675
|
-
var daemonVersion = true ? "0.2.
|
|
685
|
+
var daemonVersion = true ? "0.2.7" : "development";
|
|
676
686
|
var LeafRelayDaemonServer = class {
|
|
677
687
|
constructor(options = {}) {
|
|
678
688
|
this.options = options;
|
|
@@ -717,6 +727,7 @@ var LeafRelayDaemonServer = class {
|
|
|
717
727
|
stopping;
|
|
718
728
|
async start() {
|
|
719
729
|
await mkdir(this.paths.home, { recursive: true, mode: 448 });
|
|
730
|
+
setLogSink((level, args) => void this.log(level, formatWithOptions({ depth: 5, breakLength: Infinity }, ...args)));
|
|
720
731
|
if (process.platform !== "win32") {
|
|
721
732
|
await rm(this.paths.socketPath, { force: true });
|
|
722
733
|
}
|
|
@@ -859,7 +870,16 @@ var LeafRelayDaemonServer = class {
|
|
|
859
870
|
if (!client.initialized) {
|
|
860
871
|
throw new ResponseError(-32001, "Initialize the daemon connection first.");
|
|
861
872
|
}
|
|
862
|
-
|
|
873
|
+
try {
|
|
874
|
+
return await operation();
|
|
875
|
+
} catch (error) {
|
|
876
|
+
if (error instanceof ResponseError) {
|
|
877
|
+
throw error;
|
|
878
|
+
}
|
|
879
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
880
|
+
await this.log("error", `RPC operation failed: ${formatWithOptions({ depth: 5, breakLength: Infinity }, error)}`);
|
|
881
|
+
throw new ResponseError(-32603, message);
|
|
882
|
+
}
|
|
863
883
|
}
|
|
864
884
|
async closeClient(client) {
|
|
865
885
|
if (!this.clients.delete(client)) {
|
|
@@ -916,6 +936,7 @@ var LeafRelayDaemonServer = class {
|
|
|
916
936
|
this.cancelIdleExit();
|
|
917
937
|
await this.replicas.stopAll();
|
|
918
938
|
await this.network.stopAll();
|
|
939
|
+
setLogSink(void 0);
|
|
919
940
|
for (const client of this.clients) {
|
|
920
941
|
client.rpc.dispose();
|
|
921
942
|
client.socket.destroy();
|
package/dist/daemon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../daemon/src/server.ts","../../protocol/src/index.ts","../../daemon/src/paths.ts","../../daemon/src/codec.ts","../../daemon/src/networkRuntime.ts","../../daemon/src/replicaRegistry.ts","../../daemon/src/transport.ts","../../daemon/src/main.ts"],"sourcesContent":["import {randomBytes, randomUUID} from 'node:crypto';\nimport {appendFile, chmod, mkdir, readFile, rm, writeFile} from 'node:fs/promises';\nimport {createServer, type Server, type Socket} from 'node:net';\nimport {\n readProjectSettings,\n startServe,\n} from '@leafrelay/core';\nimport {\n LEAFRELAY_PROTOCOL_VERSION,\n RPC_METHOD,\n RPC_NOTIFICATION,\n type DaemonMetadata,\n type DaemonStatus,\n type InitializeParams,\n type InitializeResult,\n type LogNotification,\n type ReplicaAttachParams,\n type ReplicaConflictResolutionParams,\n type ReplicaStatusNotification,\n type ReplicaConflictNotification,\n type ProjectCallParams,\n type ProjectEventNotification,\n type ProjectOpenParams,\n type ServerCallParams,\n type ServerImportParams,\n type ServerLoginParams,\n} from '@leafrelay/protocol';\nimport {ResponseError, type MessageConnection} from 'vscode-jsonrpc/node';\nimport {daemonPaths, type DaemonPaths} from './paths';\nimport {decodeRpcValue, encodeRpcValue} from './codec';\nimport {NetworkRuntimeRegistry} from './networkRuntime';\nimport {ReplicaAlreadyActiveError, ReplicaRegistry} from './replicaRegistry';\nimport {createSocketRpcConnection} from './transport';\n\ndeclare const LEAFRELAY_DAEMON_VERSION:string;\n\nconst IDLE_EXIT_MS = 60_000;\nconst REPLICA_ALREADY_ACTIVE = -32010;\nconst daemonVersion = typeof LEAFRELAY_DAEMON_VERSION==='string' ? LEAFRELAY_DAEMON_VERSION : 'development';\n\ninterface ClientConnection {\n leaseId:string;\n socket:Socket;\n rpc:MessageConnection;\n clientId?:string;\n initialized:boolean;\n}\n\nexport interface DaemonServerOptions {\n paths?:DaemonPaths;\n token?:string;\n exitOnIdle?:boolean;\n}\n\nexport class LeafRelayDaemonServer {\n private readonly paths:DaemonPaths;\n private readonly token:string;\n private readonly startedAt = new Date().toISOString();\n private readonly clients = new Set<ClientConnection>();\n private readonly network:NetworkRuntimeRegistry;\n private readonly replicas:ReplicaRegistry;\n private server?:Server;\n private idleTimer?:NodeJS.Timeout;\n private stopping?:Promise<void>;\n\n constructor(private readonly options:DaemonServerOptions={}) {\n this.paths = options.paths ?? daemonPaths();\n this.token = options.token ?? randomBytes(32).toString('hex');\n this.network = new NetworkRuntimeRegistry({\n projectEvent:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.projectEvent, notification),\n log:(level, message) => void this.log(level, message),\n });\n this.replicas = new ReplicaRegistry({\n status:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaStatus, notification),\n conflict:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaConflict, notification),\n empty:() => this.scheduleIdleExit(),\n log:message => void this.log('info', message),\n }, async (directory, startOptions) => {\n const settings = await readProjectSettings(directory);\n const lease = await this.network.acquireReplica(settings.serverName, settings.projectId);\n try {\n const running = await startServe(directory, {...startOptions, remote:lease.remote});\n return {\n ...running,\n stop:async () => {\n await running.stop();\n lease.release();\n },\n };\n } catch (error) {\n lease.release();\n throw error;\n }\n });\n }\n\n async start():Promise<DaemonMetadata> {\n await mkdir(this.paths.home, {recursive:true, mode:0o700});\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n this.server = createServer(socket => this.accept(socket));\n await new Promise<void>((resolveListen, reject) => {\n this.server!.once('error', reject);\n this.server!.listen(this.paths.socketPath, () => {\n this.server!.off('error', reject);\n resolveListen();\n });\n });\n if (process.platform!=='win32') { await chmod(this.paths.socketPath, 0o600); }\n const metadata:DaemonMetadata = {\n pid:process.pid,\n socketPath:this.paths.socketPath,\n token:this.token,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n version:daemonVersion,\n startedAt:this.startedAt,\n };\n await writeFile(this.paths.metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`, {encoding:'utf8', mode:0o600});\n await chmod(this.paths.metadataPath, 0o600);\n await this.log('info', `Daemon ${daemonVersion} listening on ${this.paths.socketPath}.`);\n this.scheduleIdleExit();\n return metadata;\n }\n\n async stop():Promise<void> {\n if (this.stopping) { return this.stopping; }\n this.stopping = this.performStop();\n return this.stopping;\n }\n\n status():DaemonStatus {\n return {\n pid:process.pid,\n version:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n startedAt:this.startedAt,\n clients:this.clients.size,\n projects:this.network.projectCount,\n replicas:this.replicas.list(),\n };\n }\n\n private accept(socket:Socket):void {\n this.cancelIdleExit();\n const rpc = createSocketRpcConnection(socket);\n const client:ClientConnection = {leaseId:randomUUID(), socket, rpc, initialized:false};\n this.clients.add(client);\n rpc.onRequest(RPC_METHOD.initialize, (params:InitializeParams) => this.initialize(client, params));\n rpc.onRequest(RPC_METHOD.daemonStatus, () => this.authorized(client, () => this.status()));\n rpc.onRequest(RPC_METHOD.daemonShutdown, () => this.authorized(client, async () => {\n setTimeout(() => void this.stop(), 25);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaAttach, (params:ReplicaAttachParams) => this.authorized(client, async () => {\n try {\n return await this.replicas.attach(client.leaseId, params);\n } catch (error) {\n if (error instanceof ReplicaAlreadyActiveError) {\n throw new ResponseError(REPLICA_ALREADY_ACTIVE, error.message, {\n code:error.code,\n projectId:error.projectId,\n activeRoot:error.activeRoot,\n requestedRoot:error.requestedRoot,\n });\n }\n throw error;\n }\n }));\n rpc.onRequest(RPC_METHOD.replicaDetach, (params:{replicaId:string}) => this.authorized(client, async () => {\n await this.replicas.detach(client.leaseId, params.replicaId);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaResolveConflict, (params:ReplicaConflictResolutionParams) => this.authorized(client, async () => {\n await this.replicas.resolveConflict(params.replicaId, params.path, params.winner);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaRetry, (params:{replicaId:string; path:string}) => this.authorized(client, async () => {\n await this.replicas.retry(params.replicaId, params.path);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverList, () => this.authorized(client, () => this.network.listServers()));\n rpc.onRequest(RPC_METHOD.serverAdd, (params:{name:string; url:string}) => this.authorized(client, async () => {\n await this.network.addServer(params.name, params.url);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverRemove, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.removeServer(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.sessionLogin, (params:ServerLoginParams) => this.authorized(client, () => this.network.login(params)));\n rpc.onRequest(RPC_METHOD.sessionImport, (params:ServerImportParams) => this.authorized(client, () => this.network.importSession(params)));\n rpc.onRequest(RPC_METHOD.sessionLogout, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.logout(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverCall, (params:ServerCallParams) => this.authorized(client, async () => {\n const result = await this.network.callServer(params.server, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(result);\n }));\n rpc.onRequest(RPC_METHOD.projectOpen, (params:ProjectOpenParams) => this.authorized(client, () => (\n this.network.openProject(client.leaseId, params.server, params.projectId)\n )));\n rpc.onRequest(RPC_METHOD.projectClose, (params:{projectKey:string}) => this.authorized(client, () => {\n this.network.closeProject(client.leaseId, params.projectKey);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.projectCall, (params:ProjectCallParams) => this.authorized(client, async () => {\n const result = await this.network.callProject(params.projectKey, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(await result);\n }));\n rpc.onClose(() => void this.closeClient(client));\n rpc.onError(error => void this.log('error', `JSON-RPC connection error: ${String(error[0])}`));\n rpc.listen();\n }\n\n private initialize(client:ClientConnection, params:InitializeParams):InitializeResult {\n if (params.token!==this.token) { throw new ResponseError(-32001, 'Daemon authentication failed.'); }\n if (params.protocolVersion!==LEAFRELAY_PROTOCOL_VERSION) {\n throw new ResponseError(-32002, `Protocol ${params.protocolVersion} is incompatible with daemon protocol ${LEAFRELAY_PROTOCOL_VERSION}.`);\n }\n if (!params.clientId) { throw new ResponseError(-32602, 'clientId is required.'); }\n client.clientId = params.clientId;\n client.initialized = true;\n this.replicas.registerClient(client.leaseId);\n void this.log('info', `${params.clientName} ${params.clientVersion} connected (${params.clientId}).`);\n return {\n daemonVersion:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n pid:process.pid,\n startedAt:this.startedAt,\n };\n }\n\n private async authorized<T>(client:ClientConnection, operation:() => T|Promise<T>):Promise<T> {\n if (!client.initialized) { throw new ResponseError(-32001, 'Initialize the daemon connection first.'); }\n return operation();\n }\n\n private async closeClient(client:ClientConnection):Promise<void> {\n if (!this.clients.delete(client)) { return; }\n if (client.clientId) {\n try {\n await this.replicas.detachClient(client.leaseId);\n } catch (error) {\n await this.log('error', `Failed to stop replicas for a disconnected client: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n this.network.detachClient(client.leaseId);\n }\n }\n this.scheduleIdleExit();\n }\n\n private notifyOwners(\n owners:ReadonlySet<string>,\n method:typeof RPC_NOTIFICATION.replicaStatus|typeof RPC_NOTIFICATION.replicaConflict|typeof RPC_NOTIFICATION.projectEvent,\n notification:ReplicaStatusNotification|ReplicaConflictNotification|ProjectEventNotification,\n ):void {\n for (const client of this.clients) {\n if (owners.has(client.leaseId)) { this.notifyClient(client, method, notification); }\n }\n }\n\n private async log(level:LogNotification['level'], message:string):Promise<void> {\n const notification:LogNotification = {timestamp:new Date().toISOString(), level, message};\n await appendFile(this.paths.logPath, `${notification.timestamp} [${level}] ${message}\\n`, {encoding:'utf8', mode:0o600});\n for (const client of this.clients) {\n if (client.initialized) { this.notifyClient(client, RPC_NOTIFICATION.log, notification); }\n }\n }\n\n private notifyClient(client:ClientConnection, method:string, notification:unknown):void {\n if (!this.clients.has(client) || client.socket.destroyed) { return; }\n void client.rpc.sendNotification(method, notification).catch(() => this.closeClient(client));\n }\n\n private scheduleIdleExit():void {\n if (this.options.exitOnIdle===false || this.clients.size!==0 || this.replicas.size!==0 || this.idleTimer) { return; }\n this.idleTimer = setTimeout(() => void this.stop(), IDLE_EXIT_MS);\n this.idleTimer.unref();\n }\n\n private cancelIdleExit():void {\n if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = undefined; }\n }\n\n private async performStop():Promise<void> {\n this.cancelIdleExit();\n await this.replicas.stopAll();\n await this.network.stopAll();\n for (const client of this.clients) {\n client.rpc.dispose();\n client.socket.destroy();\n }\n this.clients.clear();\n if (this.server) {\n await new Promise<void>(resolveClose => this.server!.close(() => resolveClose()));\n }\n await rm(this.paths.metadataPath, {force:true});\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n }\n}\n\nexport async function readDaemonMetadata(paths:DaemonPaths=daemonPaths()):Promise<DaemonMetadata|undefined> {\n try {\n return JSON.parse(await readFile(paths.metadataPath, 'utf8')) as DaemonMetadata;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw error;\n }\n}\n","export const LEAFRELAY_PROTOCOL_VERSION = 1;\n\nexport const RPC_METHOD = {\n initialize:'leafrelay/initialize',\n daemonStatus:'leafrelay/daemon/status',\n daemonShutdown:'leafrelay/daemon/shutdown',\n replicaAttach:'leafrelay/replica/attach',\n replicaDetach:'leafrelay/replica/detach',\n replicaResolveConflict:'leafrelay/replica/resolveConflict',\n replicaRetry:'leafrelay/replica/retry',\n sessionImport:'leafrelay/session/import',\n sessionLogin:'leafrelay/session/login',\n sessionLogout:'leafrelay/session/logout',\n serverList:'leafrelay/server/list',\n serverAdd:'leafrelay/server/add',\n serverRemove:'leafrelay/server/remove',\n serverCall:'leafrelay/server/call',\n projectOpen:'leafrelay/project/open',\n projectClose:'leafrelay/project/close',\n projectCall:'leafrelay/project/call',\n} as const;\n\nexport const RPC_NOTIFICATION = {\n log:'leafrelay/log',\n replicaStatus:'leafrelay/replica/status',\n replicaConflict:'leafrelay/replica/conflict',\n projectEvent:'leafrelay/project/event',\n} as const;\n\nexport interface InitializeParams {\n token:string;\n clientId:string;\n clientName:'cli'|'vscode'|'library'|'test';\n clientVersion:string;\n protocolVersion:number;\n}\n\nexport interface InitializeResult {\n daemonVersion:string;\n protocolVersion:number;\n pid:number;\n startedAt:string;\n}\n\nexport interface DaemonStatus {\n pid:number;\n version:string;\n protocolVersion:number;\n startedAt:string;\n clients:number;\n projects:number;\n replicas:Array<{\n id:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n clients:number;\n status:ReplicaStatus;\n conflicts:string[];\n }>;\n}\n\nexport type ReplicaState = 'starting'|'syncing'|'active'|'paused'|'stopping'|'error';\n\nexport interface ReplicaStatus {\n state:ReplicaState;\n message?:string;\n}\n\nexport interface ReplicaAttachParams {\n directory:string;\n cookie?:string;\n}\n\nexport interface ReplicaAttachResult {\n replicaId:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n shared:boolean;\n status:ReplicaStatus;\n conflicts:string[];\n}\n\nexport interface ReplicaConflictResolutionParams {\n replicaId:string;\n path:string;\n winner:'local'|'remote';\n}\n\nexport interface ReplicaStatusNotification {\n replicaId:string;\n status:ReplicaStatus;\n}\n\nexport interface ReplicaConflictNotification {\n replicaId:string;\n path:string;\n reason:string;\n conflicts:string[];\n}\n\nexport interface LogNotification {\n timestamp:string;\n level:'info'|'warn'|'error';\n message:string;\n}\n\nexport interface DaemonMetadata {\n pid:number;\n socketPath:string;\n token:string;\n protocolVersion:number;\n version:string;\n startedAt:string;\n}\n\nexport interface ServerDescriptor {\n name:string;\n url:string;\n loggedIn:boolean;\n userId?:string;\n userEmail?:string;\n}\n\nexport interface ServerLoginParams {\n server:string;\n cookie?:string;\n email?:string;\n password?:string;\n}\n\nexport interface ServerImportParams {\n name:string;\n url:string;\n userId:string;\n userEmail:string;\n identity:{cookies:string; csrfToken:string};\n}\n\nexport interface ServerCallParams {\n server:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectOpenParams {\n server:string;\n projectId:string;\n}\n\nexport interface ProjectOpenResult {\n projectKey:string;\n shared:boolean;\n}\n\nexport interface ProjectCallParams {\n projectKey:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectEventNotification {\n projectKey:string;\n event:string;\n args:unknown[];\n}\n\nexport interface EncodedBinary {\n $leafrelay:'bytes';\n base64:string;\n}\n","import {createHash} from 'node:crypto';\nimport {homedir} from 'node:os';\nimport {join, resolve} from 'node:path';\n\nexport interface DaemonPaths {\n home:string;\n socketPath:string;\n metadataPath:string;\n logPath:string;\n startupLockPath:string;\n}\n\nexport function daemonPaths(environment:NodeJS.ProcessEnv=process.env):DaemonPaths {\n const home = environment.LEAFRELAY_HOME ? resolve(environment.LEAFRELAY_HOME) : join(homedir(), '.leafrelay');\n const socketPath = process.platform==='win32'\n ? `\\\\\\\\.\\\\pipe\\\\leafrelay-${createHash('sha256').update(home).digest('hex').slice(0, 16)}`\n : join(home, 'daemon.sock');\n return {\n home,\n socketPath,\n metadataPath:join(home, 'daemon.json'),\n logPath:join(home, 'daemon.log'),\n startupLockPath:join(home, 'daemon.starting'),\n };\n}\n","import type {EncodedBinary} from '@leafrelay/protocol';\n\nfunction isEncodedBinary(value:unknown):value is EncodedBinary {\n return typeof value==='object' && value!==null\n && (value as Partial<EncodedBinary>).$leafrelay==='bytes'\n && typeof (value as Partial<EncodedBinary>).base64==='string';\n}\n\nexport function encodeRpcValue(value:unknown):unknown {\n if (value instanceof Uint8Array) {\n return {$leafrelay:'bytes', base64:Buffer.from(value).toString('base64')} satisfies EncodedBinary;\n }\n if (Array.isArray(value)) { return value.map(encodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, encodeRpcValue(child)]));\n }\n return value;\n}\n\nexport function decodeRpcValue(value:unknown):unknown {\n if (isEncodedBinary(value)) { return Uint8Array.from(Buffer.from(value.base64, 'base64')); }\n if (Array.isArray(value)) { return value.map(decodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, decodeRpcValue(child)]));\n }\n return value;\n}\n","import {\n ExtendedBaseAPI,\n HttpRequestScheduler,\n RemoteProject,\n SocketIOAPI,\n getServerSession,\n normalizeServerUrl,\n readConfig,\n removeKnownServer,\n removeServerSession,\n saveKnownServer,\n saveServerSession,\n serverKey,\n type Identity,\n type ServeRemoteProject,\n type ServerSession,\n} from '@leafrelay/core';\nimport type {\n ProjectEventNotification,\n ProjectOpenResult,\n ServerDescriptor,\n ServerImportParams,\n ServerLoginParams,\n} from '@leafrelay/protocol';\n\nconst SERVER_OPERATIONS = new Set([\n 'userProjectsJson', 'getProjectsJson', 'projectEntitiesJson',\n 'newProject', 'cloneProject', 'renameProject', 'deleteProject',\n 'archiveProject', 'unarchiveProject', 'trashProject', 'untrashProject',\n 'getFile', 'addDoc', 'uploadFile', 'uploadProject', 'addFolder',\n 'deleteEntity', 'deleteAuxFiles', 'renameEntity', 'moveEntity',\n 'compile', 'stopCompile', 'indexAll', 'getMetadata',\n 'proxyRequestToSpellingApi', 'spellingControllerLearn', 'spellingControllerUnlearn',\n 'getProjectSettings', 'updateProjectSettings', 'getFileFromClsi',\n 'proxySyncPdf', 'proxySyncCode', 'getAllTags', 'createTag', 'renameTag',\n 'deleteTag', 'addProjectToTag', 'removeProjectFromTag',\n 'proxyToHistoryApiAndGetUpdates', 'proxyToHistoryApiAndGetFileDiff',\n 'proxyToHistoryApiAndGetFileTreeDiff', 'downloadZipOfVersion',\n 'getLabels', 'createLabel', 'deleteLabel', 'getMessages', 'sendMessage',\n 'refreshLinkedFile', 'createLinkedFile',\n]);\n\nconst PROJECT_OPERATIONS = new Set([\n 'init', 'joinProject', 'joinDoc', 'leaveDoc', 'applyOtUpdate',\n 'getConnectedUsers', 'updatePosition', 'syncFileChanges',\n]);\n\nconst REMOTE_PROJECT_OPERATIONS = new Set([\n 'entry', 'listEntries', 'read', 'write', 'mkdir', 'remove',\n 'getCurrentVersion', 'getFileTreeDiff',\n]);\n\ninterface ServerRuntime {\n key:string;\n session:ServerSession;\n scheduler:HttpRequestScheduler;\n api:ExtendedBaseAPI;\n}\n\ninterface ProjectRuntime {\n key:string;\n server:ServerRuntime;\n projectId:string;\n socket:SocketIOAPI;\n remote:RemoteProject;\n ready:Promise<void>;\n owners:Set<string>;\n replicaReferences:number;\n operationQueue:Promise<void>;\n}\n\nexport interface ProjectLease {\n remote:ServeRemoteProject;\n release():void;\n}\n\nexport interface NetworkRuntimeEvents {\n projectEvent:(owners:ReadonlySet<string>, event:ProjectEventNotification) => void;\n log:(level:'info'|'warn'|'error', message:string) => void;\n}\n\nexport class NetworkRuntimeRegistry {\n private readonly servers = new Map<string,ServerRuntime>();\n private readonly projects = new Map<string,ProjectRuntime>();\n\n constructor(private readonly events:NetworkRuntimeEvents) {}\n\n get projectCount():number { return this.projects.size; }\n\n async listServers():Promise<ServerDescriptor[]> {\n const config = await readConfig();\n const keys = new Set([...Object.keys(config.knownServers ?? {}), ...Object.keys(config.servers)]);\n if (keys.size===0) { keys.add('www.overleaf.com'); }\n return [...keys].sort().map(key => {\n const session = config.servers[key];\n const known = config.knownServers?.[key];\n return {\n name:known?.name ?? key,\n url:known?.url ?? session?.url ?? normalizeServerUrl(key),\n loggedIn:Boolean(session),\n userId:session?.userId,\n userEmail:session?.userEmail,\n };\n });\n }\n\n async addServer(name:string, url:string):Promise<void> {\n await saveKnownServer(name, url);\n }\n\n async removeServer(server:string):Promise<void> {\n const key = serverKey(server);\n for (const project of this.projects.values()) {\n if (project.server.key===key) { await this.stopProject(project); }\n }\n this.servers.delete(key);\n await removeKnownServer(server);\n }\n\n async login(params:ServerLoginParams) {\n const url = normalizeServerUrl(params.server);\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${serverKey(url)} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const api = new ExtendedBaseAPI(url, scheduler);\n const response = params.cookie\n ? await api.cookiesLogin(params.cookie)\n : await api.passportLogin(params.email ?? '', params.password ?? '');\n if (response.type!=='success' || !response.identity || !response.userInfo) {\n throw new Error(response.message || `Login to ${url} failed.`);\n }\n const session:ServerSession = {\n url,\n userId:response.userInfo.userId,\n userEmail:response.userInfo.userEmail || params.email || '',\n identity:response.identity,\n updatedAt:new Date().toISOString(),\n };\n await saveServerSession(session);\n this.servers.set(serverKey(url), {key:serverKey(url), session, scheduler, api});\n return {userId:session.userId, userEmail:session.userEmail};\n }\n\n async importSession(params:ServerImportParams) {\n const result = await this.login({server:params.url, cookie:params.identity.cookies});\n await saveKnownServer(params.name, params.url);\n return result;\n }\n\n async logout(server:string):Promise<void> {\n const runtime = await this.requireServer(server);\n await runtime.api.logout(runtime.session.identity);\n await removeServerSession(server);\n this.servers.delete(runtime.key);\n }\n\n async callServer(server:string, operation:string, args:unknown[]):Promise<unknown> {\n if (!SERVER_OPERATIONS.has(operation)) { throw new Error(`Unsupported server operation: ${operation}.`); }\n const runtime = await this.requireServer(server);\n const method = (runtime.api as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Server operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => Promise<unknown>).call(runtime.api, runtime.session.identity, ...args);\n }\n\n async openProject(clientId:string, server:string, projectId:string):Promise<ProjectOpenResult> {\n const runtime = await this.getOrCreateProject(server, projectId);\n const shared = runtime.owners.size!==0 || runtime.replicaReferences!==0;\n runtime.owners.add(clientId);\n await runtime.ready;\n return {projectKey:runtime.key, shared};\n }\n\n closeProject(clientId:string, projectKey:string):void {\n const runtime = this.requireProject(projectKey);\n runtime.owners.delete(clientId);\n this.scheduleProjectStop(runtime);\n }\n\n async callProject(projectKey:string, operation:string, args:unknown[]):Promise<unknown> {\n const runtime = this.requireProject(projectKey);\n await runtime.ready;\n if (operation.startsWith('remote.')) {\n const remoteOperation = operation.slice('remote.'.length);\n if (!REMOTE_PROJECT_OPERATIONS.has(remoteOperation)) {\n throw new Error(`Unsupported remote project operation: ${remoteOperation}.`);\n }\n const method = (runtime.remote as unknown as Record<string,unknown>)[remoteOperation];\n if (typeof method!=='function') { throw new Error(`Remote project operation ${remoteOperation} is unavailable.`); }\n return this.enqueueProjectOperation(runtime, () => (\n (method as (...values:unknown[]) => unknown).apply(runtime.remote, args)\n ));\n }\n if (!PROJECT_OPERATIONS.has(operation)) { throw new Error(`Unsupported project operation: ${operation}.`); }\n const method = (runtime.socket as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Project operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => unknown).apply(runtime.socket, args);\n }\n\n async acquireReplica(server:string, projectId:string):Promise<ProjectLease> {\n const runtime = await this.getOrCreateProject(server, projectId);\n runtime.replicaReferences += 1;\n await runtime.ready;\n let released = false;\n return {\n remote:this.replicaRemote(runtime),\n release:() => {\n if (released) { return; }\n released = true;\n runtime.replicaReferences -= 1;\n this.scheduleProjectStop(runtime);\n },\n };\n }\n\n detachClient(clientId:string):void {\n for (const runtime of this.projects.values()) {\n if (runtime.owners.delete(clientId)) { this.scheduleProjectStop(runtime); }\n }\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.projects.values()].map(runtime => this.stopProject(runtime)));\n this.servers.clear();\n }\n\n private async requireServer(server:string):Promise<ServerRuntime> {\n const key = serverKey(server);\n const existing = this.servers.get(key);\n if (existing) { return existing; }\n const session = await getServerSession(server);\n if (!session) { throw new Error(`Not logged in to ${key}.`); }\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${key} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const runtime = {key, session, scheduler, api:new ExtendedBaseAPI(session.url, scheduler)};\n this.servers.set(key, runtime);\n return runtime;\n }\n\n private async getOrCreateProject(server:string, projectId:string):Promise<ProjectRuntime> {\n const serverRuntime = await this.requireServer(server);\n const key = `${serverRuntime.key}:${projectId}`;\n const existing = this.projects.get(key);\n if (existing) { return existing; }\n const socket = new SocketIOAPI(serverRuntime.session.url, serverRuntime.api, serverRuntime.session.identity, projectId);\n const remote = new RemoteProject(\n serverRuntime.session.url,\n projectId,\n serverRuntime.session.identity.cookies,\n {api:serverRuntime.api, identity:serverRuntime.session.identity, socket},\n );\n const runtime:ProjectRuntime = {\n key,\n server:serverRuntime,\n projectId,\n socket,\n remote,\n ready:Promise.resolve(),\n owners:new Set(),\n replicaReferences:0,\n operationQueue:Promise.resolve(),\n };\n runtime.ready = remote.connect().then(() => this.registerProjectEvents(runtime)).catch(error => {\n this.projects.delete(key);\n socket.disconnect();\n throw error;\n });\n this.projects.set(key, runtime);\n return runtime;\n }\n\n private registerProjectEvents(runtime:ProjectRuntime):void {\n const emit = (event:string, ...args:unknown[]) => this.events.projectEvent(runtime.owners, {\n projectKey:runtime.key,\n event,\n args,\n });\n runtime.socket.updateEventHandlers({\n onFileCreated:(...args) => emit('onFileCreated', ...args),\n onFileRenamed:(...args) => emit('onFileRenamed', ...args),\n onFileRemoved:(...args) => emit('onFileRemoved', ...args),\n onFileMoved:(...args) => emit('onFileMoved', ...args),\n onFileChanged:(...args) => emit('onFileChanged', ...args),\n onDisconnected:(reason) => emit('onDisconnected', reason),\n onConnectionAccepted:(...args) => emit('onConnectionAccepted', ...args),\n onClientUpdated:(...args) => emit('onClientUpdated', ...args),\n onClientDisconnected:(...args) => emit('onClientDisconnected', ...args),\n onReceivedMessage:(...args) => emit('onReceivedMessage', ...args),\n onSpellCheckLanguageUpdated:(...args) => emit('onSpellCheckLanguageUpdated', ...args),\n onCompilerUpdated:(...args) => emit('onCompilerUpdated', ...args),\n onRootDocUpdated:(...args) => emit('onRootDocUpdated', ...args),\n });\n }\n\n private requireProject(projectKey:string):ProjectRuntime {\n const runtime = this.projects.get(projectKey);\n if (!runtime) { throw new Error(`Unknown project runtime ${projectKey}.`); }\n return runtime;\n }\n\n private replicaRemote(runtime:ProjectRuntime):ServeRemoteProject {\n return {\n connect:async () => {},\n disconnect:() => {},\n listEntries:() => runtime.remote.listEntries(),\n entry:path => runtime.remote.entry(path),\n read:path => this.enqueueProjectOperation(runtime, () => runtime.remote.read(path)),\n write:(path, content) => this.enqueueProjectOperation(runtime, () => runtime.remote.write(path, content)),\n remove:path => this.enqueueProjectOperation(runtime, () => runtime.remote.remove(path)),\n getCurrentVersion:() => this.enqueueProjectOperation(runtime, () => runtime.remote.getCurrentVersion()),\n getFileTreeDiff:(from, to) => this.enqueueProjectOperation(runtime, () => runtime.remote.getFileTreeDiff(from, to)),\n onChange:handler => runtime.remote.onChange(handler),\n onReconnect:handler => runtime.remote.onReconnect(handler),\n };\n }\n\n private enqueueProjectOperation<T>(runtime:ProjectRuntime, operation:() => T|Promise<T>):Promise<T> {\n const result = runtime.operationQueue.then(operation);\n runtime.operationQueue = result.then(() => undefined, () => undefined);\n return result;\n }\n\n private scheduleProjectStop(runtime:ProjectRuntime):void {\n if (runtime.owners.size!==0 || runtime.replicaReferences!==0) { return; }\n void this.stopProject(runtime);\n }\n\n private async stopProject(runtime:ProjectRuntime):Promise<void> {\n if (!this.projects.delete(runtime.key)) { return; }\n runtime.socket.disconnect();\n }\n}\n","import {randomUUID} from 'node:crypto';\nimport {realpath} from 'node:fs/promises';\nimport {resolve} from 'node:path';\nimport {readProjectSettings, startServe, type RunningServe} from '@leafrelay/core';\nimport type {\n ReplicaAttachParams,\n ReplicaAttachResult,\n ReplicaConflictNotification,\n ReplicaStatus,\n ReplicaStatusNotification,\n} from '@leafrelay/protocol';\n\ninterface ReplicaEntry {\n id:string;\n root:string;\n projectKey:string;\n serverName:string;\n projectId:string;\n projectName:string;\n owners:Set<string>;\n running:RunningServe;\n status:ReplicaStatus;\n}\n\ntype ReplicaStarter = (directory:string, options:NonNullable<Parameters<typeof startServe>[1]>) => Promise<RunningServe>;\n\nexport class ReplicaAlreadyActiveError extends Error {\n readonly code = 'ReplicaAlreadyActive';\n\n constructor(readonly projectId:string, readonly activeRoot:string, readonly requestedRoot:string) {\n super(`Overleaf project ${projectId} is already synchronized by ${activeRoot}; ${requestedRoot} cannot become a second writable replica.`);\n }\n}\n\nexport interface ReplicaRegistryEvents {\n status:(owners:ReadonlySet<string>, notification:ReplicaStatusNotification) => void;\n conflict:(owners:ReadonlySet<string>, notification:ReplicaConflictNotification) => void;\n empty:() => void;\n log:(message:string) => void;\n}\n\nexport class ReplicaRegistry {\n private readonly byId = new Map<string,ReplicaEntry>();\n private readonly byRoot = new Map<string,ReplicaEntry>();\n private readonly byProject = new Map<string,ReplicaEntry>();\n private readonly projectOperations = new Map<string,Promise<void>>();\n private readonly clients = new Set<string>();\n\n constructor(\n private readonly events:ReplicaRegistryEvents,\n private readonly start:ReplicaStarter=startServe,\n ) {}\n\n get size():number { return this.byId.size; }\n\n registerClient(clientId:string):void {\n this.clients.add(clientId);\n }\n\n async attach(clientId:string, params:ReplicaAttachParams):Promise<ReplicaAttachResult> {\n const root = await realpath(resolve(params.directory));\n const settings = await readProjectSettings(root);\n const projectKey = `${settings.serverName}\\0${settings.projectId}`;\n return this.withProjectLock(projectKey, () => this.attachResolved(clientId, params, root, settings, projectKey));\n }\n\n private async attachResolved(\n clientId:string,\n params:ReplicaAttachParams,\n root:string,\n settings:Awaited<ReturnType<typeof readProjectSettings>>,\n projectKey:string,\n ):Promise<ReplicaAttachResult> {\n if (!this.clients.has(clientId)) { throw new Error('The replica client disconnected before attachment started.'); }\n const rootEntry = this.byRoot.get(root);\n if (rootEntry) {\n if (rootEntry.projectKey!==projectKey) {\n throw new Error(`${root} is already registered for another Overleaf project.`);\n }\n this.addOwner(rootEntry, clientId);\n return this.result(rootEntry, true);\n }\n const projectEntry = this.byProject.get(projectKey);\n if (projectEntry) {\n throw new ReplicaAlreadyActiveError(settings.projectId, projectEntry.root, root);\n }\n\n const id = randomUUID();\n const owners = new Set([clientId]);\n const status:ReplicaStatus = {state:'starting'};\n let entry:ReplicaEntry|undefined;\n this.events.status(owners, {replicaId:id, status});\n try {\n const running = await this.start(root, {\n cookie:params.cookie,\n log:message => this.events.log(`[${settings.projectName}] ${message}`),\n onConflict:(path, reason) => {\n if (!entry) { return; }\n entry.status = {state:'paused', message:`Conflict in ${path}`};\n this.events.conflict(entry.owners, {\n replicaId:entry.id,\n path,\n reason,\n conflicts:entry.running.conflicts(),\n });\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n },\n });\n if (!this.clients.has(clientId)) {\n await running.stop();\n this.events.empty();\n throw new Error('The replica client disconnected before attachment completed.');\n }\n entry = {\n id,\n root,\n projectKey,\n serverName:settings.serverName,\n projectId:settings.projectId,\n projectName:settings.projectName,\n owners,\n running,\n status:running.conflicts().length===0 ? {state:'active'} : {state:'paused'},\n };\n this.byId.set(id, entry);\n this.byRoot.set(root, entry);\n this.byProject.set(projectKey, entry);\n this.events.status(owners, {replicaId:id, status:entry.status});\n return this.result(entry, false);\n } catch (error) {\n const failed:ReplicaStatus = {state:'error', message:error instanceof Error ? error.message : String(error)};\n this.events.status(owners, {replicaId:id, status:failed});\n throw error;\n }\n }\n\n async detach(clientId:string, replicaId:string):Promise<void> {\n const entry = this.require(replicaId);\n await this.withProjectLock(entry.projectKey, async () => {\n entry.owners.delete(clientId);\n if (entry.owners.size===0) { await this.stop(entry); }\n });\n }\n\n async detachClient(clientId:string):Promise<void> {\n this.clients.delete(clientId);\n const owned = [...this.byId.values()].filter(entry => entry.owners.has(clientId));\n await Promise.all(owned.map(entry => this.withProjectLock(entry.projectKey, async () => {\n entry.owners.delete(clientId);\n if (entry.owners.size===0) { await this.stop(entry); }\n })));\n }\n\n async resolveConflict(replicaId:string, path:string, winner:'local'|'remote'):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.resolveConflict(path, winner);\n entry.status = entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n async retry(replicaId:string, path:string):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.retry(path);\n entry.status = entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n list() {\n return [...this.byId.values()].map(entry => ({\n id:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n clients:entry.owners.size,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n }));\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.byId.values()].map(entry => this.stop(entry)));\n }\n\n private addOwner(entry:ReplicaEntry, clientId:string):void {\n entry.owners.add(clientId);\n }\n\n private async stop(entry:ReplicaEntry):Promise<void> {\n if (!this.byId.delete(entry.id)) { return; }\n this.byRoot.delete(entry.root);\n this.byProject.delete(entry.projectKey);\n entry.status = {state:'stopping'};\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n await entry.running.stop();\n this.events.empty();\n }\n\n private require(replicaId:string):ReplicaEntry {\n const entry = this.byId.get(replicaId);\n if (!entry) { throw new Error(`Unknown replica ${replicaId}.`); }\n return entry;\n }\n\n private result(entry:ReplicaEntry, shared:boolean):ReplicaAttachResult {\n return {\n replicaId:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n shared,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n };\n }\n\n private async withProjectLock<T>(projectKey:string, operation:() => Promise<T>):Promise<T> {\n const previous = this.projectOperations.get(projectKey) ?? Promise.resolve();\n let release!:() => void;\n const current = new Promise<void>(resolveOperation => { release = resolveOperation; });\n this.projectOperations.set(projectKey, current);\n await previous;\n try {\n return await operation();\n } finally {\n release();\n if (this.projectOperations.get(projectKey)===current) { this.projectOperations.delete(projectKey); }\n }\n }\n}\n","import type {Socket} from 'node:net';\nimport {\n createMessageConnection,\n SocketMessageReader,\n SocketMessageWriter,\n type Message,\n type MessageConnection,\n} from 'vscode-jsonrpc/node';\n\nconst CLOSED_SOCKET_ERRORS = new Set([\n 'EPIPE',\n 'ECONNRESET',\n 'ERR_SOCKET_CLOSED',\n 'ERR_STREAM_DESTROYED',\n 'ERR_STREAM_WRITE_AFTER_END',\n]);\n\nclass LeafRelaySocketWriter extends SocketMessageWriter {\n constructor(private readonly transportSocket:Socket) {\n super(transportSocket);\n }\n\n override async write(message:Message):Promise<void> {\n try {\n await super.write(message);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (this.transportSocket.destroyed || this.transportSocket.writableEnded || (code && CLOSED_SOCKET_ERRORS.has(code))) { return; }\n throw error;\n }\n }\n}\n\nexport function createSocketRpcConnection(socket:Socket):MessageConnection {\n return createMessageConnection(new SocketMessageReader(socket), new LeafRelaySocketWriter(socket));\n}\n","import {LeafRelayDaemonServer} from './server';\n\nconst server = new LeafRelayDaemonServer();\n\nconst stop = () => {\n process.off('SIGINT', stop);\n process.off('SIGTERM', stop);\n void server.stop().finally(() => process.exit(0));\n};\n\nprocess.on('SIGINT', stop);\nprocess.on('SIGTERM', stop);\nprocess.on('uncaughtException', error => {\n console.error(error);\n void server.stop().finally(() => process.exit(1));\n});\nprocess.on('unhandledRejection', error => {\n console.error(error);\n void server.stop().finally(() => process.exit(1));\n});\n\nvoid server.start().catch(error => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":"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","names":["randomUUID","server","method","resolve","resolve","randomUUID"]}
|
|
1
|
+
{"version":3,"sources":["../../daemon/src/server.ts","../../protocol/src/index.ts","../../daemon/src/paths.ts","../../daemon/src/codec.ts","../../daemon/src/networkRuntime.ts","../../daemon/src/replicaRegistry.ts","../../daemon/src/transport.ts","../../daemon/src/main.ts"],"sourcesContent":["import {randomBytes, randomUUID} from 'node:crypto';\nimport {appendFile, chmod, mkdir, readFile, rm, writeFile} from 'node:fs/promises';\nimport {createServer, type Server, type Socket} from 'node:net';\nimport {formatWithOptions} from 'node:util';\nimport {\n readProjectSettings,\n setLogSink,\n startServe,\n} from '@leafrelay/core';\nimport {\n LEAFRELAY_PROTOCOL_VERSION,\n RPC_METHOD,\n RPC_NOTIFICATION,\n type DaemonMetadata,\n type DaemonStatus,\n type InitializeParams,\n type InitializeResult,\n type LogNotification,\n type ReplicaAttachParams,\n type ReplicaConflictResolutionParams,\n type ReplicaStatusNotification,\n type ReplicaConflictNotification,\n type ProjectCallParams,\n type ProjectEventNotification,\n type ProjectOpenParams,\n type ServerCallParams,\n type ServerImportParams,\n type ServerLoginParams,\n} from '@leafrelay/protocol';\nimport {ResponseError, type MessageConnection} from 'vscode-jsonrpc/node';\nimport {daemonPaths, type DaemonPaths} from './paths';\nimport {decodeRpcValue, encodeRpcValue} from './codec';\nimport {NetworkRuntimeRegistry} from './networkRuntime';\nimport {ReplicaAlreadyActiveError, ReplicaRegistry} from './replicaRegistry';\nimport {createSocketRpcConnection} from './transport';\n\ndeclare const LEAFRELAY_DAEMON_VERSION:string;\n\nconst IDLE_EXIT_MS = 60_000;\nconst REPLICA_ALREADY_ACTIVE = -32010;\nconst daemonVersion = typeof LEAFRELAY_DAEMON_VERSION==='string' ? LEAFRELAY_DAEMON_VERSION : 'development';\n\ninterface ClientConnection {\n leaseId:string;\n socket:Socket;\n rpc:MessageConnection;\n clientId?:string;\n initialized:boolean;\n}\n\nexport interface DaemonServerOptions {\n paths?:DaemonPaths;\n token?:string;\n exitOnIdle?:boolean;\n}\n\nexport class LeafRelayDaemonServer {\n private readonly paths:DaemonPaths;\n private readonly token:string;\n private readonly startedAt = new Date().toISOString();\n private readonly clients = new Set<ClientConnection>();\n private readonly network:NetworkRuntimeRegistry;\n private readonly replicas:ReplicaRegistry;\n private server?:Server;\n private idleTimer?:NodeJS.Timeout;\n private stopping?:Promise<void>;\n\n constructor(private readonly options:DaemonServerOptions={}) {\n this.paths = options.paths ?? daemonPaths();\n this.token = options.token ?? randomBytes(32).toString('hex');\n this.network = new NetworkRuntimeRegistry({\n projectEvent:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.projectEvent, notification),\n log:(level, message) => void this.log(level, message),\n });\n this.replicas = new ReplicaRegistry({\n status:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaStatus, notification),\n conflict:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaConflict, notification),\n empty:() => this.scheduleIdleExit(),\n log:message => void this.log('info', message),\n }, async (directory, startOptions) => {\n const settings = await readProjectSettings(directory);\n const lease = await this.network.acquireReplica(settings.serverName, settings.projectId);\n try {\n const running = await startServe(directory, {...startOptions, remote:lease.remote});\n return {\n ...running,\n stop:async () => {\n await running.stop();\n lease.release();\n },\n };\n } catch (error) {\n lease.release();\n throw error;\n }\n });\n }\n\n async start():Promise<DaemonMetadata> {\n await mkdir(this.paths.home, {recursive:true, mode:0o700});\n setLogSink((level, args) => void this.log(level, formatWithOptions({depth:5, breakLength:Infinity}, ...args)));\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n this.server = createServer(socket => this.accept(socket));\n await new Promise<void>((resolveListen, reject) => {\n this.server!.once('error', reject);\n this.server!.listen(this.paths.socketPath, () => {\n this.server!.off('error', reject);\n resolveListen();\n });\n });\n if (process.platform!=='win32') { await chmod(this.paths.socketPath, 0o600); }\n const metadata:DaemonMetadata = {\n pid:process.pid,\n socketPath:this.paths.socketPath,\n token:this.token,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n version:daemonVersion,\n startedAt:this.startedAt,\n };\n await writeFile(this.paths.metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`, {encoding:'utf8', mode:0o600});\n await chmod(this.paths.metadataPath, 0o600);\n await this.log('info', `Daemon ${daemonVersion} listening on ${this.paths.socketPath}.`);\n this.scheduleIdleExit();\n return metadata;\n }\n\n async stop():Promise<void> {\n if (this.stopping) { return this.stopping; }\n this.stopping = this.performStop();\n return this.stopping;\n }\n\n status():DaemonStatus {\n return {\n pid:process.pid,\n version:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n startedAt:this.startedAt,\n clients:this.clients.size,\n projects:this.network.projectCount,\n replicas:this.replicas.list(),\n };\n }\n\n private accept(socket:Socket):void {\n this.cancelIdleExit();\n const rpc = createSocketRpcConnection(socket);\n const client:ClientConnection = {leaseId:randomUUID(), socket, rpc, initialized:false};\n this.clients.add(client);\n rpc.onRequest(RPC_METHOD.initialize, (params:InitializeParams) => this.initialize(client, params));\n rpc.onRequest(RPC_METHOD.daemonStatus, () => this.authorized(client, () => this.status()));\n rpc.onRequest(RPC_METHOD.daemonShutdown, () => this.authorized(client, async () => {\n setTimeout(() => void this.stop(), 25);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaAttach, (params:ReplicaAttachParams) => this.authorized(client, async () => {\n try {\n return await this.replicas.attach(client.leaseId, params);\n } catch (error) {\n if (error instanceof ReplicaAlreadyActiveError) {\n throw new ResponseError(REPLICA_ALREADY_ACTIVE, error.message, {\n code:error.code,\n projectId:error.projectId,\n activeRoot:error.activeRoot,\n requestedRoot:error.requestedRoot,\n });\n }\n throw error;\n }\n }));\n rpc.onRequest(RPC_METHOD.replicaDetach, (params:{replicaId:string}) => this.authorized(client, async () => {\n await this.replicas.detach(client.leaseId, params.replicaId);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaResolveConflict, (params:ReplicaConflictResolutionParams) => this.authorized(client, async () => {\n await this.replicas.resolveConflict(params.replicaId, params.path, params.winner);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaRetry, (params:{replicaId:string; path:string}) => this.authorized(client, async () => {\n await this.replicas.retry(params.replicaId, params.path);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverList, () => this.authorized(client, () => this.network.listServers()));\n rpc.onRequest(RPC_METHOD.serverAdd, (params:{name:string; url:string}) => this.authorized(client, async () => {\n await this.network.addServer(params.name, params.url);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverRemove, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.removeServer(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.sessionLogin, (params:ServerLoginParams) => this.authorized(client, () => this.network.login(params)));\n rpc.onRequest(RPC_METHOD.sessionImport, (params:ServerImportParams) => this.authorized(client, () => this.network.importSession(params)));\n rpc.onRequest(RPC_METHOD.sessionLogout, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.logout(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverCall, (params:ServerCallParams) => this.authorized(client, async () => {\n const result = await this.network.callServer(params.server, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(result);\n }));\n rpc.onRequest(RPC_METHOD.projectOpen, (params:ProjectOpenParams) => this.authorized(client, () => (\n this.network.openProject(client.leaseId, params.server, params.projectId)\n )));\n rpc.onRequest(RPC_METHOD.projectClose, (params:{projectKey:string}) => this.authorized(client, () => {\n this.network.closeProject(client.leaseId, params.projectKey);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.projectCall, (params:ProjectCallParams) => this.authorized(client, async () => {\n const result = await this.network.callProject(params.projectKey, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(await result);\n }));\n rpc.onClose(() => void this.closeClient(client));\n rpc.onError(error => void this.log('error', `JSON-RPC connection error: ${String(error[0])}`));\n rpc.listen();\n }\n\n private initialize(client:ClientConnection, params:InitializeParams):InitializeResult {\n if (params.token!==this.token) { throw new ResponseError(-32001, 'Daemon authentication failed.'); }\n if (params.protocolVersion!==LEAFRELAY_PROTOCOL_VERSION) {\n throw new ResponseError(-32002, `Protocol ${params.protocolVersion} is incompatible with daemon protocol ${LEAFRELAY_PROTOCOL_VERSION}.`);\n }\n if (!params.clientId) { throw new ResponseError(-32602, 'clientId is required.'); }\n client.clientId = params.clientId;\n client.initialized = true;\n this.replicas.registerClient(client.leaseId);\n void this.log('info', `${params.clientName} ${params.clientVersion} connected (${params.clientId}).`);\n return {\n daemonVersion:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n pid:process.pid,\n startedAt:this.startedAt,\n };\n }\n\n private async authorized<T>(client:ClientConnection, operation:() => T|Promise<T>):Promise<T> {\n if (!client.initialized) { throw new ResponseError(-32001, 'Initialize the daemon connection first.'); }\n try {\n return await operation();\n } catch (error) {\n if (error instanceof ResponseError) { throw error; }\n const message = error instanceof Error ? error.message : String(error);\n await this.log('error', `RPC operation failed: ${formatWithOptions({depth:5, breakLength:Infinity}, error)}`);\n throw new ResponseError(-32603, message);\n }\n }\n\n private async closeClient(client:ClientConnection):Promise<void> {\n if (!this.clients.delete(client)) { return; }\n if (client.clientId) {\n try {\n await this.replicas.detachClient(client.leaseId);\n } catch (error) {\n await this.log('error', `Failed to stop replicas for a disconnected client: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n this.network.detachClient(client.leaseId);\n }\n }\n this.scheduleIdleExit();\n }\n\n private notifyOwners(\n owners:ReadonlySet<string>,\n method:typeof RPC_NOTIFICATION.replicaStatus|typeof RPC_NOTIFICATION.replicaConflict|typeof RPC_NOTIFICATION.projectEvent,\n notification:ReplicaStatusNotification|ReplicaConflictNotification|ProjectEventNotification,\n ):void {\n for (const client of this.clients) {\n if (owners.has(client.leaseId)) { this.notifyClient(client, method, notification); }\n }\n }\n\n private async log(level:LogNotification['level'], message:string):Promise<void> {\n const notification:LogNotification = {timestamp:new Date().toISOString(), level, message};\n await appendFile(this.paths.logPath, `${notification.timestamp} [${level}] ${message}\\n`, {encoding:'utf8', mode:0o600});\n for (const client of this.clients) {\n if (client.initialized) { this.notifyClient(client, RPC_NOTIFICATION.log, notification); }\n }\n }\n\n private notifyClient(client:ClientConnection, method:string, notification:unknown):void {\n if (!this.clients.has(client) || client.socket.destroyed) { return; }\n void client.rpc.sendNotification(method, notification).catch(() => this.closeClient(client));\n }\n\n private scheduleIdleExit():void {\n if (this.options.exitOnIdle===false || this.clients.size!==0 || this.replicas.size!==0 || this.idleTimer) { return; }\n this.idleTimer = setTimeout(() => void this.stop(), IDLE_EXIT_MS);\n this.idleTimer.unref();\n }\n\n private cancelIdleExit():void {\n if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = undefined; }\n }\n\n private async performStop():Promise<void> {\n this.cancelIdleExit();\n await this.replicas.stopAll();\n await this.network.stopAll();\n setLogSink(undefined);\n for (const client of this.clients) {\n client.rpc.dispose();\n client.socket.destroy();\n }\n this.clients.clear();\n if (this.server) {\n await new Promise<void>(resolveClose => this.server!.close(() => resolveClose()));\n }\n await rm(this.paths.metadataPath, {force:true});\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n }\n}\n\nexport async function readDaemonMetadata(paths:DaemonPaths=daemonPaths()):Promise<DaemonMetadata|undefined> {\n try {\n return JSON.parse(await readFile(paths.metadataPath, 'utf8')) as DaemonMetadata;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw error;\n }\n}\n","export const LEAFRELAY_PROTOCOL_VERSION = 1;\n\nexport const RPC_METHOD = {\n initialize:'leafrelay/initialize',\n daemonStatus:'leafrelay/daemon/status',\n daemonShutdown:'leafrelay/daemon/shutdown',\n replicaAttach:'leafrelay/replica/attach',\n replicaDetach:'leafrelay/replica/detach',\n replicaResolveConflict:'leafrelay/replica/resolveConflict',\n replicaRetry:'leafrelay/replica/retry',\n sessionImport:'leafrelay/session/import',\n sessionLogin:'leafrelay/session/login',\n sessionLogout:'leafrelay/session/logout',\n serverList:'leafrelay/server/list',\n serverAdd:'leafrelay/server/add',\n serverRemove:'leafrelay/server/remove',\n serverCall:'leafrelay/server/call',\n projectOpen:'leafrelay/project/open',\n projectClose:'leafrelay/project/close',\n projectCall:'leafrelay/project/call',\n} as const;\n\nexport const RPC_NOTIFICATION = {\n log:'leafrelay/log',\n replicaStatus:'leafrelay/replica/status',\n replicaConflict:'leafrelay/replica/conflict',\n projectEvent:'leafrelay/project/event',\n} as const;\n\nexport interface InitializeParams {\n token:string;\n clientId:string;\n clientName:'cli'|'vscode'|'library'|'test';\n clientVersion:string;\n protocolVersion:number;\n}\n\nexport interface InitializeResult {\n daemonVersion:string;\n protocolVersion:number;\n pid:number;\n startedAt:string;\n}\n\nexport interface DaemonStatus {\n pid:number;\n version:string;\n protocolVersion:number;\n startedAt:string;\n clients:number;\n projects:number;\n replicas:Array<{\n id:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n clients:number;\n status:ReplicaStatus;\n conflicts:string[];\n }>;\n}\n\nexport type ReplicaState = 'starting'|'syncing'|'active'|'paused'|'stopping'|'error';\n\nexport interface ReplicaStatus {\n state:ReplicaState;\n message?:string;\n}\n\nexport interface ReplicaAttachParams {\n directory:string;\n cookie?:string;\n}\n\nexport interface ReplicaAttachResult {\n replicaId:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n shared:boolean;\n status:ReplicaStatus;\n conflicts:string[];\n}\n\nexport interface ReplicaConflictResolutionParams {\n replicaId:string;\n path:string;\n winner:'local'|'remote';\n}\n\nexport interface ReplicaStatusNotification {\n replicaId:string;\n status:ReplicaStatus;\n}\n\nexport interface ReplicaConflictNotification {\n replicaId:string;\n path:string;\n reason:string;\n conflicts:string[];\n}\n\nexport interface LogNotification {\n timestamp:string;\n level:'info'|'warn'|'error';\n message:string;\n}\n\nexport interface DaemonMetadata {\n pid:number;\n socketPath:string;\n token:string;\n protocolVersion:number;\n version:string;\n startedAt:string;\n}\n\nexport interface ServerDescriptor {\n name:string;\n url:string;\n loggedIn:boolean;\n userId?:string;\n userEmail?:string;\n}\n\nexport interface ServerLoginParams {\n server:string;\n cookie?:string;\n email?:string;\n password?:string;\n}\n\nexport interface ServerImportParams {\n name:string;\n url:string;\n userId:string;\n userEmail:string;\n identity:{cookies:string; csrfToken:string};\n}\n\nexport interface ServerCallParams {\n server:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectOpenParams {\n server:string;\n projectId:string;\n}\n\nexport interface ProjectOpenResult {\n projectKey:string;\n shared:boolean;\n}\n\nexport interface ProjectCallParams {\n projectKey:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectEventNotification {\n projectKey:string;\n event:string;\n args:unknown[];\n}\n\nexport interface EncodedBinary {\n $leafrelay:'bytes';\n base64:string;\n}\n","import {createHash} from 'node:crypto';\nimport {homedir} from 'node:os';\nimport {join, resolve} from 'node:path';\n\nexport interface DaemonPaths {\n home:string;\n socketPath:string;\n metadataPath:string;\n logPath:string;\n startupLockPath:string;\n}\n\nexport function daemonPaths(environment:NodeJS.ProcessEnv=process.env):DaemonPaths {\n const home = environment.LEAFRELAY_HOME ? resolve(environment.LEAFRELAY_HOME) : join(homedir(), '.leafrelay');\n const socketPath = process.platform==='win32'\n ? `\\\\\\\\.\\\\pipe\\\\leafrelay-${createHash('sha256').update(home).digest('hex').slice(0, 16)}`\n : join(home, 'daemon.sock');\n return {\n home,\n socketPath,\n metadataPath:join(home, 'daemon.json'),\n logPath:join(home, 'daemon.log'),\n startupLockPath:join(home, 'daemon.starting'),\n };\n}\n","import type {EncodedBinary} from '@leafrelay/protocol';\n\nfunction isEncodedBinary(value:unknown):value is EncodedBinary {\n return typeof value==='object' && value!==null\n && (value as Partial<EncodedBinary>).$leafrelay==='bytes'\n && typeof (value as Partial<EncodedBinary>).base64==='string';\n}\n\nexport function encodeRpcValue(value:unknown):unknown {\n if (value instanceof Uint8Array) {\n return {$leafrelay:'bytes', base64:Buffer.from(value).toString('base64')} satisfies EncodedBinary;\n }\n if (Array.isArray(value)) { return value.map(encodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, encodeRpcValue(child)]));\n }\n return value;\n}\n\nexport function decodeRpcValue(value:unknown):unknown {\n if (isEncodedBinary(value)) { return Uint8Array.from(Buffer.from(value.base64, 'base64')); }\n if (Array.isArray(value)) { return value.map(decodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, decodeRpcValue(child)]));\n }\n return value;\n}\n","import {\n ExtendedBaseAPI,\n HttpRequestScheduler,\n RemoteProject,\n SocketIOAPI,\n getServerSession,\n normalizeServerUrl,\n readConfig,\n removeKnownServer,\n removeServerSession,\n saveKnownServer,\n saveServerSession,\n serverKey,\n type Identity,\n type ServeRemoteProject,\n type ServerSession,\n} from '@leafrelay/core';\nimport type {\n ProjectEventNotification,\n ProjectOpenResult,\n ServerDescriptor,\n ServerImportParams,\n ServerLoginParams,\n} from '@leafrelay/protocol';\n\nconst SERVER_OPERATIONS = new Set([\n 'userProjectsJson', 'getProjectsJson', 'projectEntitiesJson',\n 'newProject', 'cloneProject', 'renameProject', 'deleteProject',\n 'archiveProject', 'unarchiveProject', 'trashProject', 'untrashProject',\n 'getFile', 'addDoc', 'uploadFile', 'uploadProject', 'addFolder',\n 'deleteEntity', 'deleteAuxFiles', 'renameEntity', 'moveEntity',\n 'compile', 'stopCompile', 'indexAll', 'getMetadata',\n 'proxyRequestToSpellingApi', 'spellingControllerLearn', 'spellingControllerUnlearn',\n 'getProjectSettings', 'updateProjectSettings', 'getFileFromClsi',\n 'proxySyncPdf', 'proxySyncCode', 'getAllTags', 'createTag', 'renameTag',\n 'deleteTag', 'addProjectToTag', 'removeProjectFromTag',\n 'proxyToHistoryApiAndGetUpdates', 'proxyToHistoryApiAndGetFileDiff',\n 'proxyToHistoryApiAndGetFileTreeDiff', 'downloadZipOfVersion',\n 'getLabels', 'createLabel', 'deleteLabel', 'getMessages', 'sendMessage',\n 'refreshLinkedFile', 'createLinkedFile',\n]);\n\nconst PROJECT_OPERATIONS = new Set([\n 'init', 'joinProject', 'joinDoc', 'leaveDoc', 'applyOtUpdate',\n 'getConnectedUsers', 'updatePosition', 'syncFileChanges',\n]);\n\nconst REMOTE_PROJECT_OPERATIONS = new Set([\n 'entry', 'listEntries', 'read', 'write', 'mkdir', 'remove',\n 'getCurrentVersion', 'getFileTreeDiff',\n]);\n\ninterface ServerRuntime {\n key:string;\n session:ServerSession;\n scheduler:HttpRequestScheduler;\n api:ExtendedBaseAPI;\n}\n\ninterface ProjectRuntime {\n key:string;\n server:ServerRuntime;\n projectId:string;\n socket:SocketIOAPI;\n remote:RemoteProject;\n ready:Promise<void>;\n owners:Set<string>;\n replicaReferences:number;\n operationQueue:Promise<void>;\n}\n\nexport interface ProjectLease {\n remote:ServeRemoteProject;\n release():void;\n}\n\nexport interface NetworkRuntimeEvents {\n projectEvent:(owners:ReadonlySet<string>, event:ProjectEventNotification) => void;\n log:(level:'info'|'warn'|'error', message:string) => void;\n}\n\nexport class NetworkRuntimeRegistry {\n private readonly servers = new Map<string,ServerRuntime>();\n private readonly projects = new Map<string,ProjectRuntime>();\n\n constructor(private readonly events:NetworkRuntimeEvents) {}\n\n get projectCount():number { return this.projects.size; }\n\n async listServers():Promise<ServerDescriptor[]> {\n const config = await readConfig();\n const keys = new Set([...Object.keys(config.knownServers ?? {}), ...Object.keys(config.servers)]);\n if (keys.size===0) { keys.add('www.overleaf.com'); }\n return [...keys].sort().map(key => {\n const session = config.servers[key];\n const known = config.knownServers?.[key];\n return {\n name:known?.name ?? key,\n url:known?.url ?? session?.url ?? normalizeServerUrl(key),\n loggedIn:Boolean(session),\n userId:session?.userId,\n userEmail:session?.userEmail,\n };\n });\n }\n\n async addServer(name:string, url:string):Promise<void> {\n await saveKnownServer(name, url);\n }\n\n async removeServer(server:string):Promise<void> {\n const key = serverKey(server);\n for (const project of this.projects.values()) {\n if (project.server.key===key) { await this.stopProject(project); }\n }\n this.servers.delete(key);\n await removeKnownServer(server);\n }\n\n async login(params:ServerLoginParams) {\n const url = normalizeServerUrl(params.server);\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${serverKey(url)} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const api = new ExtendedBaseAPI(url, scheduler);\n const response = params.cookie\n ? await api.cookiesLogin(params.cookie)\n : await api.passportLogin(params.email ?? '', params.password ?? '');\n if (response.type!=='success' || !response.identity || !response.userInfo) {\n throw new Error(response.message || `Login to ${url} failed.`);\n }\n const session:ServerSession = {\n url,\n userId:response.userInfo.userId,\n userEmail:response.userInfo.userEmail || params.email || '',\n identity:response.identity,\n updatedAt:new Date().toISOString(),\n };\n await saveServerSession(session);\n this.servers.set(serverKey(url), {key:serverKey(url), session, scheduler, api});\n return {userId:session.userId, userEmail:session.userEmail};\n }\n\n async importSession(params:ServerImportParams) {\n const result = await this.login({server:params.url, cookie:params.identity.cookies});\n await saveKnownServer(params.name, params.url);\n return result;\n }\n\n async logout(server:string):Promise<void> {\n const runtime = await this.requireServer(server);\n await runtime.api.logout(runtime.session.identity);\n await removeServerSession(server);\n this.servers.delete(runtime.key);\n }\n\n async callServer(server:string, operation:string, args:unknown[]):Promise<unknown> {\n if (!SERVER_OPERATIONS.has(operation)) { throw new Error(`Unsupported server operation: ${operation}.`); }\n const runtime = await this.requireServer(server);\n const method = (runtime.api as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Server operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => Promise<unknown>).call(runtime.api, runtime.session.identity, ...args);\n }\n\n async openProject(clientId:string, server:string, projectId:string):Promise<ProjectOpenResult> {\n const runtime = await this.getOrCreateProject(server, projectId);\n const shared = runtime.owners.size!==0 || runtime.replicaReferences!==0;\n runtime.owners.add(clientId);\n await runtime.ready;\n return {projectKey:runtime.key, shared};\n }\n\n closeProject(clientId:string, projectKey:string):void {\n const runtime = this.requireProject(projectKey);\n runtime.owners.delete(clientId);\n this.scheduleProjectStop(runtime);\n }\n\n async callProject(projectKey:string, operation:string, args:unknown[]):Promise<unknown> {\n const runtime = this.requireProject(projectKey);\n await runtime.ready;\n if (operation.startsWith('remote.')) {\n const remoteOperation = operation.slice('remote.'.length);\n if (!REMOTE_PROJECT_OPERATIONS.has(remoteOperation)) {\n throw new Error(`Unsupported remote project operation: ${remoteOperation}.`);\n }\n const method = (runtime.remote as unknown as Record<string,unknown>)[remoteOperation];\n if (typeof method!=='function') { throw new Error(`Remote project operation ${remoteOperation} is unavailable.`); }\n return this.enqueueProjectOperation(runtime, () => (\n (method as (...values:unknown[]) => unknown).apply(runtime.remote, args)\n ));\n }\n if (!PROJECT_OPERATIONS.has(operation)) { throw new Error(`Unsupported project operation: ${operation}.`); }\n const method = (runtime.socket as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Project operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => unknown).apply(runtime.socket, args);\n }\n\n async acquireReplica(server:string, projectId:string):Promise<ProjectLease> {\n const runtime = await this.getOrCreateProject(server, projectId);\n runtime.replicaReferences += 1;\n await runtime.ready;\n let released = false;\n return {\n remote:this.replicaRemote(runtime),\n release:() => {\n if (released) { return; }\n released = true;\n runtime.replicaReferences -= 1;\n this.scheduleProjectStop(runtime);\n },\n };\n }\n\n detachClient(clientId:string):void {\n for (const runtime of this.projects.values()) {\n if (runtime.owners.delete(clientId)) { this.scheduleProjectStop(runtime); }\n }\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.projects.values()].map(runtime => this.stopProject(runtime)));\n this.servers.clear();\n }\n\n private async requireServer(server:string):Promise<ServerRuntime> {\n const key = serverKey(server);\n const existing = this.servers.get(key);\n if (existing) { return existing; }\n const session = await getServerSession(server);\n if (!session) { throw new Error(`Not logged in to ${key}.`); }\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${key} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const runtime = {key, session, scheduler, api:new ExtendedBaseAPI(session.url, scheduler)};\n this.servers.set(key, runtime);\n return runtime;\n }\n\n private async getOrCreateProject(server:string, projectId:string):Promise<ProjectRuntime> {\n const serverRuntime = await this.requireServer(server);\n const key = `${serverRuntime.key}:${projectId}`;\n const existing = this.projects.get(key);\n if (existing) { return existing; }\n const socket = new SocketIOAPI(serverRuntime.session.url, serverRuntime.api, serverRuntime.session.identity, projectId);\n const remote = new RemoteProject(\n serverRuntime.session.url,\n projectId,\n serverRuntime.session.identity.cookies,\n {api:serverRuntime.api, identity:serverRuntime.session.identity, socket},\n );\n const runtime:ProjectRuntime = {\n key,\n server:serverRuntime,\n projectId,\n socket,\n remote,\n ready:Promise.resolve(),\n owners:new Set(),\n replicaReferences:0,\n operationQueue:Promise.resolve(),\n };\n runtime.ready = remote.connect().then(() => this.registerProjectEvents(runtime)).catch(error => {\n this.projects.delete(key);\n socket.disconnect();\n throw error;\n });\n this.projects.set(key, runtime);\n return runtime;\n }\n\n private registerProjectEvents(runtime:ProjectRuntime):void {\n const emit = (event:string, ...args:unknown[]) => this.events.projectEvent(runtime.owners, {\n projectKey:runtime.key,\n event,\n args,\n });\n runtime.socket.updateEventHandlers({\n onFileCreated:(...args) => emit('onFileCreated', ...args),\n onFileRenamed:(...args) => emit('onFileRenamed', ...args),\n onFileRemoved:(...args) => emit('onFileRemoved', ...args),\n onFileMoved:(...args) => emit('onFileMoved', ...args),\n onFileChanged:(...args) => emit('onFileChanged', ...args),\n onDisconnected:(reason) => emit('onDisconnected', reason),\n onConnectionAccepted:(...args) => emit('onConnectionAccepted', ...args),\n onClientUpdated:(...args) => emit('onClientUpdated', ...args),\n onClientDisconnected:(...args) => emit('onClientDisconnected', ...args),\n onReceivedMessage:(...args) => emit('onReceivedMessage', ...args),\n onSpellCheckLanguageUpdated:(...args) => emit('onSpellCheckLanguageUpdated', ...args),\n onCompilerUpdated:(...args) => emit('onCompilerUpdated', ...args),\n onRootDocUpdated:(...args) => emit('onRootDocUpdated', ...args),\n });\n }\n\n private requireProject(projectKey:string):ProjectRuntime {\n const runtime = this.projects.get(projectKey);\n if (!runtime) { throw new Error(`Unknown project runtime ${projectKey}.`); }\n return runtime;\n }\n\n private replicaRemote(runtime:ProjectRuntime):ServeRemoteProject {\n return {\n connect:async () => {},\n disconnect:() => {},\n listEntries:() => runtime.remote.listEntries(),\n entry:path => runtime.remote.entry(path),\n read:path => this.enqueueProjectOperation(runtime, () => runtime.remote.read(path)),\n write:(path, content) => this.enqueueProjectOperation(runtime, () => runtime.remote.write(path, content)),\n remove:path => this.enqueueProjectOperation(runtime, () => runtime.remote.remove(path)),\n getCurrentVersion:() => this.enqueueProjectOperation(runtime, () => runtime.remote.getCurrentVersion()),\n getFileTreeDiff:(from, to) => this.enqueueProjectOperation(runtime, () => runtime.remote.getFileTreeDiff(from, to)),\n onChange:handler => runtime.remote.onChange(handler),\n onReconnect:handler => runtime.remote.onReconnect(handler),\n };\n }\n\n private enqueueProjectOperation<T>(runtime:ProjectRuntime, operation:() => T|Promise<T>):Promise<T> {\n const result = runtime.operationQueue.then(operation);\n runtime.operationQueue = result.then(() => undefined, () => undefined);\n return result;\n }\n\n private scheduleProjectStop(runtime:ProjectRuntime):void {\n if (runtime.owners.size!==0 || runtime.replicaReferences!==0) { return; }\n void this.stopProject(runtime);\n }\n\n private async stopProject(runtime:ProjectRuntime):Promise<void> {\n if (!this.projects.delete(runtime.key)) { return; }\n runtime.socket.disconnect();\n }\n}\n","import {randomUUID} from 'node:crypto';\nimport {realpath} from 'node:fs/promises';\nimport {resolve} from 'node:path';\nimport {readProjectSettings, startServe, type RunningServe} from '@leafrelay/core';\nimport type {\n ReplicaAttachParams,\n ReplicaAttachResult,\n ReplicaConflictNotification,\n ReplicaStatus,\n ReplicaStatusNotification,\n} from '@leafrelay/protocol';\n\ninterface ReplicaEntry {\n id:string;\n root:string;\n projectKey:string;\n serverName:string;\n projectId:string;\n projectName:string;\n owners:Set<string>;\n running:RunningServe;\n status:ReplicaStatus;\n}\n\ntype ReplicaStarter = (directory:string, options:NonNullable<Parameters<typeof startServe>[1]>) => Promise<RunningServe>;\n\nexport class ReplicaAlreadyActiveError extends Error {\n readonly code = 'ReplicaAlreadyActive';\n\n constructor(readonly projectId:string, readonly activeRoot:string, readonly requestedRoot:string) {\n super(`Overleaf project ${projectId} is already synchronized by ${activeRoot}; ${requestedRoot} cannot become a second writable replica.`);\n }\n}\n\nexport interface ReplicaRegistryEvents {\n status:(owners:ReadonlySet<string>, notification:ReplicaStatusNotification) => void;\n conflict:(owners:ReadonlySet<string>, notification:ReplicaConflictNotification) => void;\n empty:() => void;\n log:(message:string) => void;\n}\n\nexport class ReplicaRegistry {\n private readonly byId = new Map<string,ReplicaEntry>();\n private readonly byRoot = new Map<string,ReplicaEntry>();\n private readonly byProject = new Map<string,ReplicaEntry>();\n private readonly projectOperations = new Map<string,Promise<void>>();\n private readonly clients = new Set<string>();\n\n constructor(\n private readonly events:ReplicaRegistryEvents,\n private readonly start:ReplicaStarter=startServe,\n ) {}\n\n get size():number { return this.byId.size; }\n\n registerClient(clientId:string):void {\n this.clients.add(clientId);\n }\n\n async attach(clientId:string, params:ReplicaAttachParams):Promise<ReplicaAttachResult> {\n const root = await realpath(resolve(params.directory));\n const settings = await readProjectSettings(root);\n const projectKey = `${settings.serverName}\\0${settings.projectId}`;\n return this.withProjectLock(projectKey, () => this.attachResolved(clientId, params, root, settings, projectKey));\n }\n\n private async attachResolved(\n clientId:string,\n params:ReplicaAttachParams,\n root:string,\n settings:Awaited<ReturnType<typeof readProjectSettings>>,\n projectKey:string,\n ):Promise<ReplicaAttachResult> {\n if (!this.clients.has(clientId)) { throw new Error('The replica client disconnected before attachment started.'); }\n const rootEntry = this.byRoot.get(root);\n if (rootEntry) {\n if (rootEntry.projectKey!==projectKey) {\n throw new Error(`${root} is already registered for another Overleaf project.`);\n }\n this.addOwner(rootEntry, clientId);\n return this.result(rootEntry, true);\n }\n const projectEntry = this.byProject.get(projectKey);\n if (projectEntry) {\n throw new ReplicaAlreadyActiveError(settings.projectId, projectEntry.root, root);\n }\n\n const id = randomUUID();\n const owners = new Set([clientId]);\n const status:ReplicaStatus = {state:'starting'};\n let entry:ReplicaEntry|undefined;\n this.events.status(owners, {replicaId:id, status});\n this.events.log(`[${settings.projectName}] Starting synchronization for ${root}.`);\n try {\n const running = await this.start(root, {\n cookie:params.cookie,\n onSyncError:message => {\n if (!entry) { return; }\n entry.status = message ? {state:'error', message}\n : entry.running.conflicts().length ? {state:'paused'} : {state:'active'};\n this.events.status(entry.owners, {replicaId:id, status:entry.status});\n },\n log:message => this.events.log(`[${settings.projectName}] ${message}`),\n onConflict:(path, reason) => {\n if (!entry) { return; }\n entry.status = {state:'paused', message:`Conflict in ${path}`};\n this.events.conflict(entry.owners, {\n replicaId:entry.id,\n path,\n reason,\n conflicts:entry.running.conflicts(),\n });\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n },\n });\n if (!this.clients.has(clientId)) {\n await running.stop();\n this.events.empty();\n throw new Error('The replica client disconnected before attachment completed.');\n }\n entry = {\n id,\n root,\n projectKey,\n serverName:settings.serverName,\n projectId:settings.projectId,\n projectName:settings.projectName,\n owners,\n running,\n status:running.syncError() ? {state:'error', message:running.syncError()}\n : running.conflicts().length===0 ? {state:'active'} : {state:'paused'},\n };\n this.byId.set(id, entry);\n this.byRoot.set(root, entry);\n this.byProject.set(projectKey, entry);\n this.events.status(owners, {replicaId:id, status:entry.status});\n return this.result(entry, false);\n } catch (error) {\n const failed:ReplicaStatus = {state:'error', message:error instanceof Error ? error.message : String(error)};\n this.events.status(owners, {replicaId:id, status:failed});\n throw error;\n }\n }\n\n async detach(clientId:string, replicaId:string):Promise<void> {\n const entry = this.require(replicaId);\n await this.withProjectLock(entry.projectKey, async () => {\n entry.owners.delete(clientId);\n if (entry.owners.size===0) { await this.stop(entry); }\n });\n }\n\n async detachClient(clientId:string):Promise<void> {\n this.clients.delete(clientId);\n const owned = [...this.byId.values()].filter(entry => entry.owners.has(clientId));\n await Promise.all(owned.map(entry => this.withProjectLock(entry.projectKey, async () => {\n entry.owners.delete(clientId);\n if (entry.owners.size===0) { await this.stop(entry); }\n })));\n }\n\n async resolveConflict(replicaId:string, path:string, winner:'local'|'remote'):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.resolveConflict(path, winner);\n entry.status = entry.running.syncError() ? {state:'error', message:entry.running.syncError()}\n : entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n async retry(replicaId:string, path:string):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.retry(path);\n entry.status = entry.running.syncError() ? {state:'error', message:entry.running.syncError()}\n : entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n list() {\n return [...this.byId.values()].map(entry => ({\n id:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n clients:entry.owners.size,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n }));\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.byId.values()].map(entry => this.stop(entry)));\n }\n\n private addOwner(entry:ReplicaEntry, clientId:string):void {\n entry.owners.add(clientId);\n }\n\n private async stop(entry:ReplicaEntry):Promise<void> {\n if (!this.byId.delete(entry.id)) { return; }\n this.byRoot.delete(entry.root);\n this.byProject.delete(entry.projectKey);\n entry.status = {state:'stopping'};\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n await entry.running.stop();\n this.events.empty();\n }\n\n private require(replicaId:string):ReplicaEntry {\n const entry = this.byId.get(replicaId);\n if (!entry) { throw new Error(`Unknown replica ${replicaId}.`); }\n return entry;\n }\n\n private result(entry:ReplicaEntry, shared:boolean):ReplicaAttachResult {\n return {\n replicaId:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n shared,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n };\n }\n\n private async withProjectLock<T>(projectKey:string, operation:() => Promise<T>):Promise<T> {\n const previous = this.projectOperations.get(projectKey) ?? Promise.resolve();\n let release!:() => void;\n const current = new Promise<void>(resolveOperation => { release = resolveOperation; });\n this.projectOperations.set(projectKey, current);\n await previous;\n try {\n return await operation();\n } finally {\n release();\n if (this.projectOperations.get(projectKey)===current) { this.projectOperations.delete(projectKey); }\n }\n }\n}\n","import type {Socket} from 'node:net';\nimport {\n createMessageConnection,\n SocketMessageReader,\n SocketMessageWriter,\n type Message,\n type MessageConnection,\n} from 'vscode-jsonrpc/node';\n\nconst CLOSED_SOCKET_ERRORS = new Set([\n 'EPIPE',\n 'ECONNRESET',\n 'ERR_SOCKET_CLOSED',\n 'ERR_STREAM_DESTROYED',\n 'ERR_STREAM_WRITE_AFTER_END',\n]);\n\nclass LeafRelaySocketWriter extends SocketMessageWriter {\n constructor(private readonly transportSocket:Socket) {\n super(transportSocket);\n }\n\n override async write(message:Message):Promise<void> {\n try {\n await super.write(message);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (this.transportSocket.destroyed || this.transportSocket.writableEnded || (code && CLOSED_SOCKET_ERRORS.has(code))) { return; }\n throw error;\n }\n }\n}\n\nexport function createSocketRpcConnection(socket:Socket):MessageConnection {\n return createMessageConnection(new SocketMessageReader(socket), new LeafRelaySocketWriter(socket));\n}\n","import {LeafRelayDaemonServer} from './server';\n\nconst server = new LeafRelayDaemonServer();\n\nconst stop = () => {\n process.off('SIGINT', stop);\n process.off('SIGTERM', stop);\n void server.stop().finally(() => process.exit(0));\n};\n\nprocess.on('SIGINT', stop);\nprocess.on('SIGTERM', stop);\nprocess.on('uncaughtException', error => {\n console.error(error);\n void server.stop().finally(() => process.exit(1));\n});\nprocess.on('unhandledRejection', error => {\n console.error(error);\n void server.stop().finally(() => process.exit(1));\n});\n\nvoid server.start().catch(error => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":"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","names":["randomUUID","server","method","resolve","resolve","randomUUID"]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leafrelay",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Reliable two-way synchronization between Overleaf and a local directory.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"overleaf",
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
"vscode-jsonrpc": "9.0.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@leafrelay/
|
|
63
|
-
"@leafrelay/
|
|
64
|
-
"@leafrelay/
|
|
62
|
+
"@leafrelay/core": "0.2.7",
|
|
63
|
+
"@leafrelay/protocol": "0.1.7",
|
|
64
|
+
"@leafrelay/daemon": "0.1.7"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "tsup",
|