quarrant / mobx-persist-store

Persist and rehydrate observable properties in mobx store.
268 stars 14 forks source link

[Feature] Properties array to accept a value converter object with serialize / deserialize functions #85

Closed RyoukoKonpaku closed 2 years ago

RyoukoKonpaku commented 2 years ago

Related issue #81. To allow domain objects to be persisted and hydrated that has circular references or overall have more control on how it's gonna end up in storage. While this can be done currently using a custom storage adapter, it's much more dev friend to control serialization per property than handling the whole object.

Assuming you have a domain object and Store like this.

class Todo {
    constructor(
        public name: string, 
        private store: TodoStore) {
        makeAutoObservable(this);
    }

    get asJson() {
        return {
            name: this.name
        }
    }
}

class TodoStore {
    todos: Todo[] = [];

    constructor() {
        makeAutoObservable(this);
    }
}

You could control serialization and deserialization of such property like this before handing it off to the storage adapter. This has the benefit of being agnostic on the serialization logic so the dev can choose to use a library like class-transformer or do manual serialization.

makePersistable(this, {
    name: "ComplexObjectStore",
    storage: ...,
    properties: [
      { 
        key: "todos",
        serialize: (prop) => prop.map(x => x.asJson),
        deserialize: (prop) => prop.map(x => new Todo(x.name, this))
      }
    ]
});

I'd think the property object signature would be something like this.

interface PersistPropertyConverter<T, TKey extends keyof T, TSerialized> {
    key: TKey;
    serialize: (prop: T[TKey]) => TSerialized;
    deserialize: (prop: TSerialized) => T[TKey];
}
codeBelt commented 2 years ago

@RyoukoKonpaku I had a similar idea https://github.com/quarrant/mobx-persist-store/issues/55#issuecomment-856830645

I think it will help make the library more flexible without adding a built in transformer. I can look into it but it will be some time before I can.

quarrant commented 2 years ago

It looks easy but.... I spent 3 or 4 hours to create something like serialize/deserialize functions and I can say that it's possible. But so far I couldn't create right typings for these interfaces through all code...

quarrant commented 2 years ago

Anyway, I will spend 1 or 2 weeks more to create this feature

RyoukoKonpaku commented 2 years ago

@codeBelt I definitely think it would. And yeah overall that comment on #55 definitely is similar to what I'd want.

@quarrant Thanks for looking into it, I have a fork with the feature and yeah I agree it's pretty hard to make the typings work as intended for the serialize / deserialize functions. Currently the fork it's typed as any as an escape hatch but I'll probably try take another stab on the typings when I get some free time.