Skip to content

Instantly share code, notes, and snippets.

@etienne-dldc
Created September 23, 2018 13:55
Show Gist options
  • Select an option

  • Save etienne-dldc/205f780e200cbb79a82120799688027b to your computer and use it in GitHub Desktop.

Select an option

Save etienne-dldc/205f780e200cbb79a82120799688027b to your computer and use it in GitHub Desktop.
Experiment about Overmind library api
import App, { derive, hidden, Action, Operation, Mutate } from 'overmind';
declare module 'overmind' {
function hidden<T>(val: T): T;
}
namespace Resource {
enum Status {
Void = 'void',
Pending = 'pending',
Resolved = 'resolved',
Rejected = 'rejected',
}
type PublicState<T> = {
void: boolean;
pending: boolean;
resolved: false | { data: T };
rejected: false | { error: any };
};
type InternalStateObj<T> =
| { status: Status.Void }
| { status: Status.Pending }
| { status: Status.Resolved; data: T }
| { status: Status.Rejected; error: any };
type InternalState<T> = PublicState<T> & {
_internal: InternalStateObj<T>;
};
export function create<T>(stateAccess: (state: any) => PublicState<T>, request: Operation.Map<void, T>) {
const internalStateAccess = stateAccess as (state: any) => InternalState<T>;
const state: InternalState<T> = {
_internal: hidden<InternalStateObj<T>>({ status: Status.Void }),
void: derive(state => internalStateAccess(state)._internal.status === Status.Void),
pending: derive(state => internalStateAccess(state)._internal.status === Status.Pending),
resolved: derive(s => {
const state = internalStateAccess(s);
if (state._internal.status === Status.Resolved) {
return { data: state._internal.data as any };
}
return false;
}),
rejected: derive(s => {
const state = internalStateAccess(s);
if (state._internal.status === Status.Rejected) {
return { error: state._internal.error };
}
return false;
}),
};
const isPending: Operation.When = ({ state }, v) => {
return internalStateAccess(state).pending !== false;
};
const setPending: Mutate = state => (internalStateAccess(state)._internal = { status: Status.Pending });
const setVoid: Mutate = state => (internalStateAccess(state)._internal = { status: Status.Void });
const setResolved: Mutate = (state, data) => {
internalStateAccess(state)._internal = { status: Status.Resolved, data };
};
const setRejected: Mutate = (state, error) =>
(internalStateAccess(state)._internal = { status: Status.Rejected, error });
const fetch: Action = action =>
action.when(isPending, {
true: null,
false: a =>
a
.mutate(setPending)
.map(request)
.when(isPending, {
true: a1 => a1.mutate(setResolved),
false: null,
}),
});
const reset: Action = action => action.mutate(setVoid);
return {
state: state as PublicState<T>,
actions: {
fetch,
},
};
}
}
/**
* User code
*/
type Post = {};
const postResource = Resource.create<Post>(s => s.data.post, ({ api }) => api.getPost());
const weatherResource = Resource.create<Post>(s => s.weather, ({ api }) => api.getWeather());
const app = new App({
state: {
data: {
otherStuff: true,
post: postResource.state,
},
weather: weatherResource.state,
},
actions: {
myOtherAction,
postActions: postResource.actions,
weatherActions: weatherResource.actions,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment