Skip to content

Commit dd681eb

Browse files
authored
Merge pull request #18 from monteslu/feat/auto-relay-web-port
feat: auto-relay for web port (fixes #15)
2 parents e76cc36 + 06350e8 commit dd681eb

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

connection.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ export async function createHsync(config) {
6767
hsyncClient.listeners = initListeners(hsyncClient);
6868
hsyncClient.relays = initRelays(hsyncClient);
6969

70+
// Enable auto-relay for web port (issue #15)
71+
if (port) {
72+
hsyncClient.relays.setWebPort(port);
73+
}
74+
7075
const events = new EventEmitter();
7176

7277
hsyncClient.on = events.on.bind(events);

lib/socket-relays.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ export function setNet(netImpl) {
1414

1515
export function initRelays(hsyncClient) {
1616
const cachedRelays = {};
17+
let webPort = null;
18+
19+
function setWebPort(port) {
20+
webPort = port;
21+
debug('web port set for auto-relay:', port);
22+
}
1723

1824
function getSocketRelays() {
1925
const hKeys = Object.keys(cachedRelays);
@@ -45,8 +51,15 @@ export function initRelays(hsyncClient) {
4551
return `closeRelaySocket no matching socket for ${socketId}`;
4652
});
4753

48-
const relay = cachedRelays['p' + port];
54+
let relay = cachedRelays['p' + port];
4955
debug('connect relay', port, socketId, peer.hostName);
56+
57+
// Auto-create relay if port matches web port (issue #15)
58+
if (!relay && webPort && port === webPort) {
59+
debug('auto-creating relay for web port:', port);
60+
relay = addSocketRelay({ port, targetHost: 'localhost', targetPort: port });
61+
}
62+
5063
if (!relay) {
5164
throw new Error('no relay found for port: ' + port);
5265
}
@@ -112,11 +125,13 @@ export function initRelays(hsyncClient) {
112125
hsyncClient.addSocketRelay = addSocketRelay;
113126
hsyncClient.getSocketRelays = getSocketRelays;
114127
hsyncClient.connectSocket = connectSocket;
128+
hsyncClient.setWebPort = setWebPort;
115129

116130
return {
117131
// receiveListenerData,
118132
getSocketRelays,
119133
connectSocket,
120134
addSocketRelay,
135+
setWebPort,
121136
};
122137
}

test/unit/socket-relays.test.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@ describe('socket-relays', () => {
6868
expect(mockHsyncClient.addSocketRelay).toBeTypeOf('function');
6969
expect(mockHsyncClient.getSocketRelays).toBeTypeOf('function');
7070
expect(mockHsyncClient.connectSocket).toBeTypeOf('function');
71+
expect(mockHsyncClient.setWebPort).toBeTypeOf('function');
72+
});
73+
74+
it('should return setWebPort in returned object', () => {
75+
const relays = initRelays(mockHsyncClient);
76+
77+
expect(relays.setWebPort).toBeTypeOf('function');
78+
});
79+
});
80+
81+
describe('setWebPort', () => {
82+
let relays;
83+
84+
beforeEach(() => {
85+
relays = initRelays(mockHsyncClient);
86+
});
87+
88+
it('should store web port for auto-relay', () => {
89+
// setWebPort stores the port internally - no return value
90+
relays.setWebPort(3000);
91+
// No error means success
7192
});
7293
});
7394

@@ -201,6 +222,55 @@ describe('socket-relays', () => {
201222
).toThrow('no relay found for port: 9999');
202223
});
203224

225+
it('should auto-create relay for web port (issue #15)', async () => {
226+
// Set web port without explicit relay
227+
relays.setWebPort(3000);
228+
229+
// Should NOT throw - should auto-create relay for web port
230+
const result = await relays.connectSocket(mockPeer, {
231+
port: 3000,
232+
socketId: 'auto-relay-socket',
233+
hostName: 'remote.example.com',
234+
});
235+
236+
expect(result.socketId).toBe('auto-relay-socket');
237+
expect(result.targetHost).toBe('localhost');
238+
expect(result.targetPort).toBe(3000);
239+
expect(mockSocket.connect).toHaveBeenCalledWith(3000, 'localhost', expect.any(Function));
240+
});
241+
242+
it('should still throw for non-web ports when web port is set', () => {
243+
relays.setWebPort(3000);
244+
245+
// Different port should still throw
246+
expect(() =>
247+
relays.connectSocket(mockPeer, {
248+
port: 9999,
249+
socketId: 'test-socket',
250+
hostName: 'remote.example.com',
251+
})
252+
).toThrow('no relay found for port: 9999');
253+
});
254+
255+
it('should prefer explicit relay over auto-relay', async () => {
256+
relays.setWebPort(3000);
257+
relays.addSocketRelay({
258+
port: 3000,
259+
targetPort: 4000,
260+
targetHost: 'custom-host.local',
261+
});
262+
263+
const result = await relays.connectSocket(mockPeer, {
264+
port: 3000,
265+
socketId: 'explicit-relay-socket',
266+
hostName: 'remote.example.com',
267+
});
268+
269+
// Should use explicit relay config, not auto-relay
270+
expect(result.targetHost).toBe('custom-host.local');
271+
expect(result.targetPort).toBe(4000);
272+
});
273+
204274
it('should create socket and connect to relay target', async () => {
205275
relays.addSocketRelay({
206276
port: 3000,

0 commit comments

Comments
 (0)