Skip to content

Commit

Permalink
feat(extensions): added extensions registration for devtools
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcourtice committed Feb 26, 2022
1 parent 41207b5 commit 4dcc809
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 30 deletions.
2 changes: 2 additions & 0 deletions extensions/action/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export default function actionsExtension<TState extends BaseState>(options?: Par
};

return (store: InternalStore<TState>) => {
store.register('extensions', 'action', () => options);

const _store = store as unknown as InternalStore<TState & ActionStoreState>;

const actionTasks = new Map<string, Set<Task<unknown>>>();
Expand Down
2 changes: 2 additions & 0 deletions extensions/compose/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ function getTraceObject<TValue extends object>() {
export default function composeExtension<TState extends BaseState>() {

return (store: InternalStore<TState>) => {
store.register('extensions', 'compose', () => ({}));

const {
value,
getNodes,
Expand Down
2 changes: 2 additions & 0 deletions extensions/history/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export default function historyExtension<TState extends BaseState>(options?: Par
});

return (store: InternalStore<TState>) => {
store.register('extensions', 'history', () => options);

const {
startTrace,
stopTrace,
Expand Down
1 change: 1 addition & 0 deletions extensions/lazy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default function lazyExtension<TState extends BaseState>() {
}

return (store: InternalStore<TState>) => {
store.register('extensions', 'lazy', () => ({}));

function lazy<TResult>(name: string, body: LazyBody<TState, TResult>, defaultValue?: TResult) {
const output = store.track(() => computedAsync(async onInvalidate => {
Expand Down
11 changes: 10 additions & 1 deletion extensions/reset/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
INTERNAL,
InternalStore,
BaseState,
EVENTS,
} from '@harlem/core';

import type {
Expand All @@ -22,17 +23,25 @@ export * from './types';

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

let snapshot: TState | undefined;

function reset<TBranchState extends BaseState>(branchCallback: BranchCallback<TState, TBranchState> = state => state as TBranchState) {
store.write(MUTATIONS.reset, SENDER, state => {
if (!snapshot) {
return;
}

const source = branchCallback(snapshot);
const target = branchCallback(state);

overwrite(target, clone(source), INTERNAL.pattern);
});
}

store.on(EVENTS.store.created, () => snapshot = clone(store.state) as TState);

return {
reset,
};
Expand Down
2 changes: 2 additions & 0 deletions extensions/snapshot/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export default function snapshotExtension<TState extends BaseState>(options?: Pa
} as Options;

return (store: InternalStore<TState>) => {
store.register('extensions', 'snapshot', () => options);

function apply<TBranchState extends BaseState>(snapshotBranch: TBranchState, branchCallback: BranchCallback<TState, TBranchState>) {
store.write(mutationName, SENDER, state => {
const stateBranch = branchCallback(state);
Expand Down
62 changes: 40 additions & 22 deletions extensions/storage/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {

import {
EVENTS,
INTERNAL,
BaseState,
EventPayload,
InternalStore,
MutationEventData,
INTERNAL,
} from '@harlem/core';

import {
Expand Down Expand Up @@ -43,23 +43,37 @@ export default function storageExtension<TState extends BaseState>(options?: Par
...options,
} as Options<TState>;

const storage = type === 'session' ? sessionStorage : localStorage;

return (store: InternalStore<TState>) => {
const storageKey = prefix ? `${prefix}:${store.name}` : store.name;
if (store.getFlag('ssr:server')) {
const noop = () => {};

return {
startStorageSync: noop,
stopStorageSync: noop,
clearStorage: noop,
restoreStorage: noop,
};
}

store.on(EVENTS.mutation.success, (event?: EventPayload<MutationEventData>) => {
if (!event || event.data.mutation === MUTATIONS.sync || exclude.includes(event.data.mutation)) {
return;
}
store.register('extensions', 'storage', () => options);

try {
const state = omit(store.state, INTERNAL.pattern);
storage.setItem(storageKey, serialiser(state));
} catch {
console.warn('Failed to write to storage');
}
});
const storage = type === 'session' ? sessionStorage : localStorage;
const storageKey = prefix ? `${prefix}:${store.name}` : store.name;

function startStorageWrite() {
store.on(EVENTS.mutation.success, (event?: EventPayload<MutationEventData>) => {
if (!event || event.data.mutation === MUTATIONS.sync || exclude.includes(event.data.mutation)) {
return;
}

try {
const state = omit(store.state, INTERNAL.pattern);
storage.setItem(storageKey, serialiser(state));
} catch {
console.warn('Failed to write to storage');
}
});
}

function syncStorage(value: string) {
store.write(MUTATIONS.sync, SENDER, state => Object.assign(state, parser(value)));
Expand Down Expand Up @@ -91,15 +105,19 @@ export default function storageExtension<TState extends BaseState>(options?: Par
}
}

store.once(EVENTS.store.destroyed, () => stopStorageSync());
store.once(EVENTS.store.created, () => {
startStorageWrite();

if (sync) {
startStorageSync();
}
if (sync) {
startStorageSync();
}

if (restore) {
restoreStorage();
}
if (restore) {
restoreStorage();
}
});

store.once(EVENTS.store.destroyed, () => stopStorageSync());

return {
startStorageSync,
Expand Down
12 changes: 8 additions & 4 deletions extensions/trace/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export default function traceExtension<TState extends BaseState>(options?: Parti
} as Options;

return (store: InternalStore<TState>) => {
store.register('extensions', 'trace', () => options);

const traceCallbacks = new Set<TraceCallback<TState>>();

function startTrace(gates: TraceGate<TState> | TraceGate<TState>[] = 'set') {
Expand All @@ -164,11 +166,13 @@ export default function traceExtension<TState extends BaseState>(options?: Parti
};
}

store.once(EVENTS.store.destroyed, () => traceCallbacks.clear());
store.once(EVENTS.store.created, () => {
if (autoStart) {
startTrace();
}
});

if (autoStart) {
startTrace();
}
store.once(EVENTS.store.destroyed, () => traceCallbacks.clear());

return {
startTrace,
Expand Down
2 changes: 2 additions & 0 deletions extensions/transaction/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export * from './types';

export default function transactionExtension<TState extends BaseState>() {
return (store: InternalStore<TState>) => {
store.register('extensions', 'transaction', () => ({}));

const {
snapshot,
} = snapshotExtension({
Expand Down
10 changes: 7 additions & 3 deletions plugins/ssr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ export function createServerSSRPlugin(): HarlemPlugin {
name: 'server-ssr',

install(app, eventEmitter, stores) {
eventEmitter.on(EVENTS.store.created, payload => onStoreEvent(stores, payload, store => {
stores.forEach(store => store.setFlag('ssr:server', true));

eventEmitter.on(EVENTS.ssr.initServer, payload => onStoreEvent(stores, payload, store => {
snapshot[store.name] = store.state;
}));
},
Expand All @@ -68,7 +70,7 @@ export function createServerSSRPlugin(): HarlemPlugin {

/**
* Create a new instance of the client-side SSR plugin
*/
*/
export function createClientSSRPlugin(): HarlemPlugin {
return {

Expand All @@ -77,7 +79,9 @@ export function createClientSSRPlugin(): HarlemPlugin {
install(app, eventEmitter, stores) {
const data = window.__harlemState;

eventEmitter.on(EVENTS.store.created, payload => onStoreEvent(stores, payload, store => {
stores.forEach(store => store.setFlag('ssr:client', true));

eventEmitter.on(EVENTS.ssr.initClient, payload => onStoreEvent(stores, payload, store => {
if (store.name in data) {
store.write(MUTATIONS.init, SENDER, state => overwrite(state, data[store.name]));
}
Expand Down

0 comments on commit 4dcc809

Please sign in to comment.