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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../daemon/dist/chunk-
|
|
1
|
+
// ../daemon/dist/chunk-QRLVFB6A.js
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { join, resolve } from "path";
|
|
@@ -4600,6 +4600,9 @@ function write(level, args) {
|
|
|
4600
4600
|
function log(...args) {
|
|
4601
4601
|
write("info", args);
|
|
4602
4602
|
}
|
|
4603
|
+
function error(...args) {
|
|
4604
|
+
write("error", args);
|
|
4605
|
+
}
|
|
4603
4606
|
function retryAfterMilliseconds(response, now) {
|
|
4604
4607
|
const retryAfter = response.headers.get("retry-after");
|
|
4605
4608
|
if (retryAfter) {
|
|
@@ -4633,7 +4636,7 @@ var HttpRequestScheduler = class {
|
|
|
4633
4636
|
fetchImplementation;
|
|
4634
4637
|
now;
|
|
4635
4638
|
wait;
|
|
4636
|
-
fetch(input, init) {
|
|
4639
|
+
fetch(input, init, timeoutMs = this.options.requestTimeoutMs ?? 6e4) {
|
|
4637
4640
|
const url = input instanceof Request ? input.url : String(input);
|
|
4638
4641
|
const history = url.includes("/updates?") || url.includes("/filetree/diff?") || url.includes("/diff?");
|
|
4639
4642
|
return this.enqueue(async () => {
|
|
@@ -4647,7 +4650,20 @@ var HttpRequestScheduler = class {
|
|
|
4647
4650
|
if (history) {
|
|
4648
4651
|
this.historyNextRequestAt = requestAt + this.historyIntervalMs;
|
|
4649
4652
|
}
|
|
4650
|
-
const
|
|
4653
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
4654
|
+
const signals = [timeout, init?.signal, input instanceof Request ? input.signal : void 0].filter((signal) => Boolean(signal));
|
|
4655
|
+
let response;
|
|
4656
|
+
try {
|
|
4657
|
+
response = await this.fetchImplementation(input, { ...init, signal: AbortSignal.any(signals) });
|
|
4658
|
+
} catch (error2) {
|
|
4659
|
+
const destination = new URL(url);
|
|
4660
|
+
error("HTTP request failed", {
|
|
4661
|
+
method: init?.method ?? (input instanceof Request ? input.method : "GET"),
|
|
4662
|
+
url: `${destination.origin}${destination.pathname}`,
|
|
4663
|
+
error: error2
|
|
4664
|
+
});
|
|
4665
|
+
throw error2;
|
|
4666
|
+
}
|
|
4651
4667
|
if (response.status === 429) {
|
|
4652
4668
|
this.rateLimitedUntil = Math.max(
|
|
4653
4669
|
this.rateLimitedUntil,
|
|
@@ -4746,6 +4762,8 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4746
4762
|
connected = false;
|
|
4747
4763
|
closing = false;
|
|
4748
4764
|
reconnecting;
|
|
4765
|
+
reconnectTimer;
|
|
4766
|
+
cancelReconnectWait;
|
|
4749
4767
|
connectionClosed = Promise.resolve();
|
|
4750
4768
|
initializeState;
|
|
4751
4769
|
paths;
|
|
@@ -4759,7 +4777,15 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4759
4777
|
clientId;
|
|
4760
4778
|
static async connect(options) {
|
|
4761
4779
|
const client = new _LeafRelayDaemonClient(options);
|
|
4762
|
-
|
|
4780
|
+
client.reconnecting = client.connectTransport();
|
|
4781
|
+
try {
|
|
4782
|
+
await client.reconnecting;
|
|
4783
|
+
} catch (error2) {
|
|
4784
|
+
client.close();
|
|
4785
|
+
throw error2;
|
|
4786
|
+
} finally {
|
|
4787
|
+
client.reconnecting = void 0;
|
|
4788
|
+
}
|
|
4763
4789
|
return client;
|
|
4764
4790
|
}
|
|
4765
4791
|
get initializeResult() {
|
|
@@ -4769,16 +4795,42 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4769
4795
|
return this.request(RPC_METHOD.daemonStatus);
|
|
4770
4796
|
}
|
|
4771
4797
|
async attachReplica(params) {
|
|
4772
|
-
const
|
|
4773
|
-
|
|
4774
|
-
|
|
4798
|
+
const replicaId = randomUUID();
|
|
4799
|
+
const registration = { params };
|
|
4800
|
+
this.replicas.set(replicaId, registration);
|
|
4801
|
+
try {
|
|
4802
|
+
if (!this.connected) {
|
|
4803
|
+
await this.ensureReconnected();
|
|
4804
|
+
}
|
|
4805
|
+
if (!registration.result) {
|
|
4806
|
+
const rpc = this.rpc;
|
|
4807
|
+
try {
|
|
4808
|
+
await this.registerReplica(replicaId, registration);
|
|
4809
|
+
} catch (error2) {
|
|
4810
|
+
if (this.closing || this.rpc === rpc && this.connected) {
|
|
4811
|
+
throw error2;
|
|
4812
|
+
}
|
|
4813
|
+
await this.ensureReconnected();
|
|
4814
|
+
}
|
|
4815
|
+
}
|
|
4816
|
+
return registration.result;
|
|
4817
|
+
} catch (error2) {
|
|
4818
|
+
this.replicas.delete(replicaId);
|
|
4819
|
+
throw error2;
|
|
4820
|
+
}
|
|
4775
4821
|
}
|
|
4776
4822
|
async detachReplica(replicaId) {
|
|
4823
|
+
if (!this.connected) {
|
|
4824
|
+
await this.ensureReconnected();
|
|
4825
|
+
}
|
|
4777
4826
|
const registration = this.replicas.get(replicaId);
|
|
4778
|
-
await this.request(RPC_METHOD.replicaDetach, { replicaId: registration?.currentId ?? replicaId });
|
|
4779
4827
|
this.replicas.delete(replicaId);
|
|
4828
|
+
await this.request(RPC_METHOD.replicaDetach, { replicaId: registration?.currentId ?? replicaId });
|
|
4780
4829
|
}
|
|
4781
4830
|
async resolveConflict(params) {
|
|
4831
|
+
if (!this.connected) {
|
|
4832
|
+
await this.ensureReconnected();
|
|
4833
|
+
}
|
|
4782
4834
|
const registration = this.replicas.get(params.replicaId);
|
|
4783
4835
|
await this.request(RPC_METHOD.replicaResolveConflict, {
|
|
4784
4836
|
...params,
|
|
@@ -4786,6 +4838,9 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4786
4838
|
});
|
|
4787
4839
|
}
|
|
4788
4840
|
async retry(replicaId, path2) {
|
|
4841
|
+
if (!this.connected) {
|
|
4842
|
+
await this.ensureReconnected();
|
|
4843
|
+
}
|
|
4789
4844
|
const registration = this.replicas.get(replicaId);
|
|
4790
4845
|
await this.request(RPC_METHOD.replicaRetry, { replicaId: registration?.currentId ?? replicaId, path: path2 });
|
|
4791
4846
|
}
|
|
@@ -4821,9 +4876,32 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4821
4876
|
return decodeRpcValue(result);
|
|
4822
4877
|
}
|
|
4823
4878
|
async openProject(server, projectId) {
|
|
4824
|
-
const
|
|
4825
|
-
|
|
4826
|
-
|
|
4879
|
+
const host = new URL(server.includes("://") ? server : `https://${server}`).host;
|
|
4880
|
+
const projectKey = `${host}:${projectId}`;
|
|
4881
|
+
const registration = { server, projectId, currentKey: projectKey };
|
|
4882
|
+
this.projects.set(projectKey, registration);
|
|
4883
|
+
try {
|
|
4884
|
+
if (!this.connected) {
|
|
4885
|
+
await this.ensureReconnected();
|
|
4886
|
+
}
|
|
4887
|
+
if (!registration.result) {
|
|
4888
|
+
const rpc = this.rpc;
|
|
4889
|
+
try {
|
|
4890
|
+
await this.registerProject(registration);
|
|
4891
|
+
} catch (error2) {
|
|
4892
|
+
if (this.closing || this.rpc === rpc && this.connected) {
|
|
4893
|
+
throw error2;
|
|
4894
|
+
}
|
|
4895
|
+
await this.ensureReconnected();
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
return registration.result;
|
|
4899
|
+
} catch (error2) {
|
|
4900
|
+
if (this.projects.get(projectKey) === registration) {
|
|
4901
|
+
this.projects.delete(projectKey);
|
|
4902
|
+
}
|
|
4903
|
+
throw error2;
|
|
4904
|
+
}
|
|
4827
4905
|
}
|
|
4828
4906
|
async closeProject(projectKey) {
|
|
4829
4907
|
const registration = this.projects.get(projectKey);
|
|
@@ -4848,6 +4926,10 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4848
4926
|
}
|
|
4849
4927
|
close() {
|
|
4850
4928
|
this.closing = true;
|
|
4929
|
+
if (this.reconnectTimer) {
|
|
4930
|
+
clearTimeout(this.reconnectTimer);
|
|
4931
|
+
}
|
|
4932
|
+
this.cancelReconnectWait?.();
|
|
4851
4933
|
this.connected = false;
|
|
4852
4934
|
this.rpc?.dispose();
|
|
4853
4935
|
this.socket?.destroy();
|
|
@@ -4858,15 +4940,7 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4858
4940
|
if (!this.connected) {
|
|
4859
4941
|
await this.ensureReconnected();
|
|
4860
4942
|
}
|
|
4861
|
-
|
|
4862
|
-
return await this.rawRequest(method, params);
|
|
4863
|
-
} catch (requestError) {
|
|
4864
|
-
if (this.connected || this.closing) {
|
|
4865
|
-
throw requestError;
|
|
4866
|
-
}
|
|
4867
|
-
await this.ensureReconnected();
|
|
4868
|
-
return this.rawRequest(method, params);
|
|
4869
|
-
}
|
|
4943
|
+
return this.rawRequest(method, params);
|
|
4870
4944
|
}
|
|
4871
4945
|
rawRequest(method, params) {
|
|
4872
4946
|
if (!this.rpc) {
|
|
@@ -4882,11 +4956,38 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4882
4956
|
if (this.closing) {
|
|
4883
4957
|
throw new Error("LeafRelay daemon client is closed.");
|
|
4884
4958
|
}
|
|
4885
|
-
this.reconnecting ??= this.
|
|
4959
|
+
this.reconnecting ??= this.reconnectTransport().finally(() => {
|
|
4886
4960
|
this.reconnecting = void 0;
|
|
4887
4961
|
});
|
|
4888
4962
|
return this.reconnecting;
|
|
4889
4963
|
}
|
|
4964
|
+
async reconnectTransport() {
|
|
4965
|
+
let attempt = 0;
|
|
4966
|
+
while (!this.closing) {
|
|
4967
|
+
try {
|
|
4968
|
+
await this.connectTransport();
|
|
4969
|
+
return;
|
|
4970
|
+
} catch (error2) {
|
|
4971
|
+
const code = error2.code;
|
|
4972
|
+
if (code === -32001 || code === -32002 || this.closing) {
|
|
4973
|
+
throw error2;
|
|
4974
|
+
}
|
|
4975
|
+
const delay = Math.min(1e3 * 2 ** attempt++, 16e3);
|
|
4976
|
+
dispatch(this.logListeners, {
|
|
4977
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4978
|
+
level: "warn",
|
|
4979
|
+
message: `Daemon reconnection failed; retrying in ${delay}ms: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
4980
|
+
});
|
|
4981
|
+
await new Promise((resolveWait) => {
|
|
4982
|
+
this.cancelReconnectWait = resolveWait;
|
|
4983
|
+
this.reconnectTimer = setTimeout(resolveWait, delay);
|
|
4984
|
+
});
|
|
4985
|
+
this.cancelReconnectWait = void 0;
|
|
4986
|
+
this.reconnectTimer = void 0;
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
throw new Error("LeafRelay daemon client is closed.");
|
|
4990
|
+
}
|
|
4890
4991
|
async connectTransport() {
|
|
4891
4992
|
const metadata = await this.findOrStartDaemon();
|
|
4892
4993
|
const socket = await tryConnect(metadata);
|
|
@@ -4909,8 +5010,19 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4909
5010
|
this.connected = false;
|
|
4910
5011
|
this.rpc = void 0;
|
|
4911
5012
|
this.socket = void 0;
|
|
5013
|
+
for (const registration of this.replicas.values()) {
|
|
5014
|
+
registration.currentId = void 0;
|
|
5015
|
+
registration.result = void 0;
|
|
5016
|
+
}
|
|
5017
|
+
for (const registration of this.projects.values()) {
|
|
5018
|
+
registration.result = void 0;
|
|
5019
|
+
}
|
|
4912
5020
|
if (!this.closing) {
|
|
4913
|
-
void this.ensureReconnected()
|
|
5021
|
+
void this.ensureReconnected().catch((error2) => dispatch(this.logListeners, {
|
|
5022
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5023
|
+
level: "error",
|
|
5024
|
+
message: `Daemon reconnection failed: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
5025
|
+
}));
|
|
4914
5026
|
}
|
|
4915
5027
|
});
|
|
4916
5028
|
rpc.listen();
|
|
@@ -4922,9 +5034,10 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4922
5034
|
clientVersion: this.options.clientVersion,
|
|
4923
5035
|
protocolVersion: LEAFRELAY_PROTOCOL_VERSION
|
|
4924
5036
|
});
|
|
5037
|
+
await this.restoreRegistrations();
|
|
4925
5038
|
this.connected = true;
|
|
4926
|
-
await this.restoreRegistrations(rpc);
|
|
4927
5039
|
} catch (connectError) {
|
|
5040
|
+
this.connected = false;
|
|
4928
5041
|
rpc.dispose();
|
|
4929
5042
|
socket.destroy();
|
|
4930
5043
|
if (this.rpc === rpc) {
|
|
@@ -4934,17 +5047,49 @@ var LeafRelayDaemonClient = class _LeafRelayDaemonClient {
|
|
|
4934
5047
|
throw connectError;
|
|
4935
5048
|
}
|
|
4936
5049
|
}
|
|
4937
|
-
async restoreRegistrations(
|
|
5050
|
+
async restoreRegistrations() {
|
|
4938
5051
|
for (const registration of this.projects.values()) {
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
5052
|
+
await this.registerProject(registration);
|
|
5053
|
+
}
|
|
5054
|
+
for (const [replicaId, registration] of this.replicas) {
|
|
5055
|
+
await this.registerReplica(replicaId, registration);
|
|
5056
|
+
}
|
|
5057
|
+
if (this.projects.size !== 0 || this.replicas.size !== 0) {
|
|
5058
|
+
dispatch(this.logListeners, {
|
|
5059
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5060
|
+
level: "info",
|
|
5061
|
+
message: `Daemon registrations restored: ${this.projects.size} project(s), ${this.replicas.size} local replica(s).`
|
|
4942
5062
|
});
|
|
4943
|
-
registration.currentKey = result.projectKey;
|
|
4944
5063
|
}
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
5064
|
+
}
|
|
5065
|
+
async registerProject(registration) {
|
|
5066
|
+
const rpc = this.rpc;
|
|
5067
|
+
const result = await this.rawRequest(RPC_METHOD.projectOpen, {
|
|
5068
|
+
server: registration.server,
|
|
5069
|
+
projectId: registration.projectId
|
|
5070
|
+
});
|
|
5071
|
+
if (this.rpc !== rpc) {
|
|
5072
|
+
throw new Error("LeafRelay daemon connection changed during project attachment.");
|
|
5073
|
+
}
|
|
5074
|
+
registration.currentKey = result.projectKey;
|
|
5075
|
+
registration.result = result;
|
|
5076
|
+
}
|
|
5077
|
+
async registerReplica(replicaId, registration) {
|
|
5078
|
+
const rpc = this.rpc;
|
|
5079
|
+
const result = await this.rawRequest(RPC_METHOD.replicaAttach, registration.params);
|
|
5080
|
+
if (this.rpc !== rpc) {
|
|
5081
|
+
throw new Error("LeafRelay daemon connection changed during replica attachment.");
|
|
5082
|
+
}
|
|
5083
|
+
registration.currentId = result.replicaId;
|
|
5084
|
+
registration.result = { ...result, replicaId };
|
|
5085
|
+
dispatch(this.statusListeners, { replicaId, status: result.status });
|
|
5086
|
+
for (const path2 of result.conflicts) {
|
|
5087
|
+
dispatch(this.conflictListeners, {
|
|
5088
|
+
replicaId,
|
|
5089
|
+
path: path2,
|
|
5090
|
+
conflicts: result.conflicts,
|
|
5091
|
+
reason: "This path has an unresolved synchronization conflict."
|
|
5092
|
+
});
|
|
4948
5093
|
}
|
|
4949
5094
|
}
|
|
4950
5095
|
registerNotifications(rpc) {
|
|
@@ -5067,7 +5212,7 @@ async function tryConnect(metadata) {
|
|
|
5067
5212
|
function connectCliDaemon(autoStart = true) {
|
|
5068
5213
|
return LeafRelayDaemonClient.connect({
|
|
5069
5214
|
clientName: "cli",
|
|
5070
|
-
clientVersion: "0.2.
|
|
5215
|
+
clientVersion: "0.2.7",
|
|
5071
5216
|
daemonEntrypoint: new URL("./daemon.js", import.meta.url),
|
|
5072
5217
|
autoStart
|
|
5073
5218
|
});
|
|
@@ -5092,9 +5237,9 @@ async function startServe(directory = process.cwd()) {
|
|
|
5092
5237
|
client.close();
|
|
5093
5238
|
}
|
|
5094
5239
|
};
|
|
5095
|
-
} catch (
|
|
5240
|
+
} catch (error2) {
|
|
5096
5241
|
client.close();
|
|
5097
|
-
throw
|
|
5242
|
+
throw error2;
|
|
5098
5243
|
}
|
|
5099
5244
|
}
|
|
5100
5245
|
async function serve(directory = process.cwd()) {
|
|
@@ -5104,8 +5249,8 @@ async function serve(directory = process.cwd()) {
|
|
|
5104
5249
|
const stop = () => {
|
|
5105
5250
|
process.off("SIGINT", stop);
|
|
5106
5251
|
process.off("SIGTERM", stop);
|
|
5107
|
-
running.stop().then(resolveStop, (
|
|
5108
|
-
console.error(
|
|
5252
|
+
running.stop().then(resolveStop, (error2) => {
|
|
5253
|
+
console.error(error2);
|
|
5109
5254
|
resolveStop();
|
|
5110
5255
|
});
|
|
5111
5256
|
};
|
|
@@ -5157,4 +5302,4 @@ export {
|
|
|
5157
5302
|
chokidar/index.js:
|
|
5158
5303
|
(*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
|
|
5159
5304
|
*/
|
|
5160
|
-
//# sourceMappingURL=chunk-
|
|
5305
|
+
//# sourceMappingURL=chunk-VXZVIMCG.js.map
|