import {
configureStore,
Store as MiniStore,
ReduxDevtoolsExtension,
ImmutableStateExtension,
UndoExtension,
LoggerExtension,
} from "mini-rx-store";
import { take } from "rxjs";
import { STATES_INFO } from "./states-info";
import { SsrService } from "@/app/shared/services/ssr/ssr.service";
import COUNTER_EFFECTS from "./counter/counter.effect";
import { counterReducer } from "./counter/counter.reducer";
import { initialCounterState } from "./counter/initial-counter.state";
import superjson from 'superjson';
import * as devalue from 'devalue';
interface StoreOptions {
reducers: any;
initialState: any;
}
export class StateManager {
private ssrService = SsrService.instance();
private miniState: MiniStore = null!;
private static mirror: StateManager;
private static storeOptions: StoreOptions = {
reducers: {
counter: counterReducer,
},
initialState: {
counter: initialCounterState,
},
}
private constructor() {}
static instance(): StateManager {
if (!StateManager.mirror) {
StateManager.mirror = new StateManager();
StateManager.mirror.init(this.storeOptions);
}
return StateManager.mirror;
}
private init(options: StoreOptions) {
let extensions: any[] = [
new ImmutableStateExtension(),
new UndoExtension({ bufferSize: 100 }),
// new LoggerExtension(),
];
if (this.ssrService.isPlatformBrowser()) {
extensions.push(
new ReduxDevtoolsExtension({
name: "BAMAN SHOWCASE",
maxAge: 100,
latency: 0,
}),
)
}
const opt = {
...options,
extensions,
};
this.miniState = configureStore(opt);
COUNTER_EFFECTS.forEach((effect: any) => this.miniState.effect(effect));
}
get store(): MiniStore {
return this.miniState;
}
exportStates(): Promise<string> {
return new Promise((resolve, reject) => {
this.miniState
.select((states: any) => states)
.pipe(take(1))
.subscribe({
next: (obj) => {
// let sJson = superjson.stringify(obj);
let sJson = devalue.stringify(obj);
resolve(sJson);
},
error: (error) => {
reject(error);
},
});
});
}
resetStore() {
STATES_INFO.forEach((state: any) =>
this.miniState.dispatch(state.actions.reset())
);
}
replaceStore(sJson: string) {
let store = this.miniState;
// let obj = superjson.parse<any>(sJson);
let obj = devalue.parse(sJson);
Object.keys(obj).forEach(function (key, index) {
const state = STATES_INFO.find((s) => s.name === key);
if (state) {
store.dispatch(state.actions.replace(obj[key]));
}
});
}
}