@signe/room 2.4.0 → 2.4.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signe/room",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "keywords": [],
@@ -17,7 +17,7 @@
17
17
  "dset": "^3.1.3",
18
18
  "partysocket": "^1.0.1",
19
19
  "zod": "^3.23.8",
20
- "@signe/sync": "2.4.0"
20
+ "@signe/sync": "2.4.2"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "public"
package/src/mock.ts CHANGED
@@ -47,29 +47,62 @@ export class MockPartyClient {
47
47
  }
48
48
 
49
49
  class MockLobby {
50
- constructor(public server: Server) {}
50
+ constructor(public server: Server, public lobbyId: string) {}
51
51
 
52
- socket() {
52
+ socket(_init?: any) {
53
53
  return new MockPartyClient(this.server)
54
54
  }
55
55
 
56
+ async connection(idOrOptions?: string | { id?: string, query?: Record<string, string>, headers?: Record<string, string> }, maybeOptions?: { query?: Record<string, string>, headers?: Record<string, string> }) {
57
+ const id = typeof idOrOptions === 'string' ? idOrOptions : idOrOptions?.id;
58
+ const options = (typeof idOrOptions === 'string' ? maybeOptions : idOrOptions) || {};
59
+ return (this.server.room as any).connection(this.server, id, options as any);
60
+ }
61
+
56
62
  fetch(url: string, options: any) {
57
- return request(this.server, url, options)
63
+ const baseUrl = url.includes('shard') ? '' :( '/parties/main/' + this.lobbyId )
64
+ return request(this.server, baseUrl + url, options)
58
65
  }
59
66
  }
60
67
 
68
+ interface MockContextOptions {
69
+ parties?: any;
70
+ partyFn?: (room: MockPartyRoom) => any;
71
+ }
72
+
61
73
  class MockContext {
62
74
  parties: {
63
- main: Map<string, any>
75
+ main: any
64
76
  } = {
65
77
  main: new Map()
66
78
  }
67
79
 
68
- constructor(public room: MockPartyRoom, options: any = {}) {
69
- const parties = options.parties || {}
70
- for (let lobbyId in parties) {
71
- this.parties.main.set(lobbyId, new MockLobby(parties[lobbyId](room)))
72
- }
80
+ constructor(public room: MockPartyRoom, options: MockContextOptions = {}) {
81
+ const parties = options.parties || {}
82
+ if (options.partyFn) {
83
+ const serverCache = new Map<string, Server>();
84
+ this.parties.main = {
85
+ get: async (lobbyId: string) => {
86
+ if (!serverCache.has(lobbyId)) {
87
+ // Create an isolated IO for the specified lobby without recursive parties
88
+ const io = new MockPartyRoom(lobbyId, { env: this.room.env });
89
+ const server = options.partyFn(io);
90
+ if (typeof server.onStart === 'function') {
91
+ await server.onStart();
92
+ }
93
+ serverCache.set(lobbyId, server);
94
+ }
95
+ const server = serverCache.get(lobbyId)!;
96
+ return new MockLobby(server, lobbyId)
97
+ }
98
+ }
99
+ }
100
+ else {
101
+ for (let lobbyId in parties) {
102
+ const server = parties[lobbyId](room)
103
+ ;(this.parties.main as Map<string, any>).set(lobbyId, new MockLobby(server, lobbyId))
104
+ }
105
+ }
73
106
  }
74
107
  }
75
108
 
@@ -82,18 +115,25 @@ class MockPartyRoom {
82
115
  constructor(public id?: string, options: any = {}) {
83
116
  this.id = id || generateShortUUID()
84
117
  this.context = new MockContext(this, {
85
- parties: options.parties || {}
118
+ parties: options.parties,
119
+ partyFn: options.partyFn
86
120
  })
87
121
  this.env = options.env || {}
88
122
  }
89
123
 
90
- async connection(server: Server, id?: string) {
124
+ async connection(server: Server, id?: string, opts?: { query?: Record<string, string>, headers?: Record<string, string> }) {
91
125
  const socket = new MockPartyClient(server, id);
92
126
  const url = new URL('http://localhost')
127
+ if (opts?.query) {
128
+ for (const [key, value] of Object.entries(opts.query)) {
129
+ url.searchParams.set(key, String(value))
130
+ }
131
+ }
93
132
  const request = new Request(url.toString(), {
94
133
  method: 'GET',
95
134
  headers: {
96
- 'Content-Type': 'application/json'
135
+ 'Content-Type': 'application/json',
136
+ ...(opts?.headers || {})
97
137
  }
98
138
  })
99
139
  await server.onConnect(socket.conn as any, { request } as any);
package/src/server.ts CHANGED
@@ -335,7 +335,7 @@ export class Server implements Party.Server {
335
335
  };
336
336
 
337
337
  try {
338
- const targetRoomParty = this.room.context.parties.main.get(targetRoomId);
338
+ const targetRoomParty = await this.room.context.parties.main.get(targetRoomId);
339
339
  const response = await targetRoomParty.fetch('/session-transfer', {
340
340
  method: 'POST',
341
341
  body: JSON.stringify(transferData),
package/src/testing.ts CHANGED
@@ -30,7 +30,9 @@ import { Shard } from "./shard"
30
30
  export async function testRoom(Room, options: {
31
31
  hibernate?: boolean,
32
32
  shard?: boolean,
33
- env?: Record<string, string>
33
+ env?: Record<string, string>,
34
+ parties?: Record<string, (io: any) => any>,
35
+ partyFn?: (io: any) => any
34
36
  } = {}) {
35
37
 
36
38
  const createServer = (io: any) => {
@@ -42,10 +44,14 @@ export async function testRoom(Room, options: {
42
44
  const isShard = options.shard || false
43
45
  const io = new ServerIo(Room.path, isShard ? {
44
46
  parties: {
45
- game: createServer
47
+ game: createServer,
48
+ ...(options.parties || {})
46
49
  },
50
+ partyFn: options.partyFn,
47
51
  env: options.env
48
52
  } : {
53
+ parties: options.parties,
54
+ partyFn: options.partyFn,
49
55
  env: options.env
50
56
  })
51
57
  Room.prototype.throttleSync = 0
@@ -58,11 +64,22 @@ export async function testRoom(Room, options: {
58
64
  // Add subRoom property to Shard for compatibility with Server
59
65
  (shardServer as any).subRoom = null;
60
66
  server = shardServer;
61
- for (const lobby of io.context.parties.main.values()) {
62
- await lobby.server.onStart();
67
+ // In shard mode, parties.main is a Map of lobbies; ensure their servers are started
68
+ if (io.context.parties.main instanceof Map) {
69
+ for (const lobby of io.context.parties.main.values()) {
70
+ await lobby.server.onStart();
71
+ }
63
72
  }
64
73
  } else {
65
74
  server = await createServer(io as any);
75
+ // If extra parties are provided in non-shard mode, start them too
76
+ if (io.context.parties.main instanceof Map) {
77
+ for (const lobby of io.context.parties.main.values()) {
78
+ if (lobby.server && lobby.server !== server) {
79
+ await lobby.server.onStart();
80
+ }
81
+ }
82
+ }
66
83
  }
67
84
 
68
85
  await server.onStart()
@@ -70,8 +87,8 @@ export async function testRoom(Room, options: {
70
87
  return {
71
88
  server,
72
89
  room: (server as any).subRoom,
73
- createClient: async (id?: string) => {
74
- const client = await io.connection(server as Server, id)
90
+ createClient: async (id?: string, opts?: { query?: Record<string, string>, headers?: Record<string, string> }) => {
91
+ const client = await io.connection(server as Server, id, opts)
75
92
  return client
76
93
  }
77
94
  }