@dev-anywhere/relay 0.4.79 → 0.4.81
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-L2KEGMDB.js → chunk-XJZ3HOPH.js} +144 -24
- package/dist/chunk-XJZ3HOPH.js.map +1 -0
- package/dist/handlers/client.d.ts.map +1 -1
- package/dist/handlers/proxy.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/remote-file-bridge.d.ts +17 -4
- package/dist/remote-file-bridge.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-L2KEGMDB.js.map +0 -1
|
@@ -617,6 +617,21 @@ var relayControlDefinitions = [
|
|
|
617
617
|
url: z8.string().optional(),
|
|
618
618
|
expiresAt: z8.number().int().nonnegative().optional()
|
|
619
619
|
}),
|
|
620
|
+
control("remote_file_metadata_request", {
|
|
621
|
+
...RequiredRequestIdShape,
|
|
622
|
+
sessionId: IdSchema,
|
|
623
|
+
path: z8.string().min(1)
|
|
624
|
+
}),
|
|
625
|
+
control("remote_file_metadata_response", {
|
|
626
|
+
...RequiredRequestIdShape,
|
|
627
|
+
...RequestErrorShape,
|
|
628
|
+
sessionId: IdSchema,
|
|
629
|
+
path: z8.string().optional(),
|
|
630
|
+
success: z8.boolean(),
|
|
631
|
+
mimeType: z8.string().optional(),
|
|
632
|
+
size: z8.number().int().nonnegative().optional(),
|
|
633
|
+
fileName: z8.string().optional()
|
|
634
|
+
}),
|
|
620
635
|
control("remote_file_stream_request", {
|
|
621
636
|
streamId: IdSchema,
|
|
622
637
|
sessionId: IdSchema,
|
|
@@ -1768,6 +1783,10 @@ function handleProxyConnection(ws, registry, logger, chaos, remoteFileBridge) {
|
|
|
1768
1783
|
remoteFileBridge?.handleProxyControl(proxyWs.proxyId, result.message);
|
|
1769
1784
|
return;
|
|
1770
1785
|
}
|
|
1786
|
+
if (proxyWs.proxyId && result.message.type === "remote_file_metadata_response") {
|
|
1787
|
+
remoteFileBridge?.handleProxyControl(proxyWs.proxyId, result.message);
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1771
1790
|
if (proxyWs.proxyId && result.message.type === "remote_file_stream_complete") {
|
|
1772
1791
|
remoteFileBridge?.handleProxyControl(proxyWs.proxyId, result.message);
|
|
1773
1792
|
return;
|
|
@@ -2773,24 +2792,44 @@ function handleClientConnection(ws, registry, logger, chaos, voiceConfigStore, v
|
|
|
2773
2792
|
);
|
|
2774
2793
|
return;
|
|
2775
2794
|
}
|
|
2776
|
-
|
|
2795
|
+
void remoteFileBridge.createUrl({
|
|
2777
2796
|
clientId: clientWs.clientId,
|
|
2778
2797
|
proxyId: targetProxyId,
|
|
2779
2798
|
sessionId: msg.sessionId,
|
|
2780
2799
|
path: msg.path,
|
|
2781
2800
|
disposition: msg.disposition
|
|
2801
|
+
}).then((result2) => {
|
|
2802
|
+
if (clientWs.readyState !== WebSocket7.OPEN) return;
|
|
2803
|
+
if (!result2.success) {
|
|
2804
|
+
sendRemoteFileUrlFailure(
|
|
2805
|
+
clientWs,
|
|
2806
|
+
msg.requestId,
|
|
2807
|
+
msg.sessionId,
|
|
2808
|
+
result2.error,
|
|
2809
|
+
result2.errorCode
|
|
2810
|
+
);
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
clientWs.send(
|
|
2814
|
+
serializeControl({
|
|
2815
|
+
type: "remote_file_url_response",
|
|
2816
|
+
requestId: msg.requestId,
|
|
2817
|
+
sessionId: msg.sessionId,
|
|
2818
|
+
path: result2.path,
|
|
2819
|
+
success: true,
|
|
2820
|
+
url: result2.url,
|
|
2821
|
+
expiresAt: result2.expiresAt
|
|
2822
|
+
})
|
|
2823
|
+
);
|
|
2824
|
+
}).catch((err) => {
|
|
2825
|
+
if (clientWs.readyState !== WebSocket7.OPEN) return;
|
|
2826
|
+
sendRemoteFileUrlFailure(
|
|
2827
|
+
clientWs,
|
|
2828
|
+
msg.requestId,
|
|
2829
|
+
msg.sessionId,
|
|
2830
|
+
err instanceof Error ? err.message : String(err)
|
|
2831
|
+
);
|
|
2782
2832
|
});
|
|
2783
|
-
clientWs.send(
|
|
2784
|
-
serializeControl({
|
|
2785
|
-
type: "remote_file_url_response",
|
|
2786
|
-
requestId: msg.requestId,
|
|
2787
|
-
sessionId: msg.sessionId,
|
|
2788
|
-
path: msg.path,
|
|
2789
|
-
success: true,
|
|
2790
|
-
url,
|
|
2791
|
-
expiresAt
|
|
2792
|
-
})
|
|
2793
|
-
);
|
|
2794
2833
|
return;
|
|
2795
2834
|
}
|
|
2796
2835
|
if (msg.type === "remote_file_upload_url_request") {
|
|
@@ -3578,8 +3617,10 @@ function encodeContentDisposition(disposition, fileName) {
|
|
|
3578
3617
|
function statusForErrorCode(errorCode) {
|
|
3579
3618
|
switch (errorCode) {
|
|
3580
3619
|
case ControlErrorCode.SESSION_NOT_FOUND:
|
|
3620
|
+
case ControlErrorCode.PATH_NOT_FOUND:
|
|
3581
3621
|
return 404;
|
|
3582
3622
|
case ControlErrorCode.INVALID_PATH:
|
|
3623
|
+
case ControlErrorCode.PATH_NOT_DIRECTORY:
|
|
3583
3624
|
return 400;
|
|
3584
3625
|
case ControlErrorCode.PATH_ACCESS_DENIED:
|
|
3585
3626
|
return 403;
|
|
@@ -3594,22 +3635,54 @@ var RemoteFileBridge = class {
|
|
|
3594
3635
|
deps;
|
|
3595
3636
|
tokens = /* @__PURE__ */ new Map();
|
|
3596
3637
|
uploadTokens = /* @__PURE__ */ new Map();
|
|
3638
|
+
pendingUrlMetadata = /* @__PURE__ */ new Map();
|
|
3597
3639
|
pendingStreams = /* @__PURE__ */ new Map();
|
|
3598
3640
|
pendingUploads = /* @__PURE__ */ new Map();
|
|
3599
3641
|
createUrl(input) {
|
|
3600
3642
|
this.cleanupExpiredTokens();
|
|
3601
|
-
const
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3643
|
+
const proxyWs = this.deps.registry.getProxy(input.proxyId);
|
|
3644
|
+
if (!proxyWs || proxyWs.readyState !== WebSocket11.OPEN) {
|
|
3645
|
+
return Promise.resolve({
|
|
3646
|
+
success: false,
|
|
3647
|
+
path: input.path,
|
|
3648
|
+
error: "\u5F53\u524D\u672A\u8FDE\u63A5\u5F00\u53D1\u673A",
|
|
3649
|
+
errorCode: ControlErrorCode.PROXY_OFFLINE
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3652
|
+
const requestId = nanoid3(21);
|
|
3653
|
+
return new Promise((resolve2) => {
|
|
3654
|
+
const timer = setTimeout(() => {
|
|
3655
|
+
this.pendingUrlMetadata.delete(requestId);
|
|
3656
|
+
resolve2({
|
|
3657
|
+
success: false,
|
|
3658
|
+
path: input.path,
|
|
3659
|
+
error: "\u8BFB\u53D6\u6587\u4EF6\u5143\u6570\u636E\u8D85\u65F6",
|
|
3660
|
+
errorCode: ControlErrorCode.UNKNOWN
|
|
3661
|
+
});
|
|
3662
|
+
}, REMOTE_FILE_METADATA_TIMEOUT_MS);
|
|
3663
|
+
this.pendingUrlMetadata.set(requestId, {
|
|
3664
|
+
requestId,
|
|
3665
|
+
clientId: input.clientId,
|
|
3666
|
+
proxyId: input.proxyId,
|
|
3667
|
+
sessionId: input.sessionId,
|
|
3668
|
+
path: input.path,
|
|
3669
|
+
disposition: input.disposition,
|
|
3670
|
+
timer,
|
|
3671
|
+
resolve: resolve2
|
|
3672
|
+
});
|
|
3673
|
+
proxyWs.send(
|
|
3674
|
+
serializeControl({
|
|
3675
|
+
type: "remote_file_metadata_request",
|
|
3676
|
+
requestId,
|
|
3677
|
+
sessionId: input.sessionId,
|
|
3678
|
+
path: input.path
|
|
3679
|
+
})
|
|
3680
|
+
);
|
|
3681
|
+
this.deps.logger.info(
|
|
3682
|
+
{ requestId, proxyId: input.proxyId, sessionId: input.sessionId, path: input.path },
|
|
3683
|
+
"Remote file URL metadata requested"
|
|
3684
|
+
);
|
|
3611
3685
|
});
|
|
3612
|
-
return { url: `/api/remote-files/${token}`, expiresAt };
|
|
3613
3686
|
}
|
|
3614
3687
|
createUploadUrl(input) {
|
|
3615
3688
|
this.cleanupExpiredTokens();
|
|
@@ -3748,6 +3821,9 @@ var RemoteFileBridge = class {
|
|
|
3748
3821
|
if (msg.type === "remote_file_upload_stream_response") {
|
|
3749
3822
|
return this.handleUploadResponse(proxyId, msg);
|
|
3750
3823
|
}
|
|
3824
|
+
if (msg.type === "remote_file_metadata_response") {
|
|
3825
|
+
return this.handleUrlMetadataResponse(proxyId, msg);
|
|
3826
|
+
}
|
|
3751
3827
|
const pending = this.pendingStreams.get(msg.streamId);
|
|
3752
3828
|
if (!pending) return true;
|
|
3753
3829
|
if (pending.token.proxyId !== proxyId) {
|
|
@@ -3764,6 +3840,50 @@ var RemoteFileBridge = class {
|
|
|
3764
3840
|
this.handleStreamComplete(pending, msg);
|
|
3765
3841
|
return true;
|
|
3766
3842
|
}
|
|
3843
|
+
issueUrlToken(input) {
|
|
3844
|
+
const token = nanoid3(32);
|
|
3845
|
+
const expiresAt = Date.now() + REMOTE_FILE_TOKEN_TTL_MS;
|
|
3846
|
+
this.tokens.set(token, {
|
|
3847
|
+
token,
|
|
3848
|
+
clientId: input.clientId,
|
|
3849
|
+
proxyId: input.proxyId,
|
|
3850
|
+
sessionId: input.sessionId,
|
|
3851
|
+
path: input.path,
|
|
3852
|
+
disposition: input.disposition,
|
|
3853
|
+
expiresAt
|
|
3854
|
+
});
|
|
3855
|
+
return { url: `/api/remote-files/${token}`, expiresAt };
|
|
3856
|
+
}
|
|
3857
|
+
handleUrlMetadataResponse(proxyId, msg) {
|
|
3858
|
+
const pending = this.pendingUrlMetadata.get(msg.requestId);
|
|
3859
|
+
if (!pending) return true;
|
|
3860
|
+
if (pending.proxyId !== proxyId) {
|
|
3861
|
+
this.deps.logger.warn(
|
|
3862
|
+
{ requestId: msg.requestId, expectedProxyId: pending.proxyId, proxyId },
|
|
3863
|
+
"Remote file metadata ignored: proxy mismatch"
|
|
3864
|
+
);
|
|
3865
|
+
return true;
|
|
3866
|
+
}
|
|
3867
|
+
this.pendingUrlMetadata.delete(msg.requestId);
|
|
3868
|
+
clearTimeout(pending.timer);
|
|
3869
|
+
if (!msg.success) {
|
|
3870
|
+
pending.resolve({
|
|
3871
|
+
success: false,
|
|
3872
|
+
path: pending.path,
|
|
3873
|
+
error: msg.error ?? "\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25",
|
|
3874
|
+
...msg.errorCode ? { errorCode: msg.errorCode } : {}
|
|
3875
|
+
});
|
|
3876
|
+
return true;
|
|
3877
|
+
}
|
|
3878
|
+
const { url, expiresAt } = this.issueUrlToken(pending);
|
|
3879
|
+
pending.resolve({
|
|
3880
|
+
success: true,
|
|
3881
|
+
path: pending.path,
|
|
3882
|
+
url,
|
|
3883
|
+
expiresAt
|
|
3884
|
+
});
|
|
3885
|
+
return true;
|
|
3886
|
+
}
|
|
3767
3887
|
handleProxyBinary(proxyId, data) {
|
|
3768
3888
|
const decoded = decodeFileStreamFrame(data);
|
|
3769
3889
|
if (!decoded) return false;
|
|
@@ -4153,4 +4273,4 @@ export {
|
|
|
4153
4273
|
parseRelayChaosFromEnv,
|
|
4154
4274
|
createRelayServer
|
|
4155
4275
|
};
|
|
4156
|
-
//# sourceMappingURL=chunk-
|
|
4276
|
+
//# sourceMappingURL=chunk-XJZ3HOPH.js.map
|