For now the library is supposed to be an endless pit of infrastructure code that can be reused throughout projects. Possibly it will evolve into separate packages for specific purposes, or I will spend some time organizing the code better, but for now it is more of a dump :).
First define a repository:
// repositories/dayRepository.ts
import { Repository } from 'abyss';
import { IDayModel } from 'models';
const repository = new Repository<IDayModel>();
export const dayRepository = {
getDay(id: string) {
return repository.get(`/days/${id}`);
},
persistDay(day: IDayModel) {
return repository.post<{ date: string }>('/days', {
data: { attributes: { date: day.date } }
});
}
};
Then add an async action that will be used to track the API call progress and get the response:
// redux/datastoreReducer.ts
import { ApiError } from 'abyss';
import { IDayModel } from 'models';
import actionCreatorFactory from 'typescript-fsa';
import { reducerWithInitialState } from 'typescript-fsa-reducers';
const actionCreator = actionCreatorFactory('datastore');
export const DatastoreActions = {
refreshDay: actionCreator.async<{ day: IDayModel }, IDayModel, ApiError>('REFRESH_DAY')
};
export type State = Readonly<{
day: IDayModel | null;
}>;
const initialState: State = {
day: null;
};
export const reducer = reducerWithInitialState(initialState)
.caseWithAction(DatastoreActions.refreshDay.done, (state, action) => ({ ...state, day: action.payload }))
.case(DatastoreActions.refreshDay.failed, state => ({ ...state, day: null }))
.build();
Then dispatch an API call action:
// epics/homeEpics.ts
import { ApiActions } from 'config/abyss';
export const persistDay: Epic<Action, Action, IRootState> = action$ =>
action$.pipe(
filter(HomeActions.buttonPressed.match),
map(action =>
ApiActions.directCall(dayRepository.persistDay({ day: action.payload }), DatastoreActions.refreshDay, {})
)
);
Set a new reducerVersion
in config/abyss.ts
:
AbyssConfig.redux.reducerVersion = '1'; // default 0
In theme/metrics.ts
:
import { getMetrics } from 'abyss';
export const metrics = {
...getMetrics(),
otherCustomMetric: 10
};
Assuming Transloadit is enabled in the store sonfig, simply dispatch an action:
Transloadit.action(
uri: string,
template: string,
asyncAction: AsyncActionCreators<P, S, E>,
extraParams: Record<string, string> = {}
)
// tsconfig.json
{
"extends": "./node_modules/abyss/config/tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "artifacts",
"baseUrl": "src/"
},
"exclude": ["android", "ios", "build", "node_modules", "scripts", "assets"]
}
// .eslintrc.js
module.exports = {
extends: './node_modules/abyss/config/.eslintrc.js',
};
// babel.config.js
module.exports = {
extends: './node_modules/abyss/config/.babelrc',
};
API configuration (config/abyss.ts
usually):
import { AbyssConfig, Api } from 'abyss';
// mandatory, everything else is optional
AbyssConfig.api.serverUrl = Config.SERVER_URL;
AbyssConfig.api.prefix: '/api/v1';
AbyssConfig.api.timeout = 4000;
// these calls will reset the auth token; an `auth_token` attribute is expected on the response
AbyssConfig.api.authCalls = ['login/LOG_IN_DONE', 'login/CREATE_USER_ACCOUNT_DONE'];
// manually set the auth token
Api.setAuthToken(getUniqueID());
// and other headers
Api.setHeader('Accept', 'application/json');
import { createReduxStore } from 'abyss';
import { Store } from 'redux';
import * as epics from '../epics';
import { AppActions } from '../modules/reducer';
import { IRootState, reducers } from './reducers';
export const store: Store<IRootState> = createReduxStore(epics, reducers, {
offline: {
persistCallback: () => store.dispatch(AppActions.startup()),
persistOptions: {
blacklist: ['volatile', 'hive', 'home', 'camera', 'welcome']
}
},
logger: true,
transloadit: true
});
// redux/store.ts
import { transloaditMiddleware } from 'abyss';
...
applyMiddleware(apiMiddleware, transloaditMiddleware, epicMiddleware, loggerMiddleware)
...
// config/abyss.ts
AbyssConfig.transloadit.key = Config.TRANSLOADIT_KEY;
AbyssConfig.transloadit.secret = Config.TRANSLOADIT_SECRET;
AbyssConfig.transloadit.templates = {
image: Config.TRANSLOADIT_IMAGE_TEMPLATE,
video: Config.TRANSLOADIT_VIDEO_TEMPLATE,
profile: Config.TRANSLOADIT_PROFILE_IMAGE_TEMPLATE
};
AbyssConfig.transloadit.progressAction = VolatileActions.updateUploadProgress;
AbyssConfig.transloadit.notifiyUrl = `${Config.SERVER_URL}/transloadit/file_upload`;