Skip to content

Instantly share code, notes, and snippets.

@micahnz
Created February 22, 2017 21:48
Show Gist options
  • Save micahnz/70c46956b9ad27b1dda81d87c0dc9a1a to your computer and use it in GitHub Desktop.
Save micahnz/70c46956b9ad27b1dda81d87c0dc9a1a to your computer and use it in GitHub Desktop.
//
import semver from 'semver';
//
export function createVersionedReducer() {
const ranges = [];
const map = {};
//
function versionedReducer(state, action) {
const { meta } = action;
//
if (meta === undefined || meta.version === undefined) {
throw new Error('Expected versioned action');
}
//
const version = semver.valid(meta.version);
if (version === null) {
throw new Error(`"${meta.version}" is not a valid semantic version"`);
}
// try direct version match
const vMatch = ranges.filter((r) => {
const v = semver.valid(r);
if (v) return semver.eq(version, v);
return false;
});
// use direct match over anything else
if (vMatch.length === 1) {
return map[vMatch[0]](state, action);
}
// try range match
const rMatch = ranges.filter((r) => {
return semver.satisfies(version, r);
});
if (rMatch.length > 1) {
throw new Error(`more than one reducer for semantic version "${version}" ${rMatch}`);
} else if (rMatch.length > 0) {
return map[rMatch[0]](state, action);
} else {
throw new Error(`no reducer for semantic version "${version}"`);
}
}
//
versionedReducer.addVersion = (userRange, fn) => {
const range = semver.validRange(userRange);
if (range === null) {
throw new Error(`"${userRange}" is not a valid semantic version range"`);
}
if (ranges.indexOf(range) !== -1) {
throw new Error(`a reducer with the semantic version range "${range}" already exists"`);
}
//
ranges.push(range);
map[range] = fn;
//
return versionedReducer;
};
//
return versionedReducer;
}
//
export default createVersionedReducer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment