0.8.31 • Published 3 years ago

mobx-store-model v0.8.31

Weekly downloads
112
License
ISC
Repository
github
Last release
3 years ago

Overview

This is the best model/store library for mobx.

All your crud and lifecycle events managed for a store and for a model

Setup

You need to setup your base url before anything fires

will default to local server and port

import { Service } from 'mobx-store-model';

Service.setBaseUrl('https://jsonplaceholder.typicode.com');

In your store.ts

import { Store, Model, Loader } from 'mobx-store-model';
class Todo extends Model {
  route = 'todos';
}

class Post extends Model {
  route = 'posts';
}

class HomeStore {
  // Second param passed to store is the name used to hydrate
  todos = new Store(Todo, 'todos');
  posts = new Store(Post, 'posts');
  constructor() {
    // LIFECYCLE EVENTS
    // Fires on load from api call
    this.todos.on('after load', () => console.log('AFTER TODOS ARE LOADED'));

    // This method requries you calling store.setHydrated() after hydrating from mobx-persist
    this.todos.on('after hydrate', () => console.log('AFTER TODOS ARE hydrated'));

    // This method is fired if hydration is setup
    // Fires after hydrate and load are complete
    this.todos.on('ready', () => console.log('AFTER TODOS ARE ready'));

    // Alternatively you can check flags
    /*
      ## load flags

      - hydrated: boolean;
      - initLoaded: boolean;
      - ready: boolean;

      ## fetch flags

      - fetchingData: boolean;
      - fetchFailed: boolean;
      - fetchSuccess: boolean;
      - defaultFetchFailedMessage: string;

      ## save flags

      - savingData: boolean;
      - saveSuccess: boolean;
      - saveFailed: boolean;

      ## delete flags

      - deleteSuccess: boolean;
      - deleteFailed: boolean;
      - deleteFailedMessage: string;
    */

    setTimeout(() => this.start(), 0);
  }

  async start() {
    await this.todos.refreshData(); // Calls getData() and adds data to this.objects
    await this.posts.refreshData();

    console.log(this.todos.objects);
    // [{title: '...'}, ...]
    console.log(this.posts.objects);
    // [{title: '...'}, ...]

    // METHODS
    await this.todos.getData(); // GET /todos -- you can pass a custom route or get params if you want (DOES NOT PUT DATA ON this.objects, ONLY RETURNS DATA)
    await this.todos.create({ title: '...' }); // POST /todos
    await this.todos.delete(this.todos.objects[0].id); // DELETE /todos/{id}  -- removes from this.objects
    await this.todos.udpate(this.todos.objects[0]); // PATCH /todos/{todo.id}

    // Dealing with current
    // Current is a concept when you have multiple pages or parts of app dealing/modifying a single model
    this.todos.setCurrent(this.todos.objects[0]);
    await this.todos.saveCurrent(); // if current has id, it will call create else it will call update
    await this.todos.createCurrent(); // .create(this.current)
    await this.todos.updateCurrent(); // .update(this.current)
    await this.todos.deleteCurrent(); // .delete(this.current.id)
    this.todos.resetCurrent(); // resets current data (if modified) and resets current to blank model

    // E.X.
    // This is how you modify current
    // this.todos.current.title = 'new title';
    // this.todos.saveCurent();

    await this.todos.getById(1); // Will check objects for todo and hit end point if it can't find
    this.todos.getByIdSync(1); // Will ONLY check objects for todo
    this.todos.getMultipleById([1, 2]); // Will ONLY check objects for todos
    this.todos.search({ username: 'bob' }); // GET /todos s={username: 'bob'} -- Will ONLY work with NESTJS CRUD

    // MODEL METHODS
    const todo = this.todos.objects[0];
    todo.reset(); // if it's been modified but not saved
    await todo.save(); // if id exists will do update, otherwise will create
    await todo.create(); // POST /todos
    await todo.udpate(); // PATCH /todos/{this.id}
    await todo.delete(); // DELETE /todos/{this.id}
    await todo.refresh(); // GET /todos/{this.id}  --- overrides object with latest from db
  }
}

export const Home = new HomeStore();

// If store doesn't have a name you have to pass name as second param
Loader.registerStore(Home.todos, 'todos');
Loader.registerStore(Home.posts, 'posts');
// If store was passed name and you don't want to define multiple registers
Loader.registerStores([Home.todos, Home.posts]);
Loader.init(); // this will fire refreshData and hydrate the store

You can use mobx class as store as well

import { Store, Model, Loader } from 'mobx-store-model';
class Todo extends Model {
  route: string = 'todos';
}

class HomeStore extends Store {
  name: string = 'home';
  constructor() {
    super(Todo);
  }

  start() {
    console.log(this.objects); // [{title: '...'}]
    // All the same methods from above are available here as well
    // I.E.
    this.setCurrent(this.objects[0]);
    this.saveCurrent();
  }
}
export const TodoStore = new Todo();
Loader.registerStore(TodoStore);
Loader.init();

Store

loaded data from server

objects: any[];

load flags

  • hydrated: boolean;
  • initLoaded: boolean;
  • ready: boolean;

fetch flags

  • fetchingData: boolean;
  • fetchFailed: boolean;
  • fetchSuccess: boolean;
  • defaultFetchFailedMessage: string;

save flags

  • savingData: boolean;
  • saveSuccess: boolean;
  • saveFailed: boolean;

delete flags

  • deletingData: boolean;
  • deleteSuccess: boolean;
  • deleteFailed: boolean;
  • deleteFailedMessage: string;

requires a class (it gets instantiated)

constructor(model: any);

calls get data and puts data on this.objects

refreshData(): Promise;

called after loaded from endpoint

afterLoad(): void;

called after hydrated and loaded

isReady(): {};

called after hydrate from localstorage

this is called if you regester the store in loader

afterHydrate(): {};

calls get endpoint

opts - {

route: string - adds to route of the current store,

params: object - this is a nest crud params object that converts to a query string documentation can be found at the bottom of this page https://github.com/nestjsx/crud/wiki/Requests#select

}

getData(opts?: any): Promise;

calls create endpoint

create(data: any): Promise;

calls update endpoint

update(data: any): Promise;

calls delete endpoint

delete(id: number): Promise;

checks if id exists, if so calls updateCurrent else createCurrent

if passed false does not call resetCurrent

saveCurrent(dontReset?: boolean): Promise;

sends post to create, calls resetCurrent, add

if passed false does not call resetCurrent

createCurrent(dontReset?: boolean): Promise;

sends post to update, calls resetCurrent, add

if passed false does not call resetCurrent

updateCurrent(dontReset?: boolean): Promise;

sends post to delete, calls resetCurrent

deleteCurrent(): Promise;

resets current to empty model

resetCurrent(): void;

sets current with new model and object passed to it

setCurrent(item?: any): void;

searches objects and calls getData for id

useful incase the object isn't in objects

getById(id: number): Promise;

searches objects by id

getByIdSync(id: number): any;

searches objects by list of ids

getMultipleById(ids: any[]): any[];

takes object and hits get endpoint

{name: 'bob'}

calls getData

search(obj: any): Promise;

deletes any null or undefined properties on an object

cleanObject(obj: any): any;

adds object to objects

if object exists in this.objects it will mix with it (searched by id or model.objectKey)

add(obj: any): void;

removes object from objects based off id or if model has objectKey set, will search by that

remove(obj: any): void;

Model

fetch flags

  • fetchingData: boolean;
  • fetchFailed: boolean;
  • fetchSuccess: boolean;

save flags

  • savingData: boolean;
  • saveSuccess: boolean;
  • saveFailed: boolean;

delete flags

  • deletingData: boolean;
  • deleteSuccess: boolean;
  • deleteFailed: boolean;

api endpoint (posts, users/posts)

route: string;

query params for requests ({join: 'user', 'post'})

getParams: any;

used to clean up data for saving ('metadata')

propsToDeleteForSave: string[];

used for forms to show if the object is being edited

editable: boolean;

lifecycle flag

saved: boolean;

check if model is dirty based off saved/original data

isDirty({exclude: ...props}? any): boolean;

this method mixes data with current class Object.assign(this, data);

init(data: any): void;

method used to convert any data prior to save @override

convertForSave(data?: any): object;

method used to convert data after loaded from endpoint @override

convertFromLoad(): void;

resets any changes

reset(): void;

checks if there is an id and if so fires create else update

save(): Promise;

POST => endpoint from route

create(): Promise;

PATCH => endpoint from route

update(): Promise;

DELETE => endpoint from route

delete(): Promise;

GET => endpoint from route

refresh(): Promise;

takes an object and returns query string

{s: {name: 'bob'}}

?s={"name":"bob"}

constructGetParams(obj: any): string;

if you have any other stores you want data from use this method, it should be ran after all stores are ready @override

this is called automatically if you use the loader

getDataFromStores(): void;

Loader

this is managed with mobx-persist using localForage for storing local data

Adds the store to loader

name either has to be passed in here or as a property on the store

registerStore(Store, name?) registerStores(Store, Store) // Store must have name on it

This will fire refreshData on all the stores,

call getDataFromStores from all objects downloaded

init()

0.8.31

3 years ago

0.8.30

3 years ago

0.8.29

3 years ago

0.8.27

3 years ago

0.8.26

3 years ago

0.8.28

3 years ago

0.8.23

3 years ago

0.8.25

3 years ago

0.8.24

3 years ago

0.8.22

3 years ago

0.8.21

3 years ago

0.8.19

3 years ago

0.8.18

3 years ago

0.8.16

4 years ago

0.8.17

4 years ago

0.8.14

4 years ago

0.8.15

4 years ago

0.8.13

4 years ago

0.8.12

4 years ago

0.8.11

4 years ago

0.8.10

4 years ago

0.8.9

4 years ago

0.8.7

4 years ago

0.8.6

4 years ago

0.8.5

4 years ago

0.8.4

4 years ago

0.8.1

4 years ago

0.8.0

4 years ago

0.8.3

4 years ago

0.7.40

4 years ago

0.7.39

4 years ago

0.7.38

4 years ago

0.7.35

4 years ago

0.7.37

4 years ago

0.7.34

4 years ago

0.7.33

4 years ago

0.7.32

4 years ago

0.7.31

4 years ago

0.7.30

4 years ago

0.7.29

4 years ago

0.7.28

4 years ago

0.7.27

4 years ago

0.7.11

4 years ago

0.7.19

4 years ago

0.7.18

4 years ago

0.7.15

4 years ago

0.7.14

4 years ago

0.7.17

4 years ago

0.7.16

4 years ago

0.7.24

4 years ago

0.7.23

4 years ago

0.7.25

4 years ago

0.7.1

4 years ago

0.6.67

4 years ago

0.6.66

4 years ago

0.6.65

4 years ago

0.6.64

4 years ago

0.6.63

4 years ago

0.6.61

4 years ago

0.6.60

4 years ago

0.6.62

4 years ago

0.6.59

4 years ago

0.6.58

4 years ago

0.6.57

4 years ago

0.6.55

4 years ago

0.6.54

4 years ago

0.6.53

4 years ago

0.6.52

4 years ago

0.6.51

4 years ago

0.6.50

4 years ago

0.6.47

4 years ago

0.6.49

4 years ago

0.6.48

4 years ago

0.6.46

4 years ago

0.6.45

4 years ago

0.6.44

4 years ago

0.6.43

4 years ago

0.6.41

4 years ago

0.6.39

4 years ago

0.6.38

4 years ago

0.6.37

4 years ago

0.6.36

4 years ago

0.6.34

4 years ago

0.6.33

4 years ago

0.6.32

4 years ago

0.6.30

4 years ago

0.6.28

4 years ago

0.6.27

4 years ago