Skip to content

Commit

Permalink
Merge pull request #80 from andrewcourtice/feat/skip-history-tracking
Browse files Browse the repository at this point in the history
Skip history tracking
  • Loading branch information
andrewcourtice committed Mar 15, 2023
2 parents 0b323bb + 8b2f5be commit c8ea4bb
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 43 deletions.
104 changes: 61 additions & 43 deletions extensions/history/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import traceExtension, {
} from '@harlem/extension-trace';

import {
Disposable,
matchGetFilter,
numberClamp,
objectFromPath,
Expand All @@ -43,18 +44,35 @@ import type {

export * from './types';

function getOptions(options?: Partial<Options>): Options {
return {
function getMutationGroups(mutations: Options['mutations']) {
const hasGroups = typeIsObject(mutations) && 'groups' in mutations;
const groups = hasGroups ? mutations.groups : {};

if (!hasGroups || typeIsMatchable(mutations)) {
groups[DEFAULT_GROUP_KEY] = mutations;
}

return Object.entries(groups)
.map(([key, matcher]) => {
const matchable = typeIsMatchable(matcher) ? matcher : {
include: matcher,
};

return {
key,
filter: matchGetFilter(matchable),
};
});
}

export default function historyExtension<TState extends BaseState>(options?: Partial<Options>) {
const _options = {
max: 50,
mutations: '*',
...options,
};
}

export default function historyExtension<TState extends BaseState>(options?: Partial<Options>) {
const _options = getOptions(options);
const groups = getMutationGroups(_options.mutations);

const createTraceExtension = traceExtension<TState>({
autoStart: false,
});
Expand Down Expand Up @@ -90,26 +108,43 @@ export default function historyExtension<TState extends BaseState>(options?: Par
};

let historyState = createHistoryState();
let trackingListener: Disposable | undefined;

store.on(CORE_EVENTS.mutation.before, (event?: EventPayload<TriggerEventData>) => {
if (!event || MUTATION_FILTER.test(event.data.name) || !mutationFilter(event.data.name)) {
return;
}
function startHistoryTracking() {
trackingListener ??= store.on(CORE_EVENTS.mutation.before, (event?: EventPayload<TriggerEventData>) => {
if (!event || MUTATION_FILTER.test(event.data.name) || !mutationFilter(event.data.name)) {
return;
}

startTrace([
'set',
'deleteProperty',
]);
startTrace([
'set',
'deleteProperty',
]);

const listener = onTraceResult(result => historyState.results.push(result));
const listener = onTraceResult(result => historyState.results.push(result));

store.once(CORE_EVENTS.mutation.after, () => {
stopTrace();
processResults(event.data.name);
store.once(CORE_EVENTS.mutation.after, () => {
stopTrace();
processResults(event.data.name);

listener.dispose();
listener.dispose();
});
});
});
}

function stopHistoryTracking() {
trackingListener = (trackingListener?.dispose(), undefined);
}

function skipHistoryTracking<TResult = void>(callback: () => TResult) {
stopHistoryTracking();

try {
return callback();
} finally {
startHistoryTracking();
}
}

function applyChange(type: ChangeType, change: MutationTrace) {
store.write(`extension:history:${type}`, SENDER, state => {
Expand Down Expand Up @@ -244,38 +279,21 @@ export default function historyExtension<TState extends BaseState>(options?: Par
const onHistoryChangeSuccess = getTrigger(EVENTS.change.success);
const onHistoryChangeError = getTrigger(EVENTS.change.error);

startHistoryTracking();

return {
undo,
redo,
canUndo,
canRedo,
clearHistory,
startHistoryTracking,
stopHistoryTracking,
skipHistoryTracking,
onBeforeHistoryChange,
onAfterHistoryChange,
onHistoryChangeSuccess,
onHistoryChangeError,
};
};
}

function getMutationGroups(mutations: Options['mutations']) {
const hasGroups = typeIsObject(mutations) && 'groups' in mutations;
const groups = hasGroups ? mutations.groups : {};

if (!hasGroups || typeIsMatchable(mutations)) {
groups[DEFAULT_GROUP_KEY] = mutations;
}

return Object.entries(groups)
.map(([key, matcher]) => {
const matchable = typeIsMatchable(matcher) ? matcher : {
include: matcher,
};

return {
key,
filter: matchGetFilter(matchable),
};
});
}

}
37 changes: 37 additions & 0 deletions extensions/history/test/history.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,41 @@ describe('History Extension', () => {
expect(spyFn).toHaveBeenCalledTimes(6);
});

test('Can skip history operations', () => {
const {
store,
setUserID,
setUserDetails,
} = instance;

const {
state,
canUndo,
skipHistoryTracking,
startHistoryTracking,
stopHistoryTracking,
} = store;

skipHistoryTracking(() => setUserID(5));
expect(state.id).toBe(5);
expect(canUndo()).toBe(false);

setUserID(10);
expect(state.id).toBe(10);
expect(canUndo()).toBe(true);

stopHistoryTracking();

setUserDetails({
firstName: 'Michael',
lastName: 'Scott',
});

startHistoryTracking();

expect(state.details.firstName).toBe('Michael');
expect(state.details.lastName).toBe('Scott');
expect(canUndo('userDetails')).toBe(false);
});

});

1 comment on commit c8ea4bb

@vercel
Copy link

@vercel vercel bot commented on c8ea4bb Mar 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.