Skip to content

Commit

Permalink
feat(redux-store): add mediation store
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra committed Aug 12, 2021
1 parent 430d965 commit 8a1f39e
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 1 deletion.
5 changes: 5 additions & 0 deletions packages/redux-store/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ export {
ProofsThunks,
startProofsListener,
ProofsSelectors,
// Mediation
mediationSlice,
MediationThunks,
startMediationListener,
MediationSelectors,
} from './slices'
1 change: 1 addition & 0 deletions packages/redux-store/src/slices/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { agentSlice, AgentThunks } from './agent'
export { connectionsSlice, ConnectionThunks, ConnectionsSelectors, startConnectionsListener } from './connections'
export { credentialsSlice, CredentialsThunks, CredentialsSelectors, startCredentialsListener } from './credentials'
export { proofsSlice, ProofsThunks, ProofsSelectors, startProofsListener } from './proofs'
export { mediationSlice, MediationThunks, MediationSelectors, startMediationListener } from './mediation'
4 changes: 4 additions & 0 deletions packages/redux-store/src/slices/mediation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { mediationSlice } from './mediationSlice'
export { MediationThunks } from './mediationThunks'
export { MediationSelectors } from './mediationSelectors'
export { startMediationListener } from './mediationListener'
28 changes: 28 additions & 0 deletions packages/redux-store/src/slices/mediation/mediationListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Agent, MediationStateChangedEvent } from '@aries-framework/core'
import type { EnhancedStore } from '@reduxjs/toolkit'

import { RoutingEventTypes } from '@aries-framework/core'

import { mediationSlice } from './mediationSlice'

/**
* Starts an EventListener that listens for MediationRecords state changes
* and updates the store accordingly.
*
* This function **must** be called if you're working with MediationRecords.
* If you don't, the store won't be updated.
*/
const startMediationListener = (agent: Agent, store: EnhancedStore) => {
const listener = (event: MediationStateChangedEvent) => {
const record = event.payload.mediationRecord
store.dispatch(mediationSlice.actions.updateOrAdd(record))
}

agent.events.on(RoutingEventTypes.MediationStateChanged, listener)

return () => {
agent.events.off(RoutingEventTypes.MediationStateChanged, listener)
}
}

export { startMediationListener }
35 changes: 35 additions & 0 deletions packages/redux-store/src/slices/mediation/mediationSelectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { MediationState } from './mediationSlice'
import type { MediationState as MediationRecordState } from '@aries-framework/core'

interface PartialMediationState {
mediation: MediationState
}

/**
* Namespace that holds all MediationRecord related selectors.
*/
const MediationSelectors = {
/**
* Selector that retrieves the entire **mediation** store object.
*/
mediationStateSelector: (state: PartialMediationState) => state.mediation.mediation,

/**
* Selector that retrieves all MediationRecord from the state.
*/
mediationRecordsSelector: (state: PartialMediationState) => state.mediation.mediation.records,

/**
* Selector that retrieves all MediationRecord from the store by specified state.
*/
mediationRecordsByStateSelector: (mediationState: MediationRecordState) => (state: PartialMediationState) =>
state.mediation.mediation.records.filter((record) => record.state === mediationState),

/**
* Selector that fetches a MediationRecord by id from the state.
*/
mediationRecordByIdSelector: (mediationRecordId: string) => (state: PartialMediationState) =>
state.mediation.mediation.records.find((x) => x.id === mediationRecordId),
}

export { MediationSelectors }
61 changes: 61 additions & 0 deletions packages/redux-store/src/slices/mediation/mediationSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { MediationRecord } from '@aries-framework/core'
import type { PayloadAction, SerializedError } from '@reduxjs/toolkit'

import { createSlice } from '@reduxjs/toolkit'

import { MediationThunks } from './mediationThunks'

interface MediationState {
mediation: {
records: MediationRecord[]
isLoading: boolean
}
error: null | SerializedError
}

const initialState: MediationState = {
mediation: {
records: [],
isLoading: false,
},
error: null,
}

const mediationSlice = createSlice({
name: 'mediation',
initialState,
reducers: {
updateOrAdd: (state, action: PayloadAction<MediationRecord>) => {
const index = state.mediation.records.findIndex((record) => record.id == action.payload.id)

if (index == -1) {
// records doesn't exist, add it
state.mediation.records.push(action.payload)
return state
}

// record does exist, update it
state.mediation.records[index] = action.payload
return state
},
},
extraReducers: (builder) => {
builder
// getAllMediators
.addCase(MediationThunks.getAllMediationRecords.pending, (state) => {
state.mediation.isLoading = true
})
.addCase(MediationThunks.getAllMediationRecords.rejected, (state, action) => {
state.mediation.isLoading = false
state.error = action.error
})
.addCase(MediationThunks.getAllMediationRecords.fulfilled, (state, action) => {
state.mediation.isLoading = false
state.mediation.records = action.payload
})
},
})

export { mediationSlice }

export type { MediationState }
15 changes: 15 additions & 0 deletions packages/redux-store/src/slices/mediation/mediationThunks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createAsyncAgentThunk } from '../../utils'

/**
* Namespace containing all **mediation** related actions.
*/
const MediationThunks = {
/**
* Retrieve all Mediation records
*/
getAllMediationRecords: createAsyncAgentThunk('mediation/getAll', async (_, thunkApi) => {
return thunkApi.extra.agent.mediationRecipient.getMediators()
}),
}

export { MediationThunks }
3 changes: 2 additions & 1 deletion packages/redux-store/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import type { TypedUseSelectorHook } from 'react-redux'
import { combineReducers, configureStore } from '@reduxjs/toolkit'
import { useDispatch, useSelector } from 'react-redux'

import { credentialsSlice, proofsSlice, connectionsSlice, agentSlice } from './slices'
import { credentialsSlice, proofsSlice, connectionsSlice, agentSlice, mediationSlice } from './slices'

const rootReducer = combineReducers({
agent: agentSlice.reducer,
connections: connectionsSlice.reducer,
credentials: credentialsSlice.reducer,
proofs: proofsSlice.reducer,
mediation: mediationSlice.reducer,
})

type RootState = ReturnType<typeof rootReducer>
Expand Down

0 comments on commit 8a1f39e

Please sign in to comment.