Skip to content

Instantly share code, notes, and snippets.

@aguynamedben
Created November 23, 2018 04:21
Show Gist options
  • Save aguynamedben/ee5ef358856f1543129265fd3cf8b732 to your computer and use it in GitHub Desktop.
Save aguynamedben/ee5ef358856f1543129265fd3cf8b732 to your computer and use it in GitHub Desktop.
// @flow
/* eslint-disable */
// This is a modified version of redux-persist's createMigrate that allows async
// migrations to be used if you pass the option { asyncMigrations: true }. Async
// migrations are run in sequence and block.
import { DEFAULT_VERSION } from 'redux-persist/lib/constants'
import type { PersistedState, MigrationManifest } from 'redux-persist/lib/types'
export default function createMigrate(
migrations: MigrationManifest,
config?: { debug: boolean, asyncMigrations?: boolean }
) {
let { debug, asyncMigrations } = config || {}
return function(
state: PersistedState,
currentVersion: number
): Promise<PersistedState> {
if (!state) {
if (process.env.NODE_ENV !== 'production' && debug)
console.log('redux-persist: no inbound state, skipping migration')
return Promise.resolve(undefined)
}
let inboundVersion: number =
state._persist && state._persist.version !== undefined
? state._persist.version
: DEFAULT_VERSION
if (inboundVersion === currentVersion) {
if (process.env.NODE_ENV !== 'production' && debug)
console.log('redux-persist: versions match, noop migration')
return Promise.resolve(state)
}
if (inboundVersion > currentVersion) {
if (process.env.NODE_ENV !== 'production')
console.error('redux-persist: downgrading version is not supported')
return Promise.resolve(state)
}
let migrationKeys = Object.keys(migrations)
.map(ver => parseInt(ver))
.filter(key => currentVersion >= key && key > inboundVersion)
.sort((a, b) => a - b)
if (process.env.NODE_ENV !== 'production' && debug)
console.log('redux-persist: migrationKeys', migrationKeys)
if (asyncMigrations) {
// Return Promise chain to run async migrations in sequence. Migration
// functions can return a Promise (or be async).
return migrationKeys.reduce((promiseChain, versionKey) => {
return promiseChain.
then((state) => {
console.log(`redux-persist: running migration ${versionKey}`);
return migrations[versionKey](state)
.then((state) => {
console.log(`redux-persist: successfully ran migration ${versionKey}`);
return state;
})
.catch((err) => {
console.log(`redux-persist: error running migration ${versionKey}: ${error.message}`);
throw err;
});
});
}, Promise.resolve(state));
} else {
try {
let migratedState = migrationKeys.reduce((state, versionKey) => {
if (process.env.NODE_ENV !== 'production' && debug)
console.log(
'redux-persist: running migration for versionKey',
versionKey
)
return migrations[versionKey](state)
}, state)
return Promise.resolve(migratedState)
} catch (err) {
return Promise.reject(err)
}
}
}
}
import customCreateMigrate from '../../../../app/renderer/reduxMigrations/customCreateMigrate';
describe(`customCreateMigration`, () => {
describe(`with async migrations`, () => {
it(`runs migrations with async functions`, async () => {
const persistedState = {
foo: 'different',
_persist: {
version: 1,
},
};
const asyncMigrations = {
// Already run
1: async (state) => {
return {
...state,
foo: 'different',
};
},
// Needs to run
2: async (state) => {
return {
...state,
baz: 'bang',
};
},
// Needs to run
3: async (state) => {
return {
...state,
cool: 'beans',
};
},
};
const migrate = customCreateMigrate(asyncMigrations, {
debug: true,
asyncMigrations: true,
});
const currentVersion = 3;
const migratedState = await migrate(persistedState, currentVersion);
expect(migratedState).toEqual({
foo: 'different',
baz: 'bang',
cool: 'beans',
_persist: {
version: 1,
},
});
});
it(`resolves to undefined when persistedState is undefined`, async () => {
const persistedState = undefined;
const asyncMigrations = {
1: async (state) => {
return {
...state,
foo: 'bar',
};
},
};
const migrate = customCreateMigrate(asyncMigrations, {
debug: true,
asyncMigrations: true,
});
const currentVersion = 3;
const migratedState = await migrate(persistedState, currentVersion);
expect(migratedState).toEqual(undefined);
});
it(`does nothing when inboundVersion and currentVersion match`, async () => {
const persistedState = {
foo: 'bar',
_persist: {
version: 1,
},
};
const asyncMigrations = {
1: async (state) => {
return {
...state,
foo: 'bar',
};
},
};
const migrate = customCreateMigrate(asyncMigrations, {
debug: true,
asyncMigrations: true,
});
const currentVersion = 1;
const migratedState = await migrate(persistedState, currentVersion);
expect(migratedState).toEqual(persistedState);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment