@colyseus/shared-types 0.17.2 → 0.17.3
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/build/index.cjs.map +1 -1
- package/build/index.d.ts +40 -21
- package/build/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +55 -25
package/build/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { StandardSchemaV1 } from '@standard-schema/spec';\n\n// Re-export StandardSchemaV1 for convenience\nexport type { StandardSchemaV1 };\n\n// Re-export Protocol types\nexport { Protocol, ErrorCode, CloseCode } from './Protocol.js';\n\n/**\n * Minimal Room-like interface for SDK type inference.\n * Allows typing SDK methods without depending on @colyseus/core.\n */\nexport interface ServerRoomLike<State = any, Options = any> {\n state: State;\n onJoin
|
|
4
|
+
"sourcesContent": ["import type { StandardSchemaV1 } from '@standard-schema/spec';\n\n// Re-export StandardSchemaV1 for convenience\nexport type { StandardSchemaV1 };\n\n// Re-export Protocol types\nexport { Protocol, ErrorCode, CloseCode } from './Protocol.js';\n\n/**\n * Minimal Room-like interface for SDK type inference.\n * Allows typing SDK methods without depending on @colyseus/core.\n * Note: onJoin is optional because core Room defines it as optional.\n */\nexport interface ServerRoomLike<State = any, Options = any> {\n state: State;\n onJoin?: (client: any, options?: Options, auth?: any) => any;\n messages?: Record<string, any>;\n '~client'?: { '~messages'?: Record<string, any> };\n}\n\n/**\n * Seat reservation returned by matchmaking operations.\n */\nexport interface ISeatReservation {\n name: string;\n sessionId: string;\n roomId: string;\n publicAddress?: string;\n processId?: string;\n reconnectionToken?: string;\n devMode?: boolean;\n}\n\n/**\n * Extract instance type from a constructor type.\n * If T is not a constructor, returns T as-is.\n */\ntype Instantiate<T> = T extends abstract new (...args: any) => infer I ? I : T;\n\n/**\n * Check if a type is a Schema (has ~refId marker).\n * Schema defines ~refId as optional, so we check keyof instead of property presence.\n */\ntype IsSchema<T> = '~refId' extends keyof T ? true : false;\n\n/**\n * Check if ~state phantom property contains a useful type (not object/any/never).\n * Returns true if ~state exists and has meaningful structure.\n */\ntype HasUsefulStatePhantom<T> = T extends { '~state': infer S }\n ? [S] extends [never] ? false // never is not useful\n : unknown extends S ? false // any is not useful\n : S extends object\n ? [keyof S] extends [never] ? false // {} or object with no keys is not useful\n : true\n : false\n : false;\n\n/**\n * Extract state from a Room-like instance type.\n * Priority: useful ~state phantom > Schema state property > return T as-is\n */\ntype ExtractStateFromRoom<T> = T extends { '~state': infer S }\n ? HasUsefulStatePhantom<T> extends true\n ? S // Use ~state if it's useful\n : T extends { state: infer St }\n ? IsSchema<St> extends true ? St : T // Fallback to state if Schema\n : T\n : T extends { state: infer S }\n ? IsSchema<S> extends true ? S : T\n : T;\n\n/**\n * Infer the state type from T, or use explicit S if provided.\n *\n * Supports multiple usage patterns:\n * - Room<MyState>: T is a Schema type, return as-is\n * - Room<MyRoom>: T is a Room instance, extract from ~state or state property\n * - Room<typeof MyRoom>: T is a constructor, instantiate first then extract\n * - Room<T, ExplicitState>: S overrides all inference\n */\nexport type InferState<T, S> = [S] extends [never]\n ? Instantiate<T> extends infer I\n ? IsSchema<I> extends true\n ? I // It's a Schema, return as-is\n : ExtractStateFromRoom<I>\n : never\n : S;\n\n/**\n * Normalizes T for message extraction: returns T if it has ~state (Room type),\n * otherwise returns any (plain state type). This ensures Room<State> is equivalent\n * to Room<any, State> when State doesn't have ~state.\n */\nexport type NormalizeRoomType<T> = Instantiate<T> extends { '~state': any } ? T : any;\n\n/**\n * Extract room messages type from a Room constructor or instance type.\n * Supports both constructor types (typeof MyRoom) and instance types (MyRoom)\n */\nexport type ExtractRoomMessages<T> = Instantiate<T> extends { messages: infer M } ? M : {};\n\n/**\n * Extract client-side messages type from a Room constructor or instance type.\n * These are messages that the server can send to the client.\n */\nexport type ExtractRoomClientMessages<T> = Instantiate<T> extends { '~client': { '~messages': infer M } } ? M : {};\n\n/**\n * Message handler with automatic type inference from format schema.\n * When a format is provided, the message type is automatically inferred from the schema.\n *\n * @template T - The StandardSchema type for message validation\n * @template Client - The client type (from @colyseus/core Transport)\n * @template This - The Room class context\n */\nexport type MessageHandlerWithFormat<T extends StandardSchemaV1 = any, Client = any, This = any> = {\n format: T;\n handler: (this: This, client: Client, message: StandardSchemaV1.InferOutput<T>) => void;\n};\n\n/**\n * Message handler type that can be either a function or a format handler with validation.\n *\n * @template Client - The client type (from @colyseus/core Transport)\n * @template This - The Room class context\n */\nexport type MessageHandler<Client = any, This = any> =\n | ((this: This, client: Client, message: any) => void)\n | MessageHandlerWithFormat<any, Client, This>;\n\n/**\n * Extract the message payload type from a message handler.\n * Works with both function handlers and format handlers.\n */\nexport type ExtractMessageType<T> =\n T extends { format: infer Format extends StandardSchemaV1; handler: any }\n ? StandardSchemaV1.InferOutput<Format>\n : T extends (this: any, client: any, message: infer Message) => void\n ? Message\n : any;\n\n/**\n * A map of message types to message handlers.\n *\n * @template Room - The Room class type\n * @template Client - The client type\n */\nexport type Messages<Room = any, Client = any> = Record<string, MessageHandler<Client, Room>>;\n\n/**\n * Exposed types for the client-side SDK.\n * Used by defineServer() to expose room and route types to the client.\n *\n * @template RoomTypes - Record of room names to their RegisteredHandler types\n * @template Routes - Router type from @colyseus/better-call\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, any> = any,\n Routes = any\n> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,sBAA+C;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -4,10 +4,11 @@ export { Protocol, ErrorCode, CloseCode } from './Protocol.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* Minimal Room-like interface for SDK type inference.
|
|
6
6
|
* Allows typing SDK methods without depending on @colyseus/core.
|
|
7
|
+
* Note: onJoin is optional because core Room defines it as optional.
|
|
7
8
|
*/
|
|
8
9
|
export interface ServerRoomLike<State = any, Options = any> {
|
|
9
10
|
state: State;
|
|
10
|
-
onJoin
|
|
11
|
+
onJoin?: (client: any, options?: Options, auth?: any) => any;
|
|
11
12
|
messages?: Record<string, any>;
|
|
12
13
|
'~client'?: {
|
|
13
14
|
'~messages'?: Record<string, any>;
|
|
@@ -26,45 +27,63 @@ export interface ISeatReservation {
|
|
|
26
27
|
devMode?: boolean;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* Extract instance type from a constructor type.
|
|
31
|
+
* If T is not a constructor, returns T as-is.
|
|
32
|
+
*/
|
|
33
|
+
type Instantiate<T> = T extends abstract new (...args: any) => infer I ? I : T;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a type is a Schema (has ~refId marker).
|
|
36
|
+
* Schema defines ~refId as optional, so we check keyof instead of property presence.
|
|
37
|
+
*/
|
|
38
|
+
type IsSchema<T> = '~refId' extends keyof T ? true : false;
|
|
39
|
+
/**
|
|
40
|
+
* Check if ~state phantom property contains a useful type (not object/any/never).
|
|
41
|
+
* Returns true if ~state exists and has meaningful structure.
|
|
42
|
+
*/
|
|
43
|
+
type HasUsefulStatePhantom<T> = T extends {
|
|
44
|
+
'~state': infer S;
|
|
45
|
+
} ? [S] extends [never] ? false : unknown extends S ? false : S extends object ? [keyof S] extends [never] ? false : true : false : false;
|
|
46
|
+
/**
|
|
47
|
+
* Extract state from a Room-like instance type.
|
|
48
|
+
* Priority: useful ~state phantom > Schema state property > return T as-is
|
|
49
|
+
*/
|
|
50
|
+
type ExtractStateFromRoom<T> = T extends {
|
|
51
|
+
'~state': infer S;
|
|
52
|
+
} ? HasUsefulStatePhantom<T> extends true ? S : T extends {
|
|
53
|
+
state: infer St;
|
|
54
|
+
} ? IsSchema<St> extends true ? St : T : T : T extends {
|
|
55
|
+
state: infer S;
|
|
56
|
+
} ? IsSchema<S> extends true ? S : T : T;
|
|
57
|
+
/**
|
|
58
|
+
* Infer the state type from T, or use explicit S if provided.
|
|
31
59
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
60
|
+
* Supports multiple usage patterns:
|
|
61
|
+
* - Room<MyState>: T is a Schema type, return as-is
|
|
62
|
+
* - Room<MyRoom>: T is a Room instance, extract from ~state or state property
|
|
63
|
+
* - Room<typeof MyRoom>: T is a constructor, instantiate first then extract
|
|
64
|
+
* - Room<T, ExplicitState>: S overrides all inference
|
|
34
65
|
*/
|
|
35
|
-
export type InferState<T, S> = [S] extends [never] ?
|
|
36
|
-
'~state': infer ST;
|
|
37
|
-
} ? ST : T extends {
|
|
38
|
-
'~state': infer ST;
|
|
39
|
-
} ? ST : T) : S;
|
|
66
|
+
export type InferState<T, S> = [S] extends [never] ? Instantiate<T> extends infer I ? IsSchema<I> extends true ? I : ExtractStateFromRoom<I> : never : S;
|
|
40
67
|
/**
|
|
41
68
|
* Normalizes T for message extraction: returns T if it has ~state (Room type),
|
|
42
69
|
* otherwise returns any (plain state type). This ensures Room<State> is equivalent
|
|
43
70
|
* to Room<any, State> when State doesn't have ~state.
|
|
44
71
|
*/
|
|
45
|
-
export type NormalizeRoomType<T> = T extends
|
|
46
|
-
'~state': any;
|
|
47
|
-
} ? T : T extends {
|
|
72
|
+
export type NormalizeRoomType<T> = Instantiate<T> extends {
|
|
48
73
|
'~state': any;
|
|
49
74
|
} ? T : any;
|
|
50
75
|
/**
|
|
51
76
|
* Extract room messages type from a Room constructor or instance type.
|
|
52
77
|
* Supports both constructor types (typeof MyRoom) and instance types (MyRoom)
|
|
53
78
|
*/
|
|
54
|
-
export type ExtractRoomMessages<T> = T extends
|
|
55
|
-
messages: infer M;
|
|
56
|
-
} ? M : T extends {
|
|
79
|
+
export type ExtractRoomMessages<T> = Instantiate<T> extends {
|
|
57
80
|
messages: infer M;
|
|
58
81
|
} ? M : {};
|
|
59
82
|
/**
|
|
60
83
|
* Extract client-side messages type from a Room constructor or instance type.
|
|
61
84
|
* These are messages that the server can send to the client.
|
|
62
85
|
*/
|
|
63
|
-
export type ExtractRoomClientMessages<T> = T extends
|
|
64
|
-
'~client': {
|
|
65
|
-
'~messages': infer M;
|
|
66
|
-
};
|
|
67
|
-
} ? M : T extends {
|
|
86
|
+
export type ExtractRoomClientMessages<T> = Instantiate<T> extends {
|
|
68
87
|
'~client': {
|
|
69
88
|
'~messages': infer M;
|
|
70
89
|
};
|
package/build/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { StandardSchemaV1 } from '@standard-schema/spec';\n\n// Re-export StandardSchemaV1 for convenience\nexport type { StandardSchemaV1 };\n\n// Re-export Protocol types\nexport { Protocol, ErrorCode, CloseCode } from './Protocol.js';\n\n/**\n * Minimal Room-like interface for SDK type inference.\n * Allows typing SDK methods without depending on @colyseus/core.\n */\nexport interface ServerRoomLike<State = any, Options = any> {\n state: State;\n onJoin
|
|
4
|
+
"sourcesContent": ["import type { StandardSchemaV1 } from '@standard-schema/spec';\n\n// Re-export StandardSchemaV1 for convenience\nexport type { StandardSchemaV1 };\n\n// Re-export Protocol types\nexport { Protocol, ErrorCode, CloseCode } from './Protocol.js';\n\n/**\n * Minimal Room-like interface for SDK type inference.\n * Allows typing SDK methods without depending on @colyseus/core.\n * Note: onJoin is optional because core Room defines it as optional.\n */\nexport interface ServerRoomLike<State = any, Options = any> {\n state: State;\n onJoin?: (client: any, options?: Options, auth?: any) => any;\n messages?: Record<string, any>;\n '~client'?: { '~messages'?: Record<string, any> };\n}\n\n/**\n * Seat reservation returned by matchmaking operations.\n */\nexport interface ISeatReservation {\n name: string;\n sessionId: string;\n roomId: string;\n publicAddress?: string;\n processId?: string;\n reconnectionToken?: string;\n devMode?: boolean;\n}\n\n/**\n * Extract instance type from a constructor type.\n * If T is not a constructor, returns T as-is.\n */\ntype Instantiate<T> = T extends abstract new (...args: any) => infer I ? I : T;\n\n/**\n * Check if a type is a Schema (has ~refId marker).\n * Schema defines ~refId as optional, so we check keyof instead of property presence.\n */\ntype IsSchema<T> = '~refId' extends keyof T ? true : false;\n\n/**\n * Check if ~state phantom property contains a useful type (not object/any/never).\n * Returns true if ~state exists and has meaningful structure.\n */\ntype HasUsefulStatePhantom<T> = T extends { '~state': infer S }\n ? [S] extends [never] ? false // never is not useful\n : unknown extends S ? false // any is not useful\n : S extends object\n ? [keyof S] extends [never] ? false // {} or object with no keys is not useful\n : true\n : false\n : false;\n\n/**\n * Extract state from a Room-like instance type.\n * Priority: useful ~state phantom > Schema state property > return T as-is\n */\ntype ExtractStateFromRoom<T> = T extends { '~state': infer S }\n ? HasUsefulStatePhantom<T> extends true\n ? S // Use ~state if it's useful\n : T extends { state: infer St }\n ? IsSchema<St> extends true ? St : T // Fallback to state if Schema\n : T\n : T extends { state: infer S }\n ? IsSchema<S> extends true ? S : T\n : T;\n\n/**\n * Infer the state type from T, or use explicit S if provided.\n *\n * Supports multiple usage patterns:\n * - Room<MyState>: T is a Schema type, return as-is\n * - Room<MyRoom>: T is a Room instance, extract from ~state or state property\n * - Room<typeof MyRoom>: T is a constructor, instantiate first then extract\n * - Room<T, ExplicitState>: S overrides all inference\n */\nexport type InferState<T, S> = [S] extends [never]\n ? Instantiate<T> extends infer I\n ? IsSchema<I> extends true\n ? I // It's a Schema, return as-is\n : ExtractStateFromRoom<I>\n : never\n : S;\n\n/**\n * Normalizes T for message extraction: returns T if it has ~state (Room type),\n * otherwise returns any (plain state type). This ensures Room<State> is equivalent\n * to Room<any, State> when State doesn't have ~state.\n */\nexport type NormalizeRoomType<T> = Instantiate<T> extends { '~state': any } ? T : any;\n\n/**\n * Extract room messages type from a Room constructor or instance type.\n * Supports both constructor types (typeof MyRoom) and instance types (MyRoom)\n */\nexport type ExtractRoomMessages<T> = Instantiate<T> extends { messages: infer M } ? M : {};\n\n/**\n * Extract client-side messages type from a Room constructor or instance type.\n * These are messages that the server can send to the client.\n */\nexport type ExtractRoomClientMessages<T> = Instantiate<T> extends { '~client': { '~messages': infer M } } ? M : {};\n\n/**\n * Message handler with automatic type inference from format schema.\n * When a format is provided, the message type is automatically inferred from the schema.\n *\n * @template T - The StandardSchema type for message validation\n * @template Client - The client type (from @colyseus/core Transport)\n * @template This - The Room class context\n */\nexport type MessageHandlerWithFormat<T extends StandardSchemaV1 = any, Client = any, This = any> = {\n format: T;\n handler: (this: This, client: Client, message: StandardSchemaV1.InferOutput<T>) => void;\n};\n\n/**\n * Message handler type that can be either a function or a format handler with validation.\n *\n * @template Client - The client type (from @colyseus/core Transport)\n * @template This - The Room class context\n */\nexport type MessageHandler<Client = any, This = any> =\n | ((this: This, client: Client, message: any) => void)\n | MessageHandlerWithFormat<any, Client, This>;\n\n/**\n * Extract the message payload type from a message handler.\n * Works with both function handlers and format handlers.\n */\nexport type ExtractMessageType<T> =\n T extends { format: infer Format extends StandardSchemaV1; handler: any }\n ? StandardSchemaV1.InferOutput<Format>\n : T extends (this: any, client: any, message: infer Message) => void\n ? Message\n : any;\n\n/**\n * A map of message types to message handlers.\n *\n * @template Room - The Room class type\n * @template Client - The client type\n */\nexport type Messages<Room = any, Client = any> = Record<string, MessageHandler<Client, Room>>;\n\n/**\n * Exposed types for the client-side SDK.\n * Used by defineServer() to expose room and route types to the client.\n *\n * @template RoomTypes - Record of room names to their RegisteredHandler types\n * @template Routes - Router type from @colyseus/better-call\n */\nexport interface SDKTypes<\n RoomTypes extends Record<string, any> = any,\n Routes = any\n> {\n '~rooms': RoomTypes;\n '~routes': Routes;\n}\n"],
|
|
5
5
|
"mappings": ";AAMA,SAAS,UAAU,WAAW,iBAAiB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/shared-types",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.3",
|
|
4
4
|
"description": "Shared TypeScript types for Colyseus server and client SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"input": "./src/index.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"vitest": "^3.1.1",
|
|
50
|
-
"@colyseus/
|
|
51
|
-
"@colyseus/
|
|
50
|
+
"@colyseus/core": "^0.17.21",
|
|
51
|
+
"@colyseus/sdk": "^0.17.21"
|
|
52
52
|
},
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -9,10 +9,11 @@ export { Protocol, ErrorCode, CloseCode } from './Protocol.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* Minimal Room-like interface for SDK type inference.
|
|
11
11
|
* Allows typing SDK methods without depending on @colyseus/core.
|
|
12
|
+
* Note: onJoin is optional because core Room defines it as optional.
|
|
12
13
|
*/
|
|
13
14
|
export interface ServerRoomLike<State = any, Options = any> {
|
|
14
15
|
state: State;
|
|
15
|
-
onJoin
|
|
16
|
+
onJoin?: (client: any, options?: Options, auth?: any) => any;
|
|
16
17
|
messages?: Record<string, any>;
|
|
17
18
|
'~client'?: { '~messages'?: Record<string, any> };
|
|
18
19
|
}
|
|
@@ -31,18 +32,59 @@ export interface ISeatReservation {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
35
|
+
* Extract instance type from a constructor type.
|
|
36
|
+
* If T is not a constructor, returns T as-is.
|
|
37
|
+
*/
|
|
38
|
+
type Instantiate<T> = T extends abstract new (...args: any) => infer I ? I : T;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if a type is a Schema (has ~refId marker).
|
|
42
|
+
* Schema defines ~refId as optional, so we check keyof instead of property presence.
|
|
43
|
+
*/
|
|
44
|
+
type IsSchema<T> = '~refId' extends keyof T ? true : false;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check if ~state phantom property contains a useful type (not object/any/never).
|
|
48
|
+
* Returns true if ~state exists and has meaningful structure.
|
|
49
|
+
*/
|
|
50
|
+
type HasUsefulStatePhantom<T> = T extends { '~state': infer S }
|
|
51
|
+
? [S] extends [never] ? false // never is not useful
|
|
52
|
+
: unknown extends S ? false // any is not useful
|
|
53
|
+
: S extends object
|
|
54
|
+
? [keyof S] extends [never] ? false // {} or object with no keys is not useful
|
|
55
|
+
: true
|
|
56
|
+
: false
|
|
57
|
+
: false;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Extract state from a Room-like instance type.
|
|
61
|
+
* Priority: useful ~state phantom > Schema state property > return T as-is
|
|
62
|
+
*/
|
|
63
|
+
type ExtractStateFromRoom<T> = T extends { '~state': infer S }
|
|
64
|
+
? HasUsefulStatePhantom<T> extends true
|
|
65
|
+
? S // Use ~state if it's useful
|
|
66
|
+
: T extends { state: infer St }
|
|
67
|
+
? IsSchema<St> extends true ? St : T // Fallback to state if Schema
|
|
68
|
+
: T
|
|
69
|
+
: T extends { state: infer S }
|
|
70
|
+
? IsSchema<S> extends true ? S : T
|
|
71
|
+
: T;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Infer the state type from T, or use explicit S if provided.
|
|
36
75
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
76
|
+
* Supports multiple usage patterns:
|
|
77
|
+
* - Room<MyState>: T is a Schema type, return as-is
|
|
78
|
+
* - Room<MyRoom>: T is a Room instance, extract from ~state or state property
|
|
79
|
+
* - Room<typeof MyRoom>: T is a constructor, instantiate first then extract
|
|
80
|
+
* - Room<T, ExplicitState>: S overrides all inference
|
|
39
81
|
*/
|
|
40
82
|
export type InferState<T, S> = [S] extends [never]
|
|
41
|
-
?
|
|
42
|
-
?
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
83
|
+
? Instantiate<T> extends infer I
|
|
84
|
+
? IsSchema<I> extends true
|
|
85
|
+
? I // It's a Schema, return as-is
|
|
86
|
+
: ExtractStateFromRoom<I>
|
|
87
|
+
: never
|
|
46
88
|
: S;
|
|
47
89
|
|
|
48
90
|
/**
|
|
@@ -50,31 +92,19 @@ export type InferState<T, S> = [S] extends [never]
|
|
|
50
92
|
* otherwise returns any (plain state type). This ensures Room<State> is equivalent
|
|
51
93
|
* to Room<any, State> when State doesn't have ~state.
|
|
52
94
|
*/
|
|
53
|
-
export type NormalizeRoomType<T> = T extends
|
|
54
|
-
? T // Constructor type with ~state: keep as-is
|
|
55
|
-
: T extends { '~state': any }
|
|
56
|
-
? T // Instance type with ~state: keep as-is
|
|
57
|
-
: any; // Plain state type: normalize to any
|
|
95
|
+
export type NormalizeRoomType<T> = Instantiate<T> extends { '~state': any } ? T : any;
|
|
58
96
|
|
|
59
97
|
/**
|
|
60
98
|
* Extract room messages type from a Room constructor or instance type.
|
|
61
99
|
* Supports both constructor types (typeof MyRoom) and instance types (MyRoom)
|
|
62
100
|
*/
|
|
63
|
-
export type ExtractRoomMessages<T> = T extends
|
|
64
|
-
? M
|
|
65
|
-
: T extends { messages: infer M }
|
|
66
|
-
? M
|
|
67
|
-
: {};
|
|
101
|
+
export type ExtractRoomMessages<T> = Instantiate<T> extends { messages: infer M } ? M : {};
|
|
68
102
|
|
|
69
103
|
/**
|
|
70
104
|
* Extract client-side messages type from a Room constructor or instance type.
|
|
71
105
|
* These are messages that the server can send to the client.
|
|
72
106
|
*/
|
|
73
|
-
export type ExtractRoomClientMessages<T> = T extends
|
|
74
|
-
? M
|
|
75
|
-
: T extends { '~client': { '~messages': infer M } }
|
|
76
|
-
? M
|
|
77
|
-
: {};
|
|
107
|
+
export type ExtractRoomClientMessages<T> = Instantiate<T> extends { '~client': { '~messages': infer M } } ? M : {};
|
|
78
108
|
|
|
79
109
|
/**
|
|
80
110
|
* Message handler with automatic type inference from format schema.
|