Skip to content

Commit

Permalink
refactor(core): changed mutation hook name and improved destroyed stores
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcourtice committed Aug 5, 2021
1 parent a482cdb commit cd268a4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 35 deletions.
1 change: 1 addition & 0 deletions core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const EVENTS = {
mutation: {
before: 'mutation:before',
after: 'mutation:after',
success: 'mutation:success',
error: 'mutation:error',
},
devtools: {
Expand Down
2 changes: 2 additions & 0 deletions core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export function createStore<TState extends BaseState, TExtensions extends Extens

const onBeforeMutation = getMutationHook(EVENTS.mutation.before);
const onAfterMutation = getMutationHook(EVENTS.mutation.after);
const onMutationSuccess = getMutationHook(EVENTS.mutation.success);
const onMutationError = getMutationHook(EVENTS.mutation.error);

const extendedStore = getExtendedStore<TState, TExtensions>(store, extensions);
Expand All @@ -151,6 +152,7 @@ export function createStore<TState extends BaseState, TExtensions extends Extens
destroy,
onBeforeMutation,
onAfterMutation,
onMutationSuccess,
onMutationError,
state: store.state,
getter: store.getter.bind(store),
Expand Down
58 changes: 32 additions & 26 deletions core/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import type {
StoreProviders,
StoreRegistrations,
RegistrationValueProducer,
RegistrationType,
StoreRegistration,
} from './types';

function localiseHandler(name: string, handler: EventHandler): EventHandler {
Expand Down Expand Up @@ -99,6 +101,10 @@ export default class Store<TState extends BaseState = any> implements InternalSt
}

public emit(event: string, sender: string, data: any): void {
if (!this.scope.active) {
return;
}

const payload: EventPayload = {
data,
sender,
Expand All @@ -124,24 +130,27 @@ export default class Store<TState extends BaseState = any> implements InternalSt
return this.scope.run(callback)!;
}

public hasRegistration(type: string, name: string): boolean {
return !!this.registrations[type]?.has(name);
public hasRegistration(group: string, name: string): boolean {
return !!this.registrations[group]?.has(name);
}

public getRegistration(type: string, name: string): RegistrationValueProducer | undefined {
return this.registrations[type]?.get(name);
public getRegistration(group: string, name: string): StoreRegistration | undefined {
return this.registrations[group]?.get(name);
}

public register(type: string, name: string, valueProducer: RegistrationValueProducer): void {
if (!(type in this.registrations)) {
this.registrations[type] = new Map();
public register(group: string, name: string, producer: RegistrationValueProducer, type: RegistrationType = 'other'): void {
if (!(group in this.registrations)) {
this.registrations[group] = new Map();
}

this.registrations[type].set(name, valueProducer);
this.registrations[group].set(name, {
type,
producer,
});
}

public unregister(type: string, name: string): void {
this.registrations[type]?.delete(name);
public unregister(group: string, name: string): void {
this.registrations[group]?.delete(name);
}

public getter<TResult>(name: string, getter: Getter<TState, TResult>): ComputedRef<TResult> {
Expand All @@ -151,22 +160,31 @@ export default class Store<TState extends BaseState = any> implements InternalSt

const output = this.track(() => computed(() => getter(this.state)));

this.register('getters', name, () => output.value);
this.register('getters', name, () => output.value, 'computed');

return output;
}

private mutate<TPayload, TResult = void>(name: string, sender: string, mutator: Mutator<TState, TPayload, TResult>, payload: TPayload): TResult {
if (!this.scope.active) {
throw new Error('The current store has been destroyed. Mutations can no longer take place.');
}

if (this.stack.has(name)) {
throw new Error('Circular mutation reference detected. Avoid calling mutations inside other mutations to prevent circular references.');
}

let result: TResult;

const eventData: MutationEventData<TPayload, TResult> = {
payload,
mutation: name,
};

let result: TResult;
const emitComplete = (event: string) => this.emit(event, sender, {
...eventData,
result,
});

this.stack.add(name);
this.emit(EVENTS.mutation.before, sender, eventData);
Expand All @@ -181,12 +199,10 @@ export default class Store<TState extends BaseState = any> implements InternalSt
throw error;
} finally {
this.stack.delete(name);
emitComplete(EVENTS.mutation.after);
}

this.emit(EVENTS.mutation.after, sender, {
...eventData,
result,
});
emitComplete(EVENTS.mutation.success);

return result;
}
Expand All @@ -205,16 +221,6 @@ export default class Store<TState extends BaseState = any> implements InternalSt
return mutation;
}

public exec<TResult = void>(name: string, payload?: any): TResult {
const mutation = this.getRegistration('mutations', name) as Mutation<any, TResult>;

if (!mutation) {
throw new Error(`No mutation found for ${name}`);
}

return mutation(payload);
}

public write<TResult = void>(name: string, sender: string, mutator: Mutator<TState, undefined, TResult>): TResult {
return this.mutate(name, sender, mutator, undefined);
}
Expand Down
23 changes: 14 additions & 9 deletions core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export type BaseState = object;
export type StoreProvider<TState extends BaseState> = keyof StoreProviders<TState>;
export type ReadState<TState extends BaseState> = DeepReadonly<TState>;
export type WriteState<TState extends BaseState> = TState;
export type RegistrationType = 'ref' | 'reactive' | 'computed' | 'other';
export type RegistrationValueProducer = () => unknown;
export type Getter<TState extends BaseState, TResult> = (state: ReadState<TState>) => TResult;
export type Mutator<TState extends BaseState, TPayload, TResult = void> = (state: WriteState<TState>, payload: TPayload) => TResult;
export type Mutation<TPayload, TResult = void> = undefined extends TPayload ? (payload?: TPayload) => TResult : (payload: TPayload) => TResult;
Expand Down Expand Up @@ -59,14 +61,13 @@ export interface InternalStore<TState extends BaseState = any> extends StoreBase
readonly state: ReadState<TState>;
name: string;
registrations: StoreRegistrations;
hasRegistration(type: string, name: string): boolean;
getRegistration(type: string, name: string): RegistrationValueProducer | undefined;
register(type: string, name: string, valueProducer: RegistrationValueProducer): void;
unregister(type: string, name: string): void;
hasRegistration(group: string, name: string): boolean;
getRegistration(group: string, name: string): StoreRegistration | undefined;
register(group: string, name: string, valueProducer: RegistrationValueProducer, type?: RegistrationType): void;
unregister(group: string, name: string): void;
emit(event: string, sender: string, data: any): void;
on(event: string, handler: EventHandler): EventListener;
once(event: string, handler: EventHandler): EventListener
exec<TResult = void>(name: string, payload?: any): TResult;
track<TResult>(callback: () => TResult): TResult;
provider<TKey extends StoreProvider<TState>>(key: TKey, value: StoreProviders<TState>[TKey]): void;
write<TResult = void>(name: string, sender: string, mutator: Mutator<TState, undefined, TResult>): TResult;
Expand All @@ -89,6 +90,7 @@ export interface Store<TState extends BaseState> extends StoreBase<TState> {
destroy(): void;
onBeforeMutation<TPayload = any, TResult = any>(mutationName: string | string[], handler: MutationHookHandler<TPayload, TResult>): EventListener;
onAfterMutation<TPayload = any, TResult = any>(mutationName: string | string[], handler: MutationHookHandler<TPayload, TResult>): EventListener;
onMutationSuccess<TPayload = any, TResult = any>(mutationName: string | string[], handler: MutationHookHandler<TPayload, TResult>): EventListener;
onMutationError<TPayload = any, TResult = any>(mutationName: string | string[], handler: MutationHookHandler<TPayload, TResult>): EventListener;
}

Expand All @@ -101,10 +103,13 @@ export interface PluginOptions {
plugins?: HarlemPlugin[];
}

export type RegistrationValueProducer = () => unknown;
export interface StoreRegistration {
type: RegistrationType;
producer: RegistrationValueProducer;
}

export interface StoreRegistrations {
[key: string]: Map<string, RegistrationValueProducer>;
getters: Map<string, RegistrationValueProducer>;
mutations: Map<string, RegistrationValueProducer>;
[key: string]: Map<string, StoreRegistration>;
getters: Map<string, StoreRegistration>;
mutations: Map<string, StoreRegistration>;
}

0 comments on commit cd268a4

Please sign in to comment.