mirror of
https://github.com/Rolands-Laucis/Socio.git
synced 2026-05-15 14:15:57 -06:00
all switch statements safer case scopes
This commit is contained in:
parent
8b15ad56b2
commit
e54e358cef
5 changed files with 108 additions and 78 deletions
|
|
@ -36,8 +36,8 @@ export class AdminClient extends LogHandler{
|
|||
const { kind, data }: { kind: ClientMessageKind; data: MessageDataObj } = JSON.parse(d, MapReviver)
|
||||
|
||||
switch(kind){
|
||||
case 'CON':
|
||||
//@ts-ignore
|
||||
case 'CON':{
|
||||
//@ts-expect-error
|
||||
this.#client_id = data;//should just be a string
|
||||
if (this.#is_ready !== false && typeof this.#is_ready === "function")
|
||||
this.#is_ready(true); //resolve promise to true
|
||||
|
|
@ -45,14 +45,17 @@ export class AdminClient extends LogHandler{
|
|||
|
||||
this.#is_ready = true;
|
||||
break;
|
||||
case 'RES':
|
||||
}
|
||||
case 'RES':{
|
||||
this.HandleInfo('recv:', kind, data);
|
||||
this.#HandleBasicPromiseMessage(data);
|
||||
break;
|
||||
case 'ERR':
|
||||
}
|
||||
case 'ERR':{
|
||||
this.HandleError(new E('recv:', kind, data));
|
||||
this.#HandleBasicPromiseMessage(data);
|
||||
break;
|
||||
}
|
||||
default: throw new E(`Unrecognized message kind!`, kind, data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
core/chat.ts
10
core/chat.ts
|
|
@ -80,9 +80,9 @@ export function HandleChatRoomServ(client: SocioSession, data: MessageDataObj, c
|
|||
const chat = chat_rooms.find(c => c.room_id === data.data?.room_id);
|
||||
if(!chat) return;
|
||||
switch(data.data?.type){
|
||||
case 'join': chat.Join(client.id); break;
|
||||
case 'leave': chat.Leave(client.id); break;
|
||||
case 'new_msg': chat.Post(client.id, data.data?.text); break;
|
||||
case 'join': {chat.Join(client.id); break;}
|
||||
case 'leave': {chat.Leave(client.id); break;}
|
||||
case 'new_msg': {chat.Post(client.id, data.data?.text); break;}
|
||||
default: throw new E('Unknown SocioChatRoom SERV msg type!');
|
||||
}
|
||||
}
|
||||
|
|
@ -91,8 +91,8 @@ export function HandleChatRoomServ(client: SocioSession, data: MessageDataObj, c
|
|||
export function HandleChatRoomCMD(data:any, chat:ChatRoomClient) {
|
||||
if (data?.rel == 'SocioChatRoom') {
|
||||
switch (data?.type) {
|
||||
case 'msg_history': chat.Receive(data?.msgs); break;
|
||||
case 'new_msg': chat.Receive(data?.msgs); break;
|
||||
case 'msg_history': {chat.Receive(data?.msgs); break;}
|
||||
case 'new_msg': {chat.Receive(data?.msgs); break;}
|
||||
default: throw new E('Unknown SocioChatRoom CMD msg type!');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export class SocioClient extends LogHandler {
|
|||
return;
|
||||
|
||||
switch (kind) {
|
||||
case 'CON':
|
||||
case 'CON':{
|
||||
//@ts-expect-error
|
||||
this.#client_id = data as string;//should just be a string
|
||||
this.#latency = (new Date()).getTime() - this.#latency;
|
||||
|
|
@ -118,15 +118,18 @@ export class SocioClient extends LogHandler {
|
|||
|
||||
this.#is_ready = true;
|
||||
break;
|
||||
case 'UPD':
|
||||
}
|
||||
case 'UPD':{
|
||||
this.#FindID(kind, data?.id);
|
||||
(this.#queries.get(data.id) as QueryObject).onUpdate[data.status as string](data.result); //status might be success or error, and error might not be defined
|
||||
break;
|
||||
case 'PONG':
|
||||
this.#FindID(kind, data?.id)
|
||||
this.HandleInfo('pong', data?.id);
|
||||
}
|
||||
case 'PONG':{
|
||||
this.#FindID(kind, data?.id)
|
||||
this.HandleInfo('pong', data?.id);
|
||||
break;
|
||||
case 'AUTH':
|
||||
}
|
||||
case 'AUTH':{
|
||||
this.#FindID(kind, data?.id)
|
||||
if (data?.result as Bit !== 1)
|
||||
this.HandleInfo(`AUTH returned FALSE, which means websocket has not authenticated.`);
|
||||
|
|
@ -135,60 +138,67 @@ export class SocioClient extends LogHandler {
|
|||
(this.#queries.get(data.id) as QueryPromise).res(this.#authenticated); //result should be either True or False to indicate success status
|
||||
this.#queries.delete(data.id); //clear memory
|
||||
break;
|
||||
case 'GET_PERM':
|
||||
}
|
||||
case 'GET_PERM':{
|
||||
this.#FindID(kind, data?.id)
|
||||
if (data?.result as Bit !== 1)
|
||||
if (data?.result as Bit !== 1)
|
||||
this.HandleInfo(`Server rejected grant perm for ${data?.verb} on ${data?.table}.`);
|
||||
|
||||
(this.#queries.get(data.id) as QueryPromise).res(data?.result as Bit === 1); //result should be either True or False to indicate success status
|
||||
this.#queries.delete(data.id) //clear memory
|
||||
break;
|
||||
case 'RES':
|
||||
}
|
||||
case 'RES':{
|
||||
this.#HandleBasicPromiseMessage(kind, data)
|
||||
break;
|
||||
case 'PROP_UPD':
|
||||
if (data?.prop && data.hasOwnProperty('id') && (data.hasOwnProperty('prop_val') || data.hasOwnProperty('prop_val_diff'))){
|
||||
}
|
||||
case 'PROP_UPD':{
|
||||
if (data?.prop && data.hasOwnProperty('id') && (data.hasOwnProperty('prop_val') || data.hasOwnProperty('prop_val_diff'))) {
|
||||
const prop = this.#props.get(data.prop as string);
|
||||
if (prop && prop.subs.hasOwnProperty(data.id as id) && typeof prop.subs[data.id as id] === 'function'){
|
||||
if (prop && prop.subs.hasOwnProperty(data.id as id) && typeof prop.subs[data.id as id] === 'function') {
|
||||
const prop_val = data.hasOwnProperty('prop_val') ? data.prop_val : diff_lib.applyDiff(prop.val, data.prop_val_diff);
|
||||
//@ts-expect-error
|
||||
prop.subs[data.id as id](prop_val as PropValue);
|
||||
prop.val = prop_val; //set the new val
|
||||
}//@ts-expect-error
|
||||
else throw new E('Prop UPD called, but subscribed prop does not have a callback.', { data, callback: prop.subs[data.id as id]});
|
||||
else throw new E('Prop UPD called, but subscribed prop does not have a callback.', { data, callback: prop.subs[data.id as id] });
|
||||
if (this.#queries.has(data.id))
|
||||
(this.#queries.get(data.id) as QueryPromise).res(data.prop_val as PropValue); //resolve the promise
|
||||
}else throw new E('Not enough prop info sent from server to perform prop update.', data)
|
||||
} else throw new E('Not enough prop info sent from server to perform prop update.', data)
|
||||
break;
|
||||
case 'PROP_DROP':
|
||||
}
|
||||
case 'PROP_DROP':{
|
||||
if (data?.prop && data.hasOwnProperty('id')) {
|
||||
if (this.#props.has(data.prop)){
|
||||
if (this.#props.has(data.prop)) {
|
||||
delete this.#props.get(data.prop)?.subs[data.id];
|
||||
|
||||
//tell the dev that this prop has been dropped by the server.
|
||||
if(this.lifecycle_hooks.prop_drop)
|
||||
if (this.lifecycle_hooks.prop_drop)
|
||||
this.lifecycle_hooks.prop_drop(this.name, this.#client_id, data.prop, data.id);
|
||||
}
|
||||
else throw new E('Cant drop unsubbed prop!', data)
|
||||
} else throw new E('Not enough prop info sent from server to perform prop drop.', data)
|
||||
break;
|
||||
case 'CMD': if(this.lifecycle_hooks.cmd) this.lifecycle_hooks.cmd(data); break; //the server pushed some data to this client, let the dev handle it
|
||||
case 'ERR'://The result field is sometimes used as a cause of error msg on the backend
|
||||
}
|
||||
case 'CMD': {if(this.lifecycle_hooks.cmd) this.lifecycle_hooks.cmd(data); break;} //the server pushed some data to this client, let the dev handle it
|
||||
case 'ERR': {//The result field is sometimes used as a cause of error msg on the backend
|
||||
if (typeof this.#queries.get(data.id) == 'function')
|
||||
(this.#queries.get(data.id) as QueryPromise).res();
|
||||
|
||||
this.HandleError(new E(`Request to Server returned ERROR response. [#err-msg-kind]`, { id:data?.id, reason:data?.result }));
|
||||
this.HandleError(new E(`Request to Server returned ERROR response. [#err-msg-kind]`, { id: data?.id, reason: data?.result }));
|
||||
break;
|
||||
case 'RECON':
|
||||
}
|
||||
case 'RECON':{
|
||||
this.#FindID(kind, data?.id);
|
||||
//@ts-expect-error
|
||||
this.#queries.get(data.id)(data);
|
||||
this.#queries.delete(data.id); //clear memory
|
||||
break;
|
||||
case 'RECV_FILES':
|
||||
}
|
||||
case 'RECV_FILES':{
|
||||
this.#FindID(kind, data?.id);
|
||||
|
||||
if (data?.result && data?.files){
|
||||
|
||||
if (data?.result && data?.files) {
|
||||
const files = ParseSocioFiles(data?.files as SocioFiles);
|
||||
//@ts-expect-error
|
||||
this.#queries.get(data.id)(files);
|
||||
|
|
@ -200,11 +210,13 @@ export class SocioClient extends LogHandler {
|
|||
|
||||
this.#queries.delete(data.id); //clear memory
|
||||
break;
|
||||
case 'TIMEOUT':
|
||||
}
|
||||
case 'TIMEOUT':{
|
||||
if (this.lifecycle_hooks.timeout)
|
||||
this.lifecycle_hooks.timeout(this.name, this.#client_id);
|
||||
break;
|
||||
// case '': break;
|
||||
}
|
||||
// case '': {break;}
|
||||
default: throw new E(`Unrecognized message kind!`, {kind, data});
|
||||
}
|
||||
} catch (e:err) { this.HandleError(e) }
|
||||
|
|
|
|||
99
core/core.ts
99
core/core.ts
|
|
@ -172,19 +172,19 @@ export class SocioServer extends LogHandler {
|
|||
return;
|
||||
|
||||
switch (kind) {
|
||||
case 'SUB':
|
||||
case 'SUB':{
|
||||
if (this.#lifecycle_hooks.sub)
|
||||
if (await this.#lifecycle_hooks.sub(client, kind, data))
|
||||
return;
|
||||
|
||||
//if the client happens to want to use an endpoint keyname instead of SQL, retrieve the SQL string from a hook call and procede with that.
|
||||
if (data.endpoint && !data.sql){
|
||||
if (data.endpoint && !data.sql) {
|
||||
if (this.#lifecycle_hooks.endpoint)
|
||||
data.sql = await this.#lifecycle_hooks.endpoint(client, data.endpoint);
|
||||
else throw new E('Client sent endpoint instead of SQL, but its hook is missing. [#no-endpoint-hook-SUB]');
|
||||
}
|
||||
|
||||
if(data.sql){
|
||||
if (data.sql) {
|
||||
if (QueryIsSelect(data.sql || '')) {
|
||||
//set up hook
|
||||
const tables = ParseQueryTables(data.sql || '');
|
||||
|
|
@ -198,24 +198,26 @@ export class SocioServer extends LogHandler {
|
|||
status: 'success'
|
||||
});
|
||||
} else client.Send('ERR', {
|
||||
id: data.id,
|
||||
result: 'Only SELECT queries may be subscribed to! [#reg-not-select]',
|
||||
status: 'error'
|
||||
});
|
||||
id: data.id,
|
||||
result: 'Only SELECT queries may be subscribed to! [#reg-not-select]',
|
||||
status: 'error'
|
||||
});
|
||||
} else client.Send('ERR', {
|
||||
id: data.id,
|
||||
result: 'Nothing to subscribed to! [#reg-no-res]',
|
||||
status: 'error'
|
||||
});
|
||||
break;
|
||||
case 'UNSUB':
|
||||
}
|
||||
case 'UNSUB':{
|
||||
if (this.#lifecycle_hooks.unsub)
|
||||
if (await this.#lifecycle_hooks.unsub(client, kind, data))
|
||||
return;
|
||||
|
||||
client.Send('RES', { id: data.id, result: client.UnRegisterSub(data?.unreg_id || '') });
|
||||
break;
|
||||
case 'SQL':
|
||||
}
|
||||
case 'SQL':{
|
||||
//if the client happens to want to use an endpoint keyname instead of SQL, retrieve the SQL string from a hook call and procede with that.
|
||||
if (data?.sql_is_endpoint && data.sql) {
|
||||
if (this.#lifecycle_hooks.endpoint)
|
||||
|
|
@ -229,27 +231,30 @@ export class SocioServer extends LogHandler {
|
|||
//if the sql wasnt a SELECT, but altered some resource, then need to propogate that to other connection hooks
|
||||
if (!QueryIsSelect(data.sql || ''))
|
||||
this.Update(client, data.sql || '', data?.params);
|
||||
|
||||
|
||||
break;
|
||||
case 'PING':
|
||||
client.Send('PONG', { id: data?.id });
|
||||
}
|
||||
case 'PING':{
|
||||
client.Send('PONG', { id: data?.id });
|
||||
break;
|
||||
case 'AUTH'://client requests to authenticate itself with the server
|
||||
}
|
||||
case 'AUTH': {//client requests to authenticate itself with the server
|
||||
if (client.authenticated) //check if already has auth
|
||||
client.Send('AUTH', { id: data.id, result: 1 });
|
||||
else if (this.#lifecycle_hooks.auth){
|
||||
else if (this.#lifecycle_hooks.auth) {
|
||||
const res = await client.Authenticate(this.#lifecycle_hooks.auth, data.params) //bcs its a private class field, give this function the hook to call and params to it. It will set its field and give back the result. NOTE this is safer than adding a setter to a private field
|
||||
client.Send('AUTH', { id: data.id, result: res == true ? 1 : 0 }) //authenticated can be any truthy or falsy value, but the client will only receive a boolean, so its safe to set this to like an ID or token or smth for your own use
|
||||
}else{
|
||||
} else {
|
||||
this.HandleError('AUTH function hook not registered, so client not authenticated. [#no-auth-func]')
|
||||
client.Send('AUTH', { id: data.id, result: 0 })
|
||||
}
|
||||
break;
|
||||
case 'GET_PERM':
|
||||
}
|
||||
case 'GET_PERM':{
|
||||
if (client.HasPermFor(data?.verb, data?.table))//check if already has the perm
|
||||
client.Send('GET_PERM', { id: data.id, result: 1 });
|
||||
else if (this.#lifecycle_hooks.grant_perm) {//otherwise try to grant the perm
|
||||
const granted:boolean = await this.#lifecycle_hooks.grant_perm(client, data);
|
||||
const granted: boolean = await this.#lifecycle_hooks.grant_perm(client, data);
|
||||
client.Send('GET_PERM', { id: data.id, result: granted === true ? 1 : 0 }) //the client will only receive a boolean, but still make sure to only return bools as well
|
||||
}
|
||||
else {
|
||||
|
|
@ -257,13 +262,14 @@ export class SocioServer extends LogHandler {
|
|||
client.Send('GET_PERM', { id: data.id, result: 0 })
|
||||
}
|
||||
break;
|
||||
case 'PROP_SUB':
|
||||
}
|
||||
case 'PROP_SUB':{
|
||||
this.#CheckPropExists(data?.prop, client, data.id as id, 'Prop key does not exist on the backend! [#prop-reg-not-found]')
|
||||
|
||||
|
||||
if (this.#lifecycle_hooks.sub)
|
||||
if (await this.#lifecycle_hooks.sub(client, kind, data))
|
||||
return;
|
||||
|
||||
|
||||
//set up hook
|
||||
this.#props.get(data.prop as PropKey)?.updates.set(client_id, { id: data.id as id, rate_limiter: data?.rate_limit ? new RateLimiter(data.rate_limit) : undefined })
|
||||
|
||||
|
|
@ -274,15 +280,16 @@ export class SocioServer extends LogHandler {
|
|||
prop_val: this.GetPropVal(data.prop as PropKey)
|
||||
})
|
||||
break;
|
||||
case 'PROP_UNSUB':
|
||||
}
|
||||
case 'PROP_UNSUB':{
|
||||
this.#CheckPropExists(data?.prop, client, data?.id as id, 'Prop key does not exist on the backend! [#prop-reg-not-found]')
|
||||
|
||||
|
||||
if (this.#lifecycle_hooks.unsub)
|
||||
if (await this.#lifecycle_hooks.unsub(client, kind, data))
|
||||
return;
|
||||
|
||||
//remove hook
|
||||
try{
|
||||
try {
|
||||
client.Send('RES', {
|
||||
id: data?.id,
|
||||
result: this.#props.get(data.prop as PropKey)?.updates.delete(client_id) ? 1 : 0
|
||||
|
|
@ -296,21 +303,23 @@ export class SocioServer extends LogHandler {
|
|||
throw e; //report on the server as well
|
||||
}
|
||||
break;
|
||||
case 'PROP_GET':
|
||||
}
|
||||
case 'PROP_GET':{
|
||||
this.#CheckPropExists(data?.prop, client, data.id as id, 'Prop key does not exist on the backend! [#prop-reg-not-found]')
|
||||
client.Send('RES', {
|
||||
id: data.id,
|
||||
result: this.GetPropVal(data.prop as string)
|
||||
})
|
||||
break;
|
||||
case 'PROP_SET':
|
||||
}
|
||||
case 'PROP_SET':{
|
||||
this.#CheckPropExists(data?.prop, client, data.id as id, 'Prop key does not exist on the backend! [#prop-reg-not-found]')
|
||||
try {
|
||||
if(this.#props.get(data.prop as string)?.client_writable){
|
||||
if (this.#props.get(data.prop as string)?.client_writable) {
|
||||
//UpdatePropVal does not set the new val, rather it calls the assigner, which is responsible for setting the new value.
|
||||
const result = this.UpdatePropVal(data.prop as string, data?.prop_val, client.id, data.hasOwnProperty('prop_upd_as_diff') ? data.prop_upd_as_diff : this.#prop_upd_diff); //the assigner inside Update dictates, if this was a successful set.
|
||||
client.Send('RES', { id: data.id, result }); //resolve this request to true, so the client knows everything went fine.
|
||||
}else throw new E('Prop is not client_writable.', data);
|
||||
} else throw new E('Prop is not client_writable.', data);
|
||||
} catch (e: err) {
|
||||
//send response
|
||||
client.Send('ERR', {
|
||||
|
|
@ -320,30 +329,33 @@ export class SocioServer extends LogHandler {
|
|||
throw e; //report on the server as well
|
||||
}
|
||||
break;
|
||||
case 'SERV':
|
||||
}
|
||||
case 'SERV':{
|
||||
if (this.#lifecycle_hooks.serv)
|
||||
await this.#lifecycle_hooks.serv(client, data);
|
||||
else throw new E('Client sent generic data to the server, but the hook for it is not registed. [#no-serv-hook]', client_id);
|
||||
break;
|
||||
case 'ADMIN':
|
||||
if(this.#lifecycle_hooks.admin)
|
||||
}
|
||||
case 'ADMIN':{
|
||||
if (this.#lifecycle_hooks.admin)
|
||||
if (await this.#lifecycle_hooks.admin(client, data)) //you get the client, which has its ID, ipAddr and last_seen fields, that can be used to verify access. Also data should contain some secret key, but thats up to you
|
||||
client.Send('RES', { id: data?.id, result: await this.#Admin(((data as unknown) as AdminMessageDataObj)?.function, ((data as unknown) as AdminMessageDataObj)?.args) });
|
||||
else throw new E('A non Admin send an Admin message, but was not executed.', kind, data, client_id);
|
||||
break;
|
||||
case 'RECON': //client attempts to reconnect to its previous session
|
||||
if(!this.#secure){
|
||||
}
|
||||
case 'RECON': {//client attempts to reconnect to its previous session
|
||||
if (!this.#secure) {
|
||||
client.Send('ERR', { id: data.id, result: 'Cannot reconnect on this server configuration!', status: 0 });
|
||||
throw new E(`RECON requires SocioServer to be set up with the Secure class! [#recon-needs-secure]`, {kind, data});
|
||||
throw new E(`RECON requires SocioServer to be set up with the Secure class! [#recon-needs-secure]`, { kind, data });
|
||||
}
|
||||
|
||||
if (data?.data?.type == 'GET'){
|
||||
if (data?.data?.type == 'GET') {
|
||||
//@ts-expect-error
|
||||
const token = this.#secure.socio_security.EncryptString([this.#secure.socio_security?.GenRandInt(100_000, 1_000_000), client.ipAddr, client.id, (new Date()).getTime(), this.#secure.socio_security?.GenRandInt(100_000, 1_000_000)].join(' ')); //creates string in the format "[iv_base64] [encrypted_text_base64] [auth_tag_base64]" where encrypted_text_base64 is a token of format "[rand] [ip] [client_id] [ms_since_epoch] [rand]"
|
||||
this.#tokens.add(token);
|
||||
client.Send('RES', { id: data.id, result: token, status: 1 }); //send the token to the client for one-time use to reconnect to their established client session
|
||||
}
|
||||
else if (data?.data?.type == 'POST'){
|
||||
else if (data?.data?.type == 'POST') {
|
||||
//check for valid token to begin with
|
||||
if (!data?.data?.token || !this.#tokens.has(data.data.token)) {
|
||||
client.Send('RECON', { id: data.id, result: 'Invalid token', status: 0 });
|
||||
|
|
@ -364,7 +376,7 @@ export class SocioServer extends LogHandler {
|
|||
|
||||
const [r1, ip, old_c_id, time_stamp, r2] = token.split(' '); //decrypted payload parts
|
||||
//safety check race conditions
|
||||
if (!(r1 && ip && old_c_id && time_stamp && r2)){
|
||||
if (!(r1 && ip && old_c_id && time_stamp && r2)) {
|
||||
client.Send('RECON', { id: data.id, result: 'Invalid token format', status: 0 });
|
||||
return;
|
||||
}
|
||||
|
|
@ -372,7 +384,7 @@ export class SocioServer extends LogHandler {
|
|||
client.Send('RECON', { id: data.id, result: 'IP address changed between reconnect', status: 0 });
|
||||
return;
|
||||
}
|
||||
else if ((new Date()).getTime() - parseInt(time_stamp) > (this.session_defaults.recon_ttl_ms as number)){
|
||||
else if ((new Date()).getTime() - parseInt(time_stamp) > (this.session_defaults.recon_ttl_ms as number)) {
|
||||
client.Send('RECON', { id: data.id, result: 'Token has expired', status: 0 });
|
||||
return;
|
||||
}
|
||||
|
|
@ -401,16 +413,18 @@ export class SocioServer extends LogHandler {
|
|||
this.HandleInfo(`RECON ${old_c_id} -> ${client.id} (old client ID -> new/current client ID)`);
|
||||
}
|
||||
break;
|
||||
case 'UP_FILES':
|
||||
}
|
||||
case 'UP_FILES':{
|
||||
if (this.#lifecycle_hooks?.file_upload)
|
||||
client.Send('RES', { id: data.id, result: await this.#lifecycle_hooks.file_upload(client, data?.files, data?.data) ? 1 : 0 });
|
||||
else{
|
||||
else {
|
||||
this.HandleError('file_upload hook not registered. [#no-file_upload-hook]');
|
||||
client.Send('RES', { id: data.id, result: 0 });
|
||||
}
|
||||
break;
|
||||
case 'GET_FILES':
|
||||
if (this.#lifecycle_hooks?.file_download){
|
||||
}
|
||||
case 'GET_FILES':{
|
||||
if (this.#lifecycle_hooks?.file_download) {
|
||||
const response = await this.#lifecycle_hooks.file_download(client, data?.data) as FS_Util_Response;
|
||||
if (!response?.result)
|
||||
this.HandleError(new E('file_download hook returned unsuccessful result.', response?.error));
|
||||
|
|
@ -421,7 +435,8 @@ export class SocioServer extends LogHandler {
|
|||
client.Send('RES', { id: data.id, result: 0 });
|
||||
}
|
||||
break;
|
||||
// case '': break;
|
||||
}
|
||||
// case '': {break;}
|
||||
default: throw new E(`Unrecognized message kind! [#unknown-msg-kind]`, {kind, data});
|
||||
}
|
||||
} catch (e: err) { this.HandleError(e); }
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
"noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
"noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue