'use strict'; const http=require('http'); const assert=require('assert/strict'); const {createRealtimeHub}=require('../realtime-server'); const {connectRealtime}=require('./helpers/realtime-client'); (async()=>{ const server=http.createServer((_req,res)=>{res.writeHead(404);res.end()}); const identities=new Map([ ['alice',{playerId:'alice',token:'a',name:'Alice'}], ['bob',{playerId:'bob',token:'b',name:'Bob'}] ]); const hub=createRealtimeHub({ server,claimTtlMs:120, authenticate:async({playerId,token})=>{const identity=identities.get(playerId);if(!identity||identity.token!==token)throw new Error('bad auth');return identity}, getBoardInfo:async boardId=>boardId==='B0'?{solved:false,bounds:{minX:0,minY:0,maxX:1,maxY:1}}:null }); await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve)); const base=`http://127.0.0.1:${server.address().port}`; let alice=null,bob=null; try{ alice=await connectRealtime(base,{playerId:'alice',token:'a'});bob=await connectRealtime(base,{playerId:'bob',token:'b'}); alice.send({type:'viewport',minX:-2,minY:-2,maxX:2,maxY:2});bob.send({type:'viewport',minX:-2,minY:-2,maxX:2,maxY:2});await alice.waitFor('snapshot');await bob.waitFor('snapshot'); alice.send({type:'claim',requestId:'lease-a',boardId:'B0'});assert.equal((await alice.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-a')).ok,true);await bob.waitFor(message=>message.type==='claim'&&message.claim?.boardId==='B0'); alice.close();alice=null; await bob.waitFor(message=>message.type==='claim-release'&&message.boardId==='B0'&&message.reason==='disconnected'); bob.send({type:'claim',requestId:'lease-b-after-disconnect',boardId:'B0'});const transferred=await bob.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-b-after-disconnect');assert.equal(transferred.ok,true); await new Promise(resolve=>setTimeout(resolve,170));bob.send({type:'snapshot-request'});await bob.waitFor(message=>message.type==='claim-release'&&message.boardId==='B0'&&message.reason==='expired'); bob.send({type:'claim',requestId:'lease-b-late',boardId:'B0'});const late=await bob.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-b-late');assert.equal(late.ok,true); console.log('Realtime lease expiry and disconnect release semantics passed'); }finally{ alice?.close();bob?.close();hub.close();await new Promise(resolve=>server.close(resolve)); } })().catch(error=>{console.error(error);process.exitCode=1});