@smoregg/sdk 0.6.2 → 1.0.0
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/README.md +29 -38
- package/dist/cjs/controller.cjs +299 -144
- package/dist/cjs/controller.cjs.map +1 -1
- package/dist/cjs/errors.cjs +36 -0
- package/dist/cjs/errors.cjs.map +1 -0
- package/dist/cjs/events.cjs +40 -19
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -8
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/logger.cjs +75 -0
- package/dist/cjs/logger.cjs.map +1 -0
- package/dist/cjs/screen.cjs +302 -215
- package/dist/cjs/screen.cjs.map +1 -1
- package/dist/cjs/testing.cjs +265 -22
- package/dist/cjs/testing.cjs.map +1 -1
- package/dist/cjs/transport/DirectTransport.cjs.map +1 -1
- package/dist/cjs/transport/PostMessageTransport.cjs +11 -6
- package/dist/cjs/transport/PostMessageTransport.cjs.map +1 -1
- package/dist/cjs/transport/protocol.cjs +25 -5
- package/dist/cjs/transport/protocol.cjs.map +1 -1
- package/dist/esm/controller.js +292 -136
- package/dist/esm/controller.js.map +1 -1
- package/dist/esm/errors.js +34 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/events.js +38 -18
- package/dist/esm/events.js.map +1 -1
- package/dist/esm/index.js +3 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logger.js +73 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/screen.js +290 -202
- package/dist/esm/screen.js.map +1 -1
- package/dist/esm/testing.js +265 -22
- package/dist/esm/testing.js.map +1 -1
- package/dist/esm/transport/DirectTransport.js.map +1 -1
- package/dist/esm/transport/PostMessageTransport.js +12 -7
- package/dist/esm/transport/PostMessageTransport.js.map +1 -1
- package/dist/esm/transport/protocol.js +23 -4
- package/dist/esm/transport/protocol.js.map +1 -1
- package/dist/types/controller.d.ts +1 -14
- package/dist/types/controller.d.ts.map +1 -1
- package/dist/types/errors.d.ts +45 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/events.d.ts +52 -12
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/logger.d.ts +35 -0
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/screen.d.ts +1 -14
- package/dist/types/screen.d.ts.map +1 -1
- package/dist/types/testing.d.ts +0 -1
- package/dist/types/testing.d.ts.map +1 -1
- package/dist/types/transport/DirectTransport.d.ts +2 -1
- package/dist/types/transport/DirectTransport.d.ts.map +1 -1
- package/dist/types/transport/PostMessageTransport.d.ts +17 -2
- package/dist/types/transport/PostMessageTransport.d.ts.map +1 -1
- package/dist/types/transport/index.d.ts +2 -2
- package/dist/types/transport/index.d.ts.map +1 -1
- package/dist/types/transport/protocol.d.ts +71 -23
- package/dist/types/transport/protocol.d.ts.map +1 -1
- package/dist/types/transport/types.d.ts +24 -2
- package/dist/types/transport/types.d.ts.map +1 -1
- package/dist/types/types.d.ts +298 -215
- package/dist/types/types.d.ts.map +1 -1
- package/dist/umd/smore-sdk.umd.js +950 -349
- package/dist/umd/smore-sdk.umd.js.map +1 -1
- package/dist/umd/smore-sdk.umd.min.js +1 -1
- package/dist/umd/smore-sdk.umd.min.js.map +1 -1
- package/package.json +8 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostMessageTransport.js","sources":["../../../src/transport/PostMessageTransport.ts"],"sourcesContent":["/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `
|
|
1
|
+
{"version":3,"file":"PostMessageTransport.js","sources":["../../../src/transport/PostMessageTransport.ts"],"sourcesContent":["/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `_bridge:emit` to parent and listens for `_bridge:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { BridgeEventMessage, BridgeAckMessage } from './protocol';\nimport { isBridgeMessage } from './protocol';\n\n/**\n * PostMessage-based transport for iframe-hosted games.\n *\n * Handles bi-directional communication between iframe game and parent platform using _bridge:* protocol.\n * - Outbound: `_bridge:emit` messages sent to parent\n * - Inbound: `_bridge:event` messages received from parent\n * - Acknowledgment: `_bridge:ack` pattern for request-response flows\n *\n * @example\n * ```ts\n * const transport = new PostMessageTransport('https://smore.gg');\n * transport.on('game-start', (data) => console.log('Game started', data));\n * transport.emit('player-ready', { playerIndex: 0 });\n * ```\n */\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: unknown[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: unknown[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: unknown = args[0];\n let ackId: string | undefined;\n\n // Branch 1: emit('event', callback) shorthand — no data, callback only\n // Callback will be invoked when parent sends _bridge:ack with matching ackId\n if (args.length === 1 && typeof args[0] === 'function') {\n data = undefined;\n const callback = args[0] as (...cbArgs: unknown[]) => void;\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n // Branch 2: emit('event', data, callback) — data + callback (request-response pattern)\n // Parent receives event with data and can send _bridge:ack response\n else if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args[0];\n const callback = args[args.length - 1] as (...cbArgs: unknown[]) => void;\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: '_bridge:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isBridgeMessage(msg)) return;\n\n // Branch 1: _bridge:event — state sync from bridge (server → bridge → game)\n // Parent relays socket events to iframe via this type. Game subscribes with on().\n if (msg.type === '_bridge:event') {\n const { event, data } = (msg as BridgeEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n }\n // Branch 2: _bridge:ack — response to emit with callback (request-response flow)\n // Fires the callback that was passed to emit('event', data, callback).\n // Edge case: In postMessage environment, callbacks cannot be truly serialized,\n // so only data types that survive JSON serialization roundtrip will work.\n else if (msg.type === '_bridge:ack') {\n const { ackId, data } = (msg as BridgeAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
const
|
|
2
|
-
function
|
|
3
|
-
return data && typeof data === "object" && typeof data.type === "string" && data.type.startsWith(
|
|
1
|
+
const BRIDGE_MSG_PREFIX = "_bridge:";
|
|
2
|
+
function isBridgeMessage(data) {
|
|
3
|
+
return data !== null && typeof data === "object" && "type" in data && typeof data.type === "string" && data.type.startsWith(BRIDGE_MSG_PREFIX);
|
|
4
|
+
}
|
|
5
|
+
function validateInitPayload(payload) {
|
|
6
|
+
if (!payload || typeof payload !== "object") {
|
|
7
|
+
throw new Error("[SDK] _bridge:init payload must be an object");
|
|
8
|
+
}
|
|
9
|
+
const p = payload;
|
|
10
|
+
if (typeof p.side !== "string" || !["host", "player"].includes(p.side)) {
|
|
11
|
+
throw new Error(`[SDK] _bridge:init payload.side must be "host" or "player", got: ${p.side}`);
|
|
12
|
+
}
|
|
13
|
+
if (typeof p.roomCode !== "string" || p.roomCode.length === 0) {
|
|
14
|
+
throw new Error("[SDK] _bridge:init payload.roomCode must be a non-empty string");
|
|
15
|
+
}
|
|
16
|
+
if (!Array.isArray(p.players)) {
|
|
17
|
+
throw new Error("[SDK] _bridge:init payload.players must be an array");
|
|
18
|
+
}
|
|
19
|
+
if (p.myIndex !== void 0 && typeof p.myIndex !== "number") {
|
|
20
|
+
throw new Error("[SDK] _bridge:init payload.myIndex must be a number if provided");
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
4
23
|
}
|
|
5
24
|
|
|
6
|
-
export {
|
|
25
|
+
export { BRIDGE_MSG_PREFIX, isBridgeMessage, validateInitPayload };
|
|
7
26
|
//# sourceMappingURL=protocol.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sources":["../../../src/transport/protocol.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const
|
|
1
|
+
{"version":3,"file":"protocol.js","sources":["../../../src/transport/protocol.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n *\n * Uses `_bridge:` prefix to clearly distinguish from `smore:*` socket events.\n * - `_bridge:*` = internal iframe postMessage protocol (never on socket)\n * - `smore:*` = platform service events (socket-level, e.g. smore:player-joined)\n */\n\n/**\n * Cross-reference: `CharacterAppearance` (SDK type) has an identical shape to\n * `CharacterDTO` (server type in game-project/types/src/types.ts).\n * If either type changes, the other must be updated to stay in sync.\n */\nimport type { CharacterAppearance } from '../types';\n\nexport const BRIDGE_MSG_PREFIX = '_bridge:' as const;\n\nexport interface BridgeReadyMessage {\n type: '_bridge:ready';\n}\n\n/**\n * BridgeInitMessage contains player data sent from the platform to the game iframe.\n *\n * **Field naming convention:**\n * The server uses `name` and `character` fields (matching server/Player model naming).\n * SDK code may reference fallback fields like `nickname` and `appearance` for defensive\n * compatibility with potential future field name changes, but currently the server\n * always sends `name` and `character`.\n */\nexport interface BridgeInitMessage {\n type: '_bridge:init';\n payload: {\n // 'host' = screen side, 'player' = controller side (legacy naming)\n side: 'host' | 'player';\n roomCode: string;\n players: Array<{\n playerIndex: number;\n name: string;\n connected: boolean;\n character: CharacterAppearance | null;\n }>;\n myIndex?: number;\n };\n}\n\nexport interface BridgeEmitMessage {\n type: '_bridge:emit';\n payload: {\n event: string;\n data?: unknown;\n ackId?: string;\n };\n}\n\nexport interface BridgeEventMessage {\n type: '_bridge:event';\n payload: {\n event: string;\n data?: unknown;\n };\n}\n\nexport interface BridgeAckMessage {\n type: '_bridge:ack';\n payload: {\n ackId: string;\n data?: unknown;\n };\n}\n\nexport interface BridgeUpdateMessage {\n type: '_bridge:update';\n payload: {\n players?: Array<{\n playerIndex: number;\n name: string;\n connected: boolean;\n character: CharacterAppearance | null;\n }>;\n };\n}\n\nexport type BridgeMessage =\n | BridgeReadyMessage\n | BridgeInitMessage\n | BridgeEmitMessage\n | BridgeEventMessage\n | BridgeAckMessage\n | BridgeUpdateMessage;\n\nexport function isBridgeMessage(data: unknown): data is BridgeMessage {\n return (\n data !== null &&\n typeof data === 'object' &&\n 'type' in data &&\n typeof data.type === 'string' &&\n data.type.startsWith(BRIDGE_MSG_PREFIX)\n );\n}\n\n/**\n * Validates the structure of a _bridge:init payload.\n *\n * Performs runtime validation to ensure the payload contains all required fields\n * with correct types. This provides early error detection if the parent frame\n * sends malformed initialization data.\n *\n * @param payload - The payload to validate\n * @returns true if payload is valid\n * @throws {Error} if validation fails with a descriptive error message\n *\n * @example\n * ```ts\n * try {\n * validateInitPayload(msg.payload);\n * // proceed with initialization\n * } catch (err) {\n * console.error('Invalid init payload:', err.message);\n * }\n * ```\n */\nexport function validateInitPayload(payload: unknown): payload is BridgeInitMessage['payload'] {\n if (!payload || typeof payload !== 'object') {\n throw new Error('[SDK] _bridge:init payload must be an object');\n }\n\n const p = payload as Record<string, unknown>;\n\n // Required: side\n if (typeof p.side !== 'string' || !['host', 'player'].includes(p.side)) {\n throw new Error(`[SDK] _bridge:init payload.side must be \"host\" or \"player\", got: ${p.side}`);\n }\n\n // Required: roomCode\n if (typeof p.roomCode !== 'string' || p.roomCode.length === 0) {\n throw new Error('[SDK] _bridge:init payload.roomCode must be a non-empty string');\n }\n\n // Required: players (array)\n if (!Array.isArray(p.players)) {\n throw new Error('[SDK] _bridge:init payload.players must be an array');\n }\n\n // Optional but validated if present: myIndex (controller-side only)\n if (p.myIndex !== undefined && typeof p.myIndex !== 'number') {\n throw new Error('[SDK] _bridge:init payload.myIndex must be a number if provided');\n }\n\n return true;\n}\n"],"names":[],"mappings":"AAeO,MAAM,iBAAA,GAAoB;AA4E1B,SAAS,gBAAgB,IAAA,EAAsC;AACpE,EAAA,OACE,IAAA,KAAS,IAAA,IACT,OAAO,IAAA,KAAS,YAChB,MAAA,IAAU,IAAA,IACV,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,IACrB,IAAA,CAAK,IAAA,CAAK,WAAW,iBAAiB,CAAA;AAE1C;AAuBO,SAAS,oBAAoB,OAAA,EAA2D;AAC7F,EAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,EAAU;AAC3C,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,MAAM,CAAA,GAAI,OAAA;AAGV,EAAA,IAAI,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAC,CAAC,MAAA,EAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,EAAG;AACtE,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iEAAA,EAAoE,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA;AAAA,EAC9F;AAGA,EAAA,IAAI,OAAO,CAAA,CAAE,QAAA,KAAa,YAAY,CAAA,CAAE,QAAA,CAAS,WAAW,CAAA,EAAG;AAC7D,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EAClF;AAGA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AAGA,EAAA,IAAI,EAAE,OAAA,KAAY,MAAA,IAAa,OAAO,CAAA,CAAE,YAAY,QAAA,EAAU;AAC5D,IAAA,MAAM,IAAI,MAAM,iEAAiE,CAAA;AAAA,EACnF;AAEA,EAAA,OAAO,IAAA;AACT;;;;"}
|
|
@@ -27,20 +27,7 @@
|
|
|
27
27
|
* // Use controller.instance for immediate access
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
import type { Controller, ControllerConfig, EventMap
|
|
31
|
-
/**
|
|
32
|
-
* Custom error class for SDK errors.
|
|
33
|
-
*/
|
|
34
|
-
export declare class SmoreSDKError extends Error {
|
|
35
|
-
readonly code: SmoreErrorCode;
|
|
36
|
-
readonly cause?: Error;
|
|
37
|
-
readonly details?: Record<string, unknown>;
|
|
38
|
-
constructor(code: SmoreErrorCode, message: string, options?: {
|
|
39
|
-
cause?: Error;
|
|
40
|
-
details?: Record<string, unknown>;
|
|
41
|
-
});
|
|
42
|
-
toSmoreError(): SmoreError;
|
|
43
|
-
}
|
|
30
|
+
import type { Controller, ControllerConfig, EventMap } from './types';
|
|
44
31
|
/**
|
|
45
32
|
* Create a Controller instance for the player/phone side of your game.
|
|
46
33
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAIhB,QAAQ,EAIT,MAAM,SAAS,CAAC;AA8qBjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,SAAS,QAAQ,GAAG,QAAQ,EAClE,MAAM,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,GACjC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG;IAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;CAAE,CAUlE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SmoreError, SmoreErrorCode } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Base error class for SDK-specific errors with structured metadata.
|
|
4
|
+
*
|
|
5
|
+
* Provides error codes, optional cause chaining, and custom details for debugging.
|
|
6
|
+
* Use this instead of generic Error for all SDK-thrown errors.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* throw new SmoreSDKError('INVALID_EVENT', 'Event name must not contain ":"', {
|
|
11
|
+
* details: { event: 'foo:bar' }
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example With cause
|
|
16
|
+
* ```ts
|
|
17
|
+
* try {
|
|
18
|
+
* JSON.parse(data);
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* throw new SmoreSDKError('UNKNOWN', 'Invalid JSON payload', {
|
|
21
|
+
* cause: err as Error,
|
|
22
|
+
* details: { rawData: data }
|
|
23
|
+
* });
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class SmoreSDKError extends Error {
|
|
28
|
+
readonly code: SmoreErrorCode;
|
|
29
|
+
/**
|
|
30
|
+
* The original error that caused this error.
|
|
31
|
+
*
|
|
32
|
+
* **Note:** This field intentionally shadows the native `Error.cause` (ES2022).
|
|
33
|
+
* Both this class field and the native property (set via `super()` options bag)
|
|
34
|
+
* are assigned the same value, so there is no behavioral difference.
|
|
35
|
+
* The explicit field provides TypeScript type narrowing to `Error` instead of `unknown`.
|
|
36
|
+
*/
|
|
37
|
+
readonly cause?: Error;
|
|
38
|
+
readonly details?: Record<string, unknown>;
|
|
39
|
+
constructor(code: SmoreErrorCode, message: string, options?: {
|
|
40
|
+
cause?: Error;
|
|
41
|
+
details?: Record<string, unknown>;
|
|
42
|
+
});
|
|
43
|
+
toSmoreError(): SmoreError;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGzC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAehE,YAAY,IAAI,UAAU;CAQ3B"}
|
package/dist/types/events.d.ts
CHANGED
|
@@ -1,26 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SDK
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* SDK system event constants (socket level)
|
|
3
|
+
*
|
|
4
|
+
* smore:* prefix = platform service events
|
|
5
|
+
* User events are validated to prevent ':' usage via validateEventName()
|
|
6
|
+
*
|
|
7
|
+
* Note: iframe ↔ parent internal communication uses _bridge:* prefix (transport/protocol.ts)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Platform system event names (internal use only).
|
|
11
|
+
*
|
|
12
|
+
* These events are reserved by the S'MORE platform and cannot be used by game code.
|
|
13
|
+
* All platform events use the `smore:` prefix to avoid conflicts with user events.
|
|
14
|
+
*
|
|
15
|
+
* User-defined events are validated to prevent `:` usage via validateEventName().
|
|
16
|
+
*
|
|
17
|
+
* @internal Not part of the public SDK API. Do not import directly.
|
|
5
18
|
*/
|
|
6
19
|
export declare const SMORE_EVENTS: {
|
|
7
|
-
readonly READY: "smore:ready";
|
|
8
20
|
readonly GAME_OVER: "smore:game-over";
|
|
9
21
|
readonly RETURN_TO_LOBBY: "smore:return-to-lobby";
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
22
|
+
readonly PLAYER_JOINED: "smore:player-joined";
|
|
23
|
+
readonly PLAYER_LEFT: "smore:player-left";
|
|
24
|
+
readonly PLAYER_DISCONNECTED: "smore:player-disconnected";
|
|
25
|
+
readonly PLAYER_RECONNECTED: "smore:player-reconnected";
|
|
26
|
+
readonly PLAYER_CHARACTER_UPDATED: "smore:player-character-updated";
|
|
27
|
+
readonly RATE_LIMITED: "smore:rate-limited";
|
|
12
28
|
readonly SEND_TO_PLAYER: "smore:send-to-player";
|
|
13
|
-
readonly INIT: "smore:init";
|
|
14
|
-
readonly UPDATE: "smore:update";
|
|
15
29
|
};
|
|
16
30
|
export type SmoreEvent = typeof SMORE_EVENTS[keyof typeof SMORE_EVENTS];
|
|
31
|
+
export declare const SYSTEM_EVENTS: ReadonlySet<string>;
|
|
32
|
+
export declare const EVENT_NAME_REGEX: RegExp;
|
|
33
|
+
export declare const EVENT_NAME_MAX_LENGTH = 128;
|
|
17
34
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
35
|
+
* Validate a user-defined event name.
|
|
36
|
+
*
|
|
37
|
+
* Enforces naming rules to prevent conflicts with platform system events:
|
|
38
|
+
* - Must start with a letter
|
|
39
|
+
* - Can contain letters, numbers, hyphens, underscores
|
|
40
|
+
* - Must end with a letter or number
|
|
41
|
+
* - Cannot contain `:` (reserved for platform events like `smore:*`)
|
|
42
|
+
* - Maximum length: 128 characters
|
|
43
|
+
*
|
|
44
|
+
* @throws {SmoreSDKError} INVALID_EVENT if validation fails
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* validateEventName('player-ready'); // OK
|
|
49
|
+
* validateEventName('score_update'); // OK
|
|
50
|
+
* validateEventName('tap123'); // OK
|
|
51
|
+
* validateEventName('smore:internal'); // Throws: colon not allowed
|
|
52
|
+
* validateEventName('123start'); // Throws: must start with letter
|
|
53
|
+
* ```
|
|
20
54
|
*/
|
|
21
|
-
export declare function
|
|
55
|
+
export declare function validateEventName(event: string): void;
|
|
22
56
|
/**
|
|
23
|
-
*
|
|
57
|
+
* Check if an event name is a system event.
|
|
58
|
+
*
|
|
59
|
+
* System events use the `smore:` prefix and are reserved for platform use.
|
|
60
|
+
* Prefix-based check is intentional for forward-compatibility with new system events.
|
|
61
|
+
*
|
|
62
|
+
* @param event - Event name to check
|
|
63
|
+
* @returns true if the event is a system event
|
|
24
64
|
*/
|
|
25
65
|
export declare function isSystemEvent(event: string): boolean;
|
|
26
66
|
//# sourceMappingURL=events.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;CAmBf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAExE,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAE7C,CAAC;AAGF,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AAEzE,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAmBrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -35,13 +35,11 @@
|
|
|
35
35
|
* controller.send('tap', { timestamp: Date.now() });
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
|
-
export { createScreen
|
|
38
|
+
export { createScreen } from './screen';
|
|
39
39
|
export { createController } from './controller';
|
|
40
|
-
export
|
|
41
|
-
export {
|
|
42
|
-
export {
|
|
43
|
-
export { SMORE_EVENTS, validateUserEvent, isSystemEvent } from './events';
|
|
44
|
-
export type { SmoreEvent } from './events';
|
|
40
|
+
export { SmoreSDKError } from './errors';
|
|
41
|
+
export { validateEventName } from './events';
|
|
42
|
+
export type { PlayerIndex, RoomCode, EventMap, EventNames, EventData, Controller, ControllerConfig, ControllerEventHandler, ControllerListeners, ControllerInfo, CharacterAppearance, Screen, ScreenConfig, ScreenEventHandler, ScreenListeners, GameResults, SmoreError, SmoreErrorCode, LogLevel, DebugOptions, GameMetadata, } from './types';
|
|
45
43
|
export { createMockScreen, createMockController } from './testing';
|
|
46
44
|
export type { MockScreen, MockController, MockOptions } from './testing';
|
|
47
45
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAMH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,YAAY,EAEV,WAAW,EACX,QAAQ,EAER,QAAQ,EACR,UAAU,EACV,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EAEnB,MAAM,EACN,YAAY,EACZ,kBAAkB,EAClB,eAAe,EAEf,WAAW,EAEX,UAAU,EACV,cAAc,EAEd,QAAQ,EACR,YAAY,EAEZ,YAAY,GACb,MAAM,SAAS,CAAC;AAMjB,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { DebugOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Internal debug logger with configurable verbosity levels.
|
|
4
|
+
*
|
|
5
|
+
* Maps SDK log levels (debug/info/warn/error) to console methods.
|
|
6
|
+
* Can be toggled per-instance with granular control over send/receive/lifecycle logs.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const logger = new DebugLogger({ enabled: true, level: 'info' });
|
|
11
|
+
* logger.info('Game initialized');
|
|
12
|
+
* logger.send('player-ready', { index: 0 }); // Shows as debug
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class DebugLogger {
|
|
16
|
+
private enabled;
|
|
17
|
+
private level;
|
|
18
|
+
private prefix;
|
|
19
|
+
private logSend;
|
|
20
|
+
private logReceive;
|
|
21
|
+
private logLifecycle;
|
|
22
|
+
private customLogger?;
|
|
23
|
+
private static levelOrder;
|
|
24
|
+
constructor(options?: boolean | DebugOptions, defaultPrefix?: string);
|
|
25
|
+
private shouldLog;
|
|
26
|
+
private log;
|
|
27
|
+
debug(message: string, data?: unknown): void;
|
|
28
|
+
info(message: string, data?: unknown): void;
|
|
29
|
+
warn(message: string, data?: unknown): void;
|
|
30
|
+
error(message: string, data?: unknown): void;
|
|
31
|
+
send(event: string, data?: unknown): void;
|
|
32
|
+
receive(event: string, data?: unknown): void;
|
|
33
|
+
lifecycle(message: string, data?: unknown): void;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,SAAS,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,YAAY,CAAC,CAA6D;IAElF,OAAO,CAAC,MAAM,CAAC,UAAU,CAKvB;gBAEU,OAAO,CAAC,EAAE,OAAO,GAAG,YAAY,EAAE,aAAa,SAAY;IAWvE,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;IAgBX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAOzC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAO5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;CAKjD"}
|
package/dist/types/screen.d.ts
CHANGED
|
@@ -28,20 +28,7 @@
|
|
|
28
28
|
* // Use screen.instance for immediate access
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
|
-
import type { EventMap, Screen, ScreenConfig
|
|
32
|
-
/**
|
|
33
|
-
* Custom error class for SDK errors with structured error handling.
|
|
34
|
-
*/
|
|
35
|
-
export declare class SmoreSDKError extends Error {
|
|
36
|
-
readonly code: SmoreErrorCode;
|
|
37
|
-
readonly cause?: Error;
|
|
38
|
-
readonly details?: Record<string, unknown>;
|
|
39
|
-
constructor(code: SmoreErrorCode, message: string, options?: {
|
|
40
|
-
cause?: Error;
|
|
41
|
-
details?: Record<string, unknown>;
|
|
42
|
-
});
|
|
43
|
-
toSmoreError(): SmoreError;
|
|
44
|
-
}
|
|
31
|
+
import type { EventMap, Screen, ScreenConfig } from './types';
|
|
45
32
|
/**
|
|
46
33
|
* Create a Screen instance for the host/TV side of your game.
|
|
47
34
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EACV,QAAQ,EAGR,MAAM,EACN,YAAY,
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EACV,QAAQ,EAGR,MAAM,EACN,YAAY,EAMb,MAAM,SAAS,CAAC;AAuvBjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAAC,OAAO,SAAS,QAAQ,GAAG,QAAQ,EAC9D,MAAM,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,GAC7B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;CAAE,CAU1D"}
|
package/dist/types/testing.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,QAAQ,
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,QAAQ,EASR,UAAU,EACV,cAAc,EACd,WAAW,EACZ,MAAM,SAAS,CAAC;AAkBjB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,SAAS,QAAQ,GAAG,QAAQ,EAClE,OAAO,GAAE,WAAgB,GACxB,UAAU,CAAC,OAAO,CAAC,CA6VrB;AAWD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,QAAQ,GAAG,QAAQ,EACtE,OAAO,GAAE,WAAgB,GACxB,cAAc,CAAC,OAAO,CAAC,CA8RzB;AAMD,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -7,8 +7,9 @@ import type { Transport, TransportEventHandler } from './types';
|
|
|
7
7
|
export declare class DirectTransport implements Transport {
|
|
8
8
|
private socket;
|
|
9
9
|
constructor(socket: Socket);
|
|
10
|
-
emit(event: string, ...args:
|
|
10
|
+
emit(event: string, ...args: unknown[]): void;
|
|
11
11
|
on(event: string, handler: TransportEventHandler): void;
|
|
12
12
|
off(event: string, handler?: TransportEventHandler): void;
|
|
13
|
+
destroy(): void;
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=DirectTransport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DirectTransport.d.ts","sourceRoot":"","sources":["../../../src/transport/DirectTransport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhE,qBAAa,eAAgB,YAAW,SAAS;IACnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAElC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"DirectTransport.d.ts","sourceRoot":"","sources":["../../../src/transport/DirectTransport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhE,qBAAa,eAAgB,YAAW,SAAS;IACnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAElC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI7C,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAIvD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI;IAQzD,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PostMessageTransport - Transport over window.postMessage for iframe-hosted games.
|
|
3
3
|
*
|
|
4
|
-
* Used inside an iframe. Sends `
|
|
4
|
+
* Used inside an iframe. Sends `_bridge:emit` to parent and listens for `_bridge:event` from parent.
|
|
5
5
|
*/
|
|
6
6
|
import type { Transport, TransportEventHandler } from './types';
|
|
7
|
+
/**
|
|
8
|
+
* PostMessage-based transport for iframe-hosted games.
|
|
9
|
+
*
|
|
10
|
+
* Handles bi-directional communication between iframe game and parent platform using _bridge:* protocol.
|
|
11
|
+
* - Outbound: `_bridge:emit` messages sent to parent
|
|
12
|
+
* - Inbound: `_bridge:event` messages received from parent
|
|
13
|
+
* - Acknowledgment: `_bridge:ack` pattern for request-response flows
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const transport = new PostMessageTransport('https://smore.gg');
|
|
18
|
+
* transport.on('game-start', (data) => console.log('Game started', data));
|
|
19
|
+
* transport.emit('player-ready', { playerIndex: 0 });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
7
22
|
export declare class PostMessageTransport implements Transport {
|
|
8
23
|
private handlers;
|
|
9
24
|
private ackCallbacks;
|
|
@@ -11,7 +26,7 @@ export declare class PostMessageTransport implements Transport {
|
|
|
11
26
|
private parentOrigin;
|
|
12
27
|
private boundMessageHandler;
|
|
13
28
|
constructor(parentOrigin?: string);
|
|
14
|
-
emit(event: string, ...args:
|
|
29
|
+
emit(event: string, ...args: unknown[]): void;
|
|
15
30
|
on(event: string, handler: TransportEventHandler): void;
|
|
16
31
|
off(event: string, handler?: TransportEventHandler): void;
|
|
17
32
|
destroy(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostMessageTransport.d.ts","sourceRoot":"","sources":["../../../src/transport/PostMessageTransport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAIhE,qBAAa,oBAAqB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"PostMessageTransport.d.ts","sourceRoot":"","sources":["../../../src/transport/PostMessageTransport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAIhE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,YAAY,CAAmD;IACvE,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,mBAAmB,CAA4B;gBAE3C,YAAY,GAAE,MAAY;IAMtC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IA4B7C,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IASvD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI;IAQzD,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,aAAa;CA6BtB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { Transport, TransportEventHandler } from './types';
|
|
2
2
|
export { DirectTransport } from './DirectTransport';
|
|
3
3
|
export { PostMessageTransport } from './PostMessageTransport';
|
|
4
|
-
export {
|
|
5
|
-
export type {
|
|
4
|
+
export { isBridgeMessage } from './protocol';
|
|
5
|
+
export type { BridgeMessage, BridgeReadyMessage, BridgeInitMessage, BridgeEmitMessage, BridgeEventMessage, BridgeAckMessage, BridgeUpdateMessage, } from './protocol';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
@@ -1,50 +1,98 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* postMessage protocol types for iframe ↔ parent communication.
|
|
3
|
+
*
|
|
4
|
+
* Uses `_bridge:` prefix to clearly distinguish from `smore:*` socket events.
|
|
5
|
+
* - `_bridge:*` = internal iframe postMessage protocol (never on socket)
|
|
6
|
+
* - `smore:*` = platform service events (socket-level, e.g. smore:player-joined)
|
|
3
7
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Cross-reference: `CharacterAppearance` (SDK type) has an identical shape to
|
|
10
|
+
* `CharacterDTO` (server type in game-project/types/src/types.ts).
|
|
11
|
+
* If either type changes, the other must be updated to stay in sync.
|
|
12
|
+
*/
|
|
13
|
+
import type { CharacterAppearance } from '../types';
|
|
14
|
+
export declare const BRIDGE_MSG_PREFIX: "_bridge:";
|
|
15
|
+
export interface BridgeReadyMessage {
|
|
16
|
+
type: '_bridge:ready';
|
|
7
17
|
}
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
/**
|
|
19
|
+
* BridgeInitMessage contains player data sent from the platform to the game iframe.
|
|
20
|
+
*
|
|
21
|
+
* **Field naming convention:**
|
|
22
|
+
* The server uses `name` and `character` fields (matching server/Player model naming).
|
|
23
|
+
* SDK code may reference fallback fields like `nickname` and `appearance` for defensive
|
|
24
|
+
* compatibility with potential future field name changes, but currently the server
|
|
25
|
+
* always sends `name` and `character`.
|
|
26
|
+
*/
|
|
27
|
+
export interface BridgeInitMessage {
|
|
28
|
+
type: '_bridge:init';
|
|
10
29
|
payload: {
|
|
11
30
|
side: 'host' | 'player';
|
|
12
31
|
roomCode: string;
|
|
13
|
-
players:
|
|
14
|
-
|
|
32
|
+
players: Array<{
|
|
33
|
+
playerIndex: number;
|
|
34
|
+
name: string;
|
|
35
|
+
connected: boolean;
|
|
36
|
+
character: CharacterAppearance | null;
|
|
37
|
+
}>;
|
|
15
38
|
myIndex?: number;
|
|
16
|
-
isLeader?: boolean;
|
|
17
39
|
};
|
|
18
40
|
}
|
|
19
|
-
export interface
|
|
20
|
-
type: '
|
|
41
|
+
export interface BridgeEmitMessage {
|
|
42
|
+
type: '_bridge:emit';
|
|
21
43
|
payload: {
|
|
22
44
|
event: string;
|
|
23
|
-
data?:
|
|
45
|
+
data?: unknown;
|
|
24
46
|
ackId?: string;
|
|
25
47
|
};
|
|
26
48
|
}
|
|
27
|
-
export interface
|
|
28
|
-
type: '
|
|
49
|
+
export interface BridgeEventMessage {
|
|
50
|
+
type: '_bridge:event';
|
|
29
51
|
payload: {
|
|
30
52
|
event: string;
|
|
31
|
-
data?:
|
|
53
|
+
data?: unknown;
|
|
32
54
|
};
|
|
33
55
|
}
|
|
34
|
-
export interface
|
|
35
|
-
type: '
|
|
56
|
+
export interface BridgeAckMessage {
|
|
57
|
+
type: '_bridge:ack';
|
|
36
58
|
payload: {
|
|
37
59
|
ackId: string;
|
|
38
|
-
data?:
|
|
60
|
+
data?: unknown;
|
|
39
61
|
};
|
|
40
62
|
}
|
|
41
|
-
export interface
|
|
42
|
-
type: '
|
|
63
|
+
export interface BridgeUpdateMessage {
|
|
64
|
+
type: '_bridge:update';
|
|
43
65
|
payload: {
|
|
44
|
-
players?:
|
|
45
|
-
|
|
66
|
+
players?: Array<{
|
|
67
|
+
playerIndex: number;
|
|
68
|
+
name: string;
|
|
69
|
+
connected: boolean;
|
|
70
|
+
character: CharacterAppearance | null;
|
|
71
|
+
}>;
|
|
46
72
|
};
|
|
47
73
|
}
|
|
48
|
-
export type
|
|
49
|
-
export declare function
|
|
74
|
+
export type BridgeMessage = BridgeReadyMessage | BridgeInitMessage | BridgeEmitMessage | BridgeEventMessage | BridgeAckMessage | BridgeUpdateMessage;
|
|
75
|
+
export declare function isBridgeMessage(data: unknown): data is BridgeMessage;
|
|
76
|
+
/**
|
|
77
|
+
* Validates the structure of a _bridge:init payload.
|
|
78
|
+
*
|
|
79
|
+
* Performs runtime validation to ensure the payload contains all required fields
|
|
80
|
+
* with correct types. This provides early error detection if the parent frame
|
|
81
|
+
* sends malformed initialization data.
|
|
82
|
+
*
|
|
83
|
+
* @param payload - The payload to validate
|
|
84
|
+
* @returns true if payload is valid
|
|
85
|
+
* @throws {Error} if validation fails with a descriptive error message
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* try {
|
|
90
|
+
* validateInitPayload(msg.payload);
|
|
91
|
+
* // proceed with initialization
|
|
92
|
+
* } catch (err) {
|
|
93
|
+
* console.error('Invalid init payload:', err.message);
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function validateInitPayload(payload: unknown): payload is BridgeInitMessage['payload'];
|
|
50
98
|
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/transport/protocol.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/transport/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAG,UAAmB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,eAAe,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE;QAEP,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,KAAK,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,EAAE,OAAO,CAAC;YACnB,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;SACvC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,KAAK,CAAC;YACd,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,EAAE,OAAO,CAAC;YACnB,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;SACvC,CAAC,CAAC;KACJ,CAAC;CACH;AAED,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,gBAAgB,GAChB,mBAAmB,CAAC;AAExB,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,CAQpE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,iBAAiB,CAAC,SAAS,CAAC,CA4B7F"}
|
|
@@ -5,10 +5,32 @@
|
|
|
5
5
|
* - DirectTransport: wraps a Socket.IO socket (bundled games)
|
|
6
6
|
* - PostMessageTransport: wraps window.postMessage (iframe games)
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Event handler callback type for transport layer.
|
|
10
|
+
*
|
|
11
|
+
* Receives arbitrary arguments from the transport implementation.
|
|
12
|
+
*/
|
|
13
|
+
export type TransportEventHandler = (...args: unknown[]) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Abstract transport interface for SDK communication.
|
|
16
|
+
*
|
|
17
|
+
* Decouples SDK core from the underlying messaging protocol.
|
|
18
|
+
* Implementations provide concrete message passing:
|
|
19
|
+
* - PostMessageTransport: iframe-based games using window.postMessage
|
|
20
|
+
* - DirectTransport: bundled games using Socket.IO
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const transport = new PostMessageTransport('https://smore.gg');
|
|
25
|
+
* transport.on('event-name', (data) => console.log(data));
|
|
26
|
+
* transport.emit('other-event', { payload: 123 });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
9
29
|
export interface Transport {
|
|
10
|
-
emit(event: string, ...args:
|
|
30
|
+
emit(event: string, ...args: unknown[]): void;
|
|
11
31
|
on(event: string, handler: TransportEventHandler): void;
|
|
12
32
|
off(event: string, handler?: TransportEventHandler): void;
|
|
33
|
+
/** Clean up resources (remove event listeners, clear internal state). */
|
|
34
|
+
destroy(): void;
|
|
13
35
|
}
|
|
14
36
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/transport/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/transport/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAEjE;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9C,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACxD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC1D,yEAAyE;IACzE,OAAO,IAAI,IAAI,CAAC;CACjB"}
|