Skip to content

Commit

Permalink
feat(extensions): added branch function to reset
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcourtice committed Sep 5, 2021
1 parent 9d8e71b commit 3501915
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 37 deletions.
2 changes: 1 addition & 1 deletion extensions/reset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@harlem/core": "^2.0.0-alpha.0"
},
"dependencies": {
"@harlem/extension-snapshot": "^2.0.0-beta.3"
"@harlem/utilities": "^2.0.0-beta.3"
},
"devDependencies": {
"@harlem/core": "^2.0.0-beta.3",
Expand Down
1 change: 1 addition & 0 deletions extensions/reset/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SENDER = 'extension:reset';
34 changes: 24 additions & 10 deletions extensions/reset/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import snapshotExtension from '@harlem/extension-snapshot';
import {
SENDER,
} from './constants';

import {
clone,
overwrite,
} from '@harlem/utilities';

import type {
InternalStore,
BaseState,
} from '@harlem/core';

export default function resetExtension<TState extends BaseState>() {
const createSnapshotExtension = snapshotExtension<TState>({
mutationName: '$reset',
});
import type {
BranchCallback,
} from './types';

export * from './types';

export default function resetExtension<TState extends BaseState>() {
return (store: InternalStore<TState>) => {
const {
snapshot,
} = createSnapshotExtension(store);
const snapshot = clone(store.state) as TState;

function reset<TBranchState extends BaseState>(branchCallback: BranchCallback<TState, TBranchState> = state => state as TBranchState) {
store.write('$reset', SENDER, state => {
const source = branchCallback(snapshot);
const target = branchCallback(state);

const snap = snapshot();
overwrite(target, source, /^\$/);
});
}

return {
reset: () => snap.apply(),
reset,
};
};
}
7 changes: 7 additions & 0 deletions extensions/reset/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {
BaseState,
ReadState,
WriteState,
} from '@harlem/core';

export type BranchCallback<TState extends BaseState, TData extends BaseState> = (state: ReadState<TState> | WriteState<TState>) => TData;
93 changes: 67 additions & 26 deletions extensions/reset/test/reset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ describe('Reset Extension', () => {
const getInstance = () => getStore({
extensions: [
resetExtension(),
store => {
const value = 'value';

// @ts-ignore
store.write('$test', 'test', state => state.$internal = value);

return {
value,
};
},
],
});

Expand All @@ -30,6 +40,7 @@ describe('Reset Extension', () => {
setUserDetails({
firstName: 'John',
lastName: 'Smith',
age: 35,
});

expect(store.state.id).toBe(5);
Expand All @@ -41,33 +52,63 @@ describe('Reset Extension', () => {
expect(store.state.id).toBe(0);
expect(store.state.details.firstName).toBe('');
expect(store.state.details.lastName).toBe('');
expect(store.state.details.age).toBe(0);
});

test('Performs a partial reset', () => {
const {
store,
setUserID,
setUserDetails,
} = instance;

setUserID(7);
setUserDetails({
firstName: 'John',
lastName: 'Smith',
age: 35,
});

expect(store.state.id).toBe(7);
expect(store.state.details.firstName).toBe('John');
expect(store.state.details.lastName).toBe('Smith');
expect(store.state.details.age).toBe(35);

store.reset(state => state.details);

expect(store.state.id).toBe(7);
expect(store.state.details.firstName).toBe('');
expect(store.state.details.lastName).toBe('');
expect(store.state.details.age).toBe(0);
});

// test('Performs a partial reset', () => {
// const {
// store,
// setUserID,
// setUserDetails,
// } = instance;

// setUserID(7);
// setUserDetails({
// firstName: 'John',
// lastName: 'Smith',
// age: 35,
// });

// expect(store.state.id).toBe(7);
// expect(store.state.details.firstName).toBe('John');
// expect(store.state.details.lastName).toBe('Smith');
// expect(store.state.details.age).toBe(35);

// store.reset(state => state.details);

// expect(store.state.id).toBe(7);
// expect(store.state.details.firstName).toBe('');
// expect(store.state.details.lastName).toBe('');
// expect(store.state.details.age).toBe(0);
// });
test('Ignores internal properties', () => {
const {
store,
setUserID,
setUserDetails,
} = instance;

setUserID(7);
setUserDetails({
firstName: 'John',
lastName: 'Smith',
age: 35,
});

expect(store.state.id).toBe(7);
expect(store.state.details.firstName).toBe('John');
expect(store.state.details.lastName).toBe('Smith');
expect(store.state.details.age).toBe(35);

store.reset();

// @ts-ignore
expect(store.state.$internal).toBe(store.value);
expect(store.state.id).toBe(0);
expect(store.state.details.firstName).toBe('');
expect(store.state.details.lastName).toBe('');
expect(store.state.details.age).toBe(0);
});

});

0 comments on commit 3501915

Please sign in to comment.