diff --git a/src/base/BasePayload.ts b/src/base/BasePayload.ts new file mode 100644 index 0000000..ae29937 --- /dev/null +++ b/src/base/BasePayload.ts @@ -0,0 +1,8 @@ +export interface BaseRequestPayload { + +} + +export interface BaseResponsePayload { + name?:string, + error?:Error, +} \ No newline at end of file diff --git a/src/event/actionsGenerator.ts b/src/event/actionsGenerator.ts new file mode 100644 index 0000000..77c0b59 --- /dev/null +++ b/src/event/actionsGenerator.ts @@ -0,0 +1,54 @@ +import solace from 'solclientjs/lib-browser/solclient'; + +import { IEventActionDict } from './types' + +import makeType from '../utils/makeType'; +import createFSA from '../utils/createFSA'; + +export default ():IEventActionDict=>{ + + const result = { + // basic session event + [solace.SessionEventCode.UP_NOTICE]:{actionType:makeType('UP_NOTICE')}, + [solace.SessionEventCode.CONNECT_FAILED_ERROR]:{actionType:makeType('CONNECT_FAILED_ERROR')}, + [solace.SessionEventCode.DISCONNECTED]:{actionType:makeType('DISCONNECTED')}, + [solace.SessionEventCode.SUBSCRIPTION_ERROR]:{actionType:makeType('SUBSCRIPTION_ERROR')}, + [solace.SessionEventCode.SUBSCRIPTION_OK]:{actionType:makeType('SUBSCRIPTION_OK')}, + [solace.SessionEventCode.MESSAGE]:{actionType:makeType('MESSAGE')}, + + // additional session event + [solace.SessionEventCode.ACKNOWLEDGED_MESSAGE]:{actionType:makeType('ACKNOWLEDGED_MESSAGE')}, + [solace.SessionEventCode.CAN_ACCEPT_DATA]:{actionType:makeType('CAN_ACCEPT_DATA')}, + [solace.SessionEventCode.DOWN_ERROR]:{actionType:makeType('DOWN_ERROR')}, + [solace.SessionEventCode.GUARANTEED_MESSAGE_PUBLISHER_DOWN]:{actionType:makeType('GUARANTEED_MESSAGE_PUBLISHER_DOWN')}, + [solace.SessionEventCode.PROPERTY_UPDATE_ERROR]:{actionType:makeType('PROPERTY_UPDATE_ERROR')}, + [solace.SessionEventCode.PROPERTY_UPDATE_OK]:{actionType:makeType('PROPERTY_UPDATE_OK')}, + [solace.SessionEventCode.RECONNECTED_NOTICE]:{actionType:makeType('RECONNECTED_NOTICE')}, + [solace.SessionEventCode.RECONNECTING_NOTICE]:{actionType:makeType('RECONNECTING_NOTICE')}, + [solace.SessionEventCode.REJECTED_MESSAGE_ERROR]:{actionType:makeType('REJECTED_MESSAGE_ERROR')}, + [solace.SessionEventCode.REPUBLISHING_UNACKED_MESSAGES]:{actionType:makeType('REPUBLISHING_UNACKED_MESSAGES')}, + [solace.SessionEventCode.UNSUBSCRIBE_TE_TOPIC_ERROR]:{actionType:makeType('UNSUBSCRIBE_TE_TOPIC_ERROR')}, + [solace.SessionEventCode.UNSUBSCRIBE_TE_TOPIC_OK]:{actionType:makeType('UNSUBSCRIBE_TE_TOPIC_OK')}, + [solace.SessionEventCode.VIRTUALROUTER_NAME_CHANGED]:{actionType:makeType('VIRTUALROUTER_NAME_CHANGED')}, + + // consumer event + [solace.MessageConsumerEventName.ACTIVE]:{actionType:makeType('CONSUMER_ACTIVE')}, + [solace.MessageConsumerEventName.CONNECT_FAILED_ERROR]:{actionType:makeType('CONSUMER_CONNECT_FAILED_ERROR')}, + [solace.MessageConsumerEventName.DISPOSED]:{actionType:makeType('CONSUMER_DISPOSED')}, + [solace.MessageConsumerEventName.DOWN]:{actionType:makeType('CONSUMER_DOWN')}, + [solace.MessageConsumerEventName.DOWN_ERROR]:{actionType:makeType('CONSUMER_DOWN_ERROR')}, + [solace.MessageConsumerEventName.GM_DISABLED]:{actionType:makeType('CONSUMER_GM_DISABLED')}, + [solace.MessageConsumerEventName.INACTIVE]:{actionType:makeType('CONSUMER_INACTIVE')}, + [solace.MessageConsumerEventName.MESSAGE]:{actionType:makeType('CONSUMER_MESSAGE')}, + [solace.MessageConsumerEventName.UP]:{actionType:makeType('CONSUMER_UP')}, + }; + + Object.keys(result).forEach((eventCode)=>{ + result[eventCode].action = createFSA( + result[eventCode].actionType, + options => (options) + ) + }); + + return result as IEventActionDict; +} \ No newline at end of file diff --git a/src/event/index.ts b/src/event/index.ts new file mode 100644 index 0000000..d7631d9 --- /dev/null +++ b/src/event/index.ts @@ -0,0 +1,5 @@ +import actionsGenerator from './actionsGenerator'; + +export default { + actionsDict:actionsGenerator(), +} \ No newline at end of file diff --git a/src/event/types.ts b/src/event/types.ts new file mode 100644 index 0000000..70bc525 --- /dev/null +++ b/src/event/types.ts @@ -0,0 +1,10 @@ +export interface IEventActionDict { + [key:string]:{ + actionType:string, + action:(options:any)=>any + }, + [key:number]:{ + actionType:string, + action:(options:any)=>any + }, +} \ No newline at end of file diff --git a/src/init.ts b/src/init.ts index a64c99e..504d3ac 100644 --- a/src/init.ts +++ b/src/init.ts @@ -1,4 +1,5 @@ import {Store } from 'redux'; +import {Action} from 'redux-actions'; import solace from 'solclientjs/lib-browser/solclient'; import SolaceContext from './utils/SolaceContext'; @@ -20,6 +21,13 @@ export const initState:IInitState = { window.solace = solace; window.solaceContext = initState.solaceContext; +export function dispatchAction( action: Action ) { + if (initState.store){ + const { dispatch } = initState.store; + dispatch(action); + } +} + function init(store?:Store) { if (store){ initState.store = store; diff --git a/src/session/actions.constant.ts b/src/session/actions.constant.ts new file mode 100644 index 0000000..d5d9e88 --- /dev/null +++ b/src/session/actions.constant.ts @@ -0,0 +1,16 @@ +import makeType from '../utils/makeType'; + +export const CREATE_AND_CONNECT_SESSION = makeType('CREATE_AND_CONNECT_SESSION'); +export const CREATE_AND_CONNECT_SESSION_RES = makeType('CREATE_AND_CONNECT_SESSION_RES'); + +export const DISCONNECT_AND_REMOVE_ONE_SESSION = makeType('DISCONNECT_AND_REMOVE_ONE_SESSION'); +export const DISCONNECT_AND_REMOVE_ONE_SESSION_RES = makeType('DISCONNECT_AND_REMOVE_ONE_SESSION_RES'); + +export const CLOSE_AND_REMOVE_ALL_SESSIONS = makeType('CLOSE_AND_REMOVE_ALL_SESSIONS'); +export const CLOSE_AND_REMOVE_ALL_SESSIONS_RES = makeType('CLOSE_AND_REMOVE_ALL_SESSIONS_RES'); + +export const SEND_CACHE_REQUEST_OF_ONE_SESSION = makeType('SEND_CACHE_REQUEST_OF_ONE_SESSION'); +export const SEND_CACHE_REQUEST_OF_ONE_SESSION_RES = makeType('SEND_CACHE_REQUEST_OF_ONE_SESSION_RES'); + +export const SOLACE_CONTEXT_CHANGED = makeType('SOLACE_CONTEXT_CHANGED'); + diff --git a/src/session/actions.ts b/src/session/actions.ts new file mode 100644 index 0000000..a4cdf18 --- /dev/null +++ b/src/session/actions.ts @@ -0,0 +1,29 @@ +import { Action } from 'redux-actions'; +import createFSA, { ActionCreator } from '../utils/createFSA'; + +import * as types from './types'; +import * as actionTypes from './actions.constant'; + +export const createAndConnectSession:ActionCreator = + createFSA( + actionTypes.CREATE_AND_CONNECT_SESSION, + (options:types.ICreateAndConnectSessionPayload) => options + ); + +export const disconnectAndRemoveOneSession:ActionCreator = + createFSA( + actionTypes.DISCONNECT_AND_REMOVE_ONE_SESSION, + (options:types.IDisconnectAndRemoveOneSessionPayload) => options + ); + +export const closeAndRemoveAllSessions:ActionCreator = + createFSA( + actionTypes.CLOSE_AND_REMOVE_ALL_SESSIONS, + (options:types.ICloseAndRemoveAllSessionsPayload) => options + ); + +export const sendCacheRequestOfOneSession:ActionCreator = + createFSA( + actionTypes.SEND_CACHE_REQUEST_OF_ONE_SESSION, + (options:types.ISendCacheRequestOfOneSessionPayload) => options + ); \ No newline at end of file diff --git a/src/session/async.ts b/src/session/async.ts new file mode 100644 index 0000000..6d1578c --- /dev/null +++ b/src/session/async.ts @@ -0,0 +1,63 @@ +import {Action} from 'redux-actions'; + +import { initState, dispatchAction } from '../init'; +import { SessionContext } from '../utils/SolaceContext'; +import msgBuilder, {IMsgBuilt} from '../utils/msgBuilder'; + +import SolaceEvents from '../event'; + +import * as types from "./types"; +import * as handlerActions from './handlerActions'; + +const CREATE_SESSION_ERR_MSG='[redux-solace] Failed to create solace session'; +const CLOSE_SESSION_ERR_MSG='[redux-solace] Failed to close one solace session'; +const CLOSE_ALL_SESSION_ERR_MSG='[redux-solace] Failed to close all solace session'; +const SEND_CACHE_REQUEST_OF_ONE_SESSION_ERR_MSG='[redux-solace] Failed to send cache request of one session'; + +export async function createAndConnectSession(action:Action) + :Promise> +{ + const { + hostUrl, vpn, username, sessionCache, pass, config + } = action.payload; + + let newSessionContext:SessionContext = null; + try{ + newSessionContext = initState.solaceContext.createAndConnectSession( + hostUrl,username,pass, vpn, sessionCache, {}, config + ); + }catch (e) { + console.error(e.message) + dispatchAction(handlerActions.createAndConnectSessionRes({ + name:CREATE_SESSION_ERR_MSG, + error:e, + })); + }finally { + dispatchAction(handlerActions.solaceContextChanged(initState.solaceContext.getContextPayload())) + } + + if(newSessionContext){ + const sessionId = newSessionContext.id; + const solaceSessionEventDict = SolaceEvents.actionsDict; + const responseAction = handlerActions.createAndConnectSessionRes({result:newSessionContext}); + Object.keys(solaceSessionEventDict).forEach(oneEvtCode => { + if (oneEvtCode === initState.solace.SessionEventCode.MESSAGE){ + initState.solaceContext.addOneToEventHookOfOneSession(sessionId,oneEvtCode,(sessionEvent)=>{ + const msgBuilt:IMsgBuilt = msgBuilder(sessionEvent); + dispatchAction(solaceSessionEventDict[oneEvtCode].action({ + sessionId, ...msgBuilt, + })); + }) + + }else{ + initState.solaceContext.addOneToEventHookOfOneSession(sessionId,oneEvtCode,(sessionEvent)=>{ + dispatchAction(solaceSessionEventDict[oneEvtCode].action({sessionId,sessionEvent})); + }) + } + }); + dispatchAction(responseAction); + return responseAction; + }else{ + throw CREATE_SESSION_ERR_MSG; + } +} \ No newline at end of file diff --git a/src/session/handlerActions.ts b/src/session/handlerActions.ts new file mode 100644 index 0000000..4ed0b3a --- /dev/null +++ b/src/session/handlerActions.ts @@ -0,0 +1,35 @@ +import { Action } from 'redux-actions'; +import createFSA, { ActionCreator } from '../utils/createFSA'; + +import * as types from './types'; +import * as actionTypes from './actions.constant'; + +export const createAndConnectSessionRes:ActionCreator = + createFSA( + actionTypes.CREATE_AND_CONNECT_SESSION_RES, + (options:types.ICreateAndConnectSessionResPayload) => options + ); + +export const disconnectAndRemoveOneSessionRes:ActionCreator = + createFSA( + actionTypes.DISCONNECT_AND_REMOVE_ONE_SESSION_RES, + (options:types.IDisconnectAndRemoveOneSessionResPayload) => options + ); + +export const closeAndRemoveAllSessionRes:ActionCreator = + createFSA( + actionTypes.CLOSE_AND_REMOVE_ALL_SESSIONS_RES, + (options:types.ICloseAndRemoveAllSessionsResPayload) => options + ); + +export const sendCacheRequestOfOneSessionRes:ActionCreator = + createFSA( + actionTypes.SEND_CACHE_REQUEST_OF_ONE_SESSION_RES, + (options:types.ISendCacheRequestOfOneSessionResPayload) => options + ); + +export const solaceContextChanged:ActionCreator = + createFSA( + actionTypes.SOLACE_CONTEXT_CHANGED, + (options:types.ISolaceContextChangedEventPayload) => options + ); \ No newline at end of file diff --git a/src/session/handlers.ts b/src/session/handlers.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/session/index.ts b/src/session/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/session/types.ts b/src/session/types.ts new file mode 100644 index 0000000..0689f9b --- /dev/null +++ b/src/session/types.ts @@ -0,0 +1,43 @@ +import { BaseRequestPayload, BaseResponsePayload } from '../base/BasePayload'; + +import { ISessionContextConfig, ISolaceContextPayload, SessionContext } from '../utils/SolaceContext'; + +export interface ICreateAndConnectSessionPayload extends BaseRequestPayload{ + hostUrl:string, + vpn:string, + username:string, + sessionCache:string, + pass:string, + config?:ISessionContextConfig, +} +export interface ICreateAndConnectSessionResPayload extends BaseResponsePayload{ + result?: SessionContext, +} + + +export interface IDisconnectAndRemoveOneSessionPayload extends BaseRequestPayload{ + +} +export interface IDisconnectAndRemoveOneSessionResPayload extends BaseResponsePayload{ + +} + + +export interface ICloseAndRemoveAllSessionsPayload extends BaseRequestPayload{ + +} +export interface ICloseAndRemoveAllSessionsResPayload extends BaseResponsePayload{ + +} + + +export interface ISendCacheRequestOfOneSessionPayload extends BaseRequestPayload{ + +} +export interface ISendCacheRequestOfOneSessionResPayload extends BaseResponsePayload{ + +} + +export interface ISolaceContextChangedEventPayload extends ISolaceContextPayload { + +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c2ff48f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "outDir": "./build", + "declaration": true, + "declarationDir": "./build", + "sourceMap": true, + "noImplicitAny": false, + "module": "commonjs", + "target": "es6", + "lib": ["es6","dom"] + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "node_modules", + "build", + "config", + "scripts", + "acceptance-tests", + "webpack", + "jest", + "./src/**/__mocks__/", + "./src/**/__tests__/", + "./src/**/*.spec.ts", + "./src/**/*.test.ts" + ] +}