Actually using Type Guards in queries received by WA.
This commit is contained in:
parent
0aa93543bc
commit
86fa869b20
3 changed files with 45 additions and 32 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import * as tg from "generic-type-guard";
|
||||||
import type { GameStateEvent } from "./GameStateEvent";
|
import type { GameStateEvent } from "./GameStateEvent";
|
||||||
import type { ButtonClickedEvent } from "./ButtonClickedEvent";
|
import type { ButtonClickedEvent } from "./ButtonClickedEvent";
|
||||||
import type { ChatEvent } from "./ChatEvent";
|
import type { ChatEvent } from "./ChatEvent";
|
||||||
|
@ -19,6 +20,9 @@ import type { MenuItemRegisterEvent } from "./ui/MenuItemRegisterEvent";
|
||||||
import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent";
|
import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent";
|
||||||
import type { SetTilesEvent } from "./SetTilesEvent";
|
import type { SetTilesEvent } from "./SetTilesEvent";
|
||||||
import type { SetVariableEvent } from "./SetVariableEvent";
|
import type { SetVariableEvent } from "./SetVariableEvent";
|
||||||
|
import {isGameStateEvent} from "./GameStateEvent";
|
||||||
|
import {isMapDataEvent} from "./MapDataEvent";
|
||||||
|
import {isSetVariableEvent} from "./SetVariableEvent";
|
||||||
|
|
||||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||||
data: T;
|
data: T;
|
||||||
|
@ -81,20 +85,32 @@ export const isIframeResponseEventWrapper = (event: {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List event types sent from an iFrame to WorkAdventure that expect a unique answer from WorkAdventure along the type for the answer from WorkAdventure to the iFrame
|
* List event types sent from an iFrame to WorkAdventure that expect a unique answer from WorkAdventure along the type for the answer from WorkAdventure to the iFrame.
|
||||||
|
* Types are defined using Type guards that will actually bused to enforce and check types.
|
||||||
*/
|
*/
|
||||||
export type IframeQueryMap = {
|
export const iframeQueryMapTypeGuards = {
|
||||||
getState: {
|
getState: {
|
||||||
query: undefined,
|
query: tg.isUndefined,
|
||||||
answer: GameStateEvent,
|
answer: isGameStateEvent,
|
||||||
},
|
},
|
||||||
getMapData: {
|
getMapData: {
|
||||||
query: undefined,
|
query: tg.isUndefined,
|
||||||
answer: MapDataEvent,
|
answer: isMapDataEvent,
|
||||||
},
|
},
|
||||||
setVariable: {
|
setVariable: {
|
||||||
query: SetVariableEvent,
|
query: isSetVariableEvent,
|
||||||
answer: void
|
answer: tg.isUndefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type GuardedType<T> = T extends (x: unknown) => x is (infer T) ? T : never;
|
||||||
|
type IframeQueryMapTypeGuardsType = typeof iframeQueryMapTypeGuards;
|
||||||
|
type UnknownToVoid<T> = undefined extends T ? void : T;
|
||||||
|
|
||||||
|
export type IframeQueryMap = {
|
||||||
|
[key in keyof IframeQueryMapTypeGuardsType]: {
|
||||||
|
query: GuardedType<IframeQueryMapTypeGuardsType[key]['query']>
|
||||||
|
answer: UnknownToVoid<GuardedType<IframeQueryMapTypeGuardsType[key]['answer']>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,8 +124,21 @@ export interface IframeQueryWrapper<T extends keyof IframeQueryMap> {
|
||||||
query: IframeQuery<T>;
|
query: IframeQuery<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isIframeQueryKey = (type: string): type is keyof IframeQueryMap => {
|
||||||
|
return type in iframeQueryMapTypeGuards;
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const isIframeQuery = (event: any): event is IframeQuery<keyof IframeQueryMap> => typeof event.type === 'string';
|
export const isIframeQuery = (event: any): event is IframeQuery<keyof IframeQueryMap> => {
|
||||||
|
const type = event.type;
|
||||||
|
if (typeof type !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isIframeQueryKey(type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return iframeQueryMapTypeGuards[type].query(event.data);
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const isIframeQueryWrapper = (event: any): event is IframeQueryWrapper<keyof IframeQueryMap> => typeof event.id === 'number' && isIframeQuery(event.query);
|
export const isIframeQueryWrapper = (event: any): event is IframeQueryWrapper<keyof IframeQueryMap> => typeof event.id === 'number' && isIframeQuery(event.query);
|
||||||
|
|
|
@ -168,13 +168,15 @@ class IframeListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorHandler = (reason: any) => {
|
const errorHandler = (reason: unknown) => {
|
||||||
console.error('An error occurred while responding to an iFrame query.', reason);
|
console.error('An error occurred while responding to an iFrame query.', reason);
|
||||||
let reasonMsg: string;
|
let reasonMsg: string = '';
|
||||||
if (reason instanceof Error) {
|
if (reason instanceof Error) {
|
||||||
reasonMsg = reason.message;
|
reasonMsg = reason.message;
|
||||||
} else {
|
} else if (typeof reason === 'object') {
|
||||||
reasonMsg = reason.toString();
|
reasonMsg = reason ? reason.toString() : '';
|
||||||
|
} else if (typeof reason === 'string') {
|
||||||
|
reasonMsg = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe?.contentWindow?.postMessage({
|
iframe?.contentWindow?.postMessage({
|
||||||
|
|
|
@ -14,24 +14,6 @@
|
||||||
"x":0,
|
"x":0,
|
||||||
"y":0
|
"y":0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
||||||
"height":10,
|
|
||||||
"id":6,
|
|
||||||
"name":"triggerZone",
|
|
||||||
"opacity":1,
|
|
||||||
"properties":[
|
|
||||||
{
|
|
||||||
"name":"zone",
|
|
||||||
"type":"string",
|
|
||||||
"value":"myTrigger"
|
|
||||||
}],
|
|
||||||
"type":"tilelayer",
|
|
||||||
"visible":true,
|
|
||||||
"width":10,
|
|
||||||
"x":0,
|
|
||||||
"y":0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
"height":10,
|
"height":10,
|
||||||
|
@ -58,7 +40,7 @@
|
||||||
{
|
{
|
||||||
"fontfamily":"Sans Serif",
|
"fontfamily":"Sans Serif",
|
||||||
"pixelsize":11,
|
"pixelsize":11,
|
||||||
"text":"Test:\nTODO",
|
"text":"Test:\nOpen your console\n\nResult:\nYou should see a list of tests performed and results associated.",
|
||||||
"wrap":true
|
"wrap":true
|
||||||
},
|
},
|
||||||
"type":"",
|
"type":"",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue