diff --git a/src/Root.tsx b/src/Root.tsx index 85808d0..4b67554 100644 --- a/src/Root.tsx +++ b/src/Root.tsx @@ -6,7 +6,8 @@ import Container from './Container'; import SyncGate from './SyncGate'; import LoginForm from './LoginForm'; -import { store, StoreState, CredentialsType, fetchCredentials } from './store'; +import { store, StoreState, CredentialsType } from './store'; +import { fetchCredentials } from './store/actions'; import * as C from './Constants'; diff --git a/src/SideMenu.tsx b/src/SideMenu.tsx index fc89923..aab213d 100644 --- a/src/SideMenu.tsx +++ b/src/SideMenu.tsx @@ -14,7 +14,8 @@ import SideMenuJournals from './SideMenuJournals'; import { routeResolver, getPalette } from './App'; -import { store, logout, JournalsType, StoreState, CredentialsData } from './store'; +import { store, JournalsType, StoreState, CredentialsData } from './store'; +import { logout } from './store/actions'; import * as C from './Constants'; diff --git a/src/SyncGate.tsx b/src/SyncGate.tsx index e674eab..637ddc2 100644 --- a/src/SyncGate.tsx +++ b/src/SyncGate.tsx @@ -14,7 +14,8 @@ import Pim from './Pim'; import * as EteSync from './api/EteSync'; -import { store, JournalsType, EntriesType, fetchJournals, fetchEntries, StoreState, CredentialsData } from './store'; +import { store, JournalsType, EntriesType, StoreState, CredentialsData } from './store'; +import { fetchJournals, fetchEntries } from './store/actions'; export interface SyncInfoJournal { journal: EteSync.Journal; diff --git a/src/etesync-helpers.tsx b/src/etesync-helpers.tsx index c3dd3be..dfb3c9c 100644 --- a/src/etesync-helpers.tsx +++ b/src/etesync-helpers.tsx @@ -2,7 +2,8 @@ import { List } from 'immutable'; import * as EteSync from './api/EteSync'; -import { CredentialsData, createEntries } from './store'; +import { CredentialsData } from './store'; +import { createEntries } from './store/actions'; export function createJournalEntry( etesync: CredentialsData, diff --git a/src/store/actions.ts b/src/store/actions.ts new file mode 100644 index 0000000..866df5b --- /dev/null +++ b/src/store/actions.ts @@ -0,0 +1,69 @@ +import { createActions } from 'redux-actions'; + +import * as EteSync from '../api/EteSync'; + +import { CredentialsData } from './'; + +export const { fetchCredentials, logout } = createActions({ + FETCH_CREDENTIALS: (username: string, password: string, encryptionPassword: string, server: string) => { + const authenticator = new EteSync.Authenticator(server); + + return new Promise((resolve, reject) => { + authenticator.getAuthToken(username, password).then( + (authToken) => { + const creds = new EteSync.Credentials(username, authToken); + const derived = EteSync.deriveKey(username, encryptionPassword); + + const context = { + serviceApiUrl: server, + credentials: creds, + encryptionKey: derived, + }; + + resolve(context); + }, + (error) => { + reject(error); + } + ); + }); + }, + LOGOUT: () => undefined, +}); + +export const { fetchJournals } = createActions({ + FETCH_JOURNALS: (etesync: CredentialsData) => { + const creds = etesync.credentials; + const apiBase = etesync.serviceApiUrl; + let journalManager = new EteSync.JournalManager(creds, apiBase); + + return journalManager.list(); + }, +}); + +export const { fetchEntries, createEntries } = createActions({ + FETCH_ENTRIES: [ + (etesync: CredentialsData, journalUid: string, prevUid: string | null) => { + const creds = etesync.credentials; + const apiBase = etesync.serviceApiUrl; + let entryManager = new EteSync.EntryManager(creds, apiBase, journalUid); + + return entryManager.list(prevUid); + }, + (etesync: CredentialsData, journalUid: string, prevUid: string | null) => { + return { journal: journalUid, prevUid }; + } + ], + CREATE_ENTRIES: [ + (etesync: CredentialsData, journalUid: string, newEntries: Array, prevUid: string | null) => { + const creds = etesync.credentials; + const apiBase = etesync.serviceApiUrl; + let entryManager = new EteSync.EntryManager(creds, apiBase, journalUid); + + return entryManager.create(newEntries, prevUid).then(response => newEntries); + }, + (etesync: CredentialsData, journalUid: string, newEntries: Array, prevUid: string | null) => { + return { journal: journalUid, entries: newEntries, prevUid }; + } + ] +}); diff --git a/src/store.test.tsx b/src/store/index.test.ts similarity index 88% rename from src/store.test.tsx rename to src/store/index.test.ts index bc88d1a..527c094 100644 --- a/src/store.test.tsx +++ b/src/store/index.test.ts @@ -1,8 +1,9 @@ -import { entries, createEntries, fetchEntries, EntriesTypeImmutable } from './store'; +import { createEntries, fetchEntries } from './actions'; +import { entries, EntriesTypeImmutable } from './reducers'; import { Map } from 'immutable'; -import * as EteSync from './api/EteSync'; +import * as EteSync from '../api/EteSync'; it('Entries reducer', () => { const jId = '24324324324'; diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..f927dc8 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,36 @@ +import { createStore, applyMiddleware } from 'redux'; +import { persistStore } from 'redux-persist'; +import thunkMiddleware from 'redux-thunk'; +import { createLogger } from 'redux-logger'; + +import promiseMiddleware from './promise-middleware'; + +import reducers from './reducers'; +import { CredentialsType, JournalsType, EntriesType } from './reducers'; + +export { CredentialsType, CredentialsData, JournalsType, JournalsData, EntriesType, EntriesData } from './reducers'; + +export interface StoreState { + fetchCount: number; + credentials: CredentialsType; + cache: { + journals: JournalsType; + entries: EntriesType; + }; +} + +let middleware = [ + thunkMiddleware, + promiseMiddleware, +]; + +if (process.env.NODE_ENV === 'development') { + middleware.push(createLogger()); +} + +export const store = createStore( + reducers, + applyMiddleware(...middleware) +); + +export const persistor = persistStore(store); diff --git a/src/promise-middleware.tsx b/src/store/promise-middleware.ts similarity index 100% rename from src/promise-middleware.tsx rename to src/store/promise-middleware.ts diff --git a/src/store.tsx b/src/store/reducers.ts similarity index 59% rename from src/store.tsx rename to src/store/reducers.ts index 89d5226..8d088c3 100644 --- a/src/store.tsx +++ b/src/store/reducers.ts @@ -1,16 +1,15 @@ -import { createStore, combineReducers, applyMiddleware } from 'redux'; -import { persistReducer, persistStore, createTransform } from 'redux-persist'; -import { createActions, handleAction, handleActions, combineActions } from 'redux-actions'; +import { combineReducers } from 'redux'; +import { persistReducer, createTransform } from 'redux-persist'; +import { handleAction, handleActions, combineActions } from 'redux-actions'; + import * as localforage from 'localforage'; import session from 'redux-persist/lib/storage/session'; -import thunkMiddleware from 'redux-thunk'; -import { createLogger } from 'redux-logger'; import { List, Map, Record } from 'immutable'; -import promiseMiddleware from './promise-middleware'; +import * as EteSync from '../api/EteSync'; -import * as EteSync from './api/EteSync'; +import * as actions from './actions'; interface FetchTypeInterface { value: T | null; @@ -24,7 +23,7 @@ export interface CredentialsData { encryptionKey: string; } -type FetchType = FetchTypeInterface; +export type FetchType = FetchTypeInterface; function fetchTypeRecord() { return Record>({ @@ -48,15 +47,6 @@ const EntriesFetchRecord = fetchTypeRecord(); export type EntriesTypeImmutable = Map>>; export type EntriesType = Map>; -export interface StoreState { - fetchCount: number; - credentials: CredentialsType; - cache: { - journals: JournalsType; - entries: EntriesType; - }; -} - function credentialsIdentityReducer(state: CredentialsType = {value: null}, action: any, extend: boolean = false) { if (action.error) { return { @@ -95,74 +85,10 @@ function fetchTypeIdentityReducer( } } -export const { fetchCredentials, logout } = createActions({ - FETCH_CREDENTIALS: (username: string, password: string, encryptionPassword: string, server: string) => { - const authenticator = new EteSync.Authenticator(server); - - return new Promise((resolve, reject) => { - authenticator.getAuthToken(username, password).then( - (authToken) => { - const creds = new EteSync.Credentials(username, authToken); - const derived = EteSync.deriveKey(username, encryptionPassword); - - const context = { - serviceApiUrl: server, - credentials: creds, - encryptionKey: derived, - }; - - resolve(context); - }, - (error) => { - reject(error); - } - ); - }); - }, - LOGOUT: () => undefined, -}); - -export const { fetchJournals } = createActions({ - FETCH_JOURNALS: (etesync: CredentialsData) => { - const creds = etesync.credentials; - const apiBase = etesync.serviceApiUrl; - let journalManager = new EteSync.JournalManager(creds, apiBase); - - return journalManager.list(); - }, -}); - -export const { fetchEntries, createEntries } = createActions({ - FETCH_ENTRIES: [ - (etesync: CredentialsData, journalUid: string, prevUid: string | null) => { - const creds = etesync.credentials; - const apiBase = etesync.serviceApiUrl; - let entryManager = new EteSync.EntryManager(creds, apiBase, journalUid); - - return entryManager.list(prevUid); - }, - (etesync: CredentialsData, journalUid: string, prevUid: string | null) => { - return { journal: journalUid, prevUid }; - } - ], - CREATE_ENTRIES: [ - (etesync: CredentialsData, journalUid: string, newEntries: Array, prevUid: string | null) => { - const creds = etesync.credentials; - const apiBase = etesync.serviceApiUrl; - let entryManager = new EteSync.EntryManager(creds, apiBase, journalUid); - - return entryManager.create(newEntries, prevUid).then(response => newEntries); - }, - (etesync: CredentialsData, journalUid: string, newEntries: Array, prevUid: string | null) => { - return { journal: journalUid, entries: newEntries, prevUid }; - } - ] -}); - const credentials = handleActions( { - [fetchCredentials.toString()]: credentialsIdentityReducer, - [logout.toString()]: (state: CredentialsType, action: any) => { + [actions.fetchCredentials.toString()]: credentialsIdentityReducer, + [actions.logout.toString()]: (state: CredentialsType, action: any) => { return {out: true, value: null}; }, }, @@ -170,7 +96,7 @@ const credentials = handleActions( ); export const entries = handleAction( - combineActions(fetchEntries, createEntries), + combineActions(actions.fetchEntries, actions.createEntries), (state: EntriesTypeImmutable, action: any) => { const prevState = state.get(action.meta.journal); const extend = action.meta.prevUid != null; @@ -181,16 +107,16 @@ export const entries = handleAction( ); const journals = handleAction( - fetchJournals, + actions.fetchJournals, fetchTypeIdentityReducer, new JournalsFetchRecord(), ); const fetchCount = handleAction( combineActions( - fetchCredentials, - fetchJournals, - fetchEntries + actions.fetchCredentials, + actions.fetchJournals, + actions.fetchEntries ), (state: number, action: any) => { if (action.payload === undefined) { @@ -291,18 +217,4 @@ const reducers = combineReducers({ })), }); -let middleware = [ - thunkMiddleware, - promiseMiddleware, -]; - -if (process.env.NODE_ENV === 'development') { - middleware.push(createLogger()); -} - -export const store = createStore( - reducers, - applyMiddleware(...middleware) -); - -export const persistor = persistStore(store); +export default reducers;