thinknimble / tn-models

Pure JavaScript library for creating data model and API services to support front end applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ThinkNimble Models for Client-Side Apps

Installation

npm install @thinknimble/tn-models

Model Class

The Model class is the main class that data models are built out of they contain all the logic for a class instance and usually will wrap the api class to provide a full structure for use across the project.

To define a model simply extend the base Model Class adding in fields as static arguments to the model. Behind the scenes the constructor will pick up properties defined as fields and inject them into the class as internal properties. Only fields defined here will be collected and injected other static methods, getters and properties can be included and will override the defaults if they are already defined.

Simple Model

class UserModel extends Model {

    static id = new fields.CharField({readOnly:true})
    static firstName = new fields.CharField()
    static lastName = new fields.CharField()
    static age = new fields.IntegerField()
}

Recommended Model

class UserModel extends Model {

    static api = UserAPI.create(UserModel)

    static id = new fields.CharField({readOnly:true})
    static firstName = new fields.CharField()
    static lastName = new fields.CharField()
    static age = new fields.IntegerField()
}

Above is the recommended structure to follow when creating a model for a service. Injecting the api class directly in your model results in a single datastructure to work with api calls from django. The api mehtod (see bellow) is statically defined from an api class that extends the ModelAPI structure. It has built in methods for common api calls made. To over ride these methods just re-define them

ModelAPI

Basic Usage

Class UserAPI extends ModelAPI{

    static ENDPOINT = '/user/'

    get client(){
        return <axiosClient>
    }

}

This is all that is required to set up an api class, the client to use and the static endpoint

Additional set up

Class UserAPI extends ModelAPI{

    static ENDPOINT = '/user/'

    // extend additional filters using the ApiFilter class

    static FILTER_MAP = {...UserAPI.FILTER_MAP, organization: ApiFilter.create({key:'organization'})}

    get client(){
        return <axiosClient>
    }

    // override existing method retrieve

    retrieve(id){
        //content
    }



}

Method/Property fn call Args description
getFields() this.constructor.getFields() Iterates over static properties and extracts the ones that use the Field Class. This will return a list of fields that can be retrieved directly as properties of the class and stores them in a private property called _fields **Note this method is used internally and should be considered private**
getReadOnlyFields this.constructor.getReadOnlyFields() Iterates over static properties and extracts the ones that use the Field Class and are defined as readOnly. This will return a list of fields that can be retrieved directly as properties of the class and stores them in a private property called _fields.
**Note this method is used internally and should be considered private**
fromAPI ModelClass.fromAPI() json={} Iterates over provided object and calls the ModelClass.create() method with the objectToCamelCase method applied to it return an instance of the ModelClass.
toAPI ModelClass.toAPI() obj,fields=[],excludeFields=[] Iterates over provided object and calls the objectToSnakeCase method, this will also remove the _fields and any readonly or exclude fields, if fields argument is passed will only include specified fields (still removing all readOnly or excluded fields, useful for partial updates.
toAPI ModelClass.toAPI() obj,fields=[],excludeFields=[] Iterates over provided object and calls the objectToSnakeCase method, this will also remove the _fields and any readonly or exclude fields, if fields argument is passed will only include specified fields (still removing all readOnly or excluded fields, useful for partial updates.
createCollection ModelClass.createCollection() opts Helper method to create a collectionManager instance of a class (instead of manually doing so by importing the CollectionManager) by default the ModelClass is set to this and will override the model class passed in through opts if one is present

ApiFilter Class

This class creates filters for requests in a consistent structure, to define a new filter add it to the filter maps and declare it with a new ApiFilter class. This filter class will only add filters if there are values and will ommit them by default if they do not. This removes the need to add additional if else checks*.

Note this is a default behavior if you need null as a value you will need to manually define a filter on the method

Method/Property fn call Args description
static create ModelClass.create() cls Factory function that creates a wrapper for ModelClass when called from ModelClass (static api = ModelAPI.create(cls)) Most built in methods require the presence of a class which include the to and from api methods
FILTERS_MAP ModelAPI.FILTERS_MAPS Creates a filters object, by default page, pageSize and ordering are included using the ApiFilter Class. To add additional opts spread the object static FILTERS_MAP ={...ModelAPI.FILTERS_MAP}
client get Client() This getter supplies the client to be used for requests and is required if none is provided an error will be thrown
list ModeClass.api.list()
ModelAPI.list()
filters={}, pagination={} Calls the list method to the api (if this does not exist this will fail) and calls the fromAPI method from the inheriting class
***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class
create ModeClass.api.create()
ModelAPI.create()
obj,fields=[],excludeFields=[] Calls the create method to the api (if this does not exist this will fail) and calls the fromAPI method from the inheriting class
***Note this is different from the static create (factory function) ***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class
retrieve ModeClass.api.retrieve()
ModelAPI.retrieve()
id Calls the retrieve endpoint of a view
***Note the buil in method requires use of the recommended strucutre and calls this.cls.fromAPI() which refers to the model class

Collection Manager

The Collection Manager creates a list collection of a model and is included by default as part of the list method in the ModelAPI, this creates a consistent model for listing resources from the api. It includes default handling for pagination and creates a model out of the results.

Pagination Class

The pagination class is modeled of the expected django drf paginated queryset but can be easily adpated to work with any (page pagination). This class is automatically applied to the default list method in the ModelAPI class through the collection manager and is applied as filters by default in the FILTER_MAPS

Fields Class

All field types extend the base Field class, they inherit the methods clean(value) (which type casts the value if it is not null/undefined) and getDefaultVal(value) which returns the default value provided (also accepts a function)

Custom Classes can be created on the fly by extending the Field class

NB ArrayField requires type to be of class Field and initialized as it calls the clean method (it can also be of any other class interface as long as it has the clean method)

NB ModelField requires ModelClass to be a (defined) Class (uninitialized) and should use the Model Class but can be any class which calls toAPI

field class parameters description
CharField new CharField() readOnly creates a new char field, properties are optional ( defaults: false)
IdField new IdField() defaultVal, readOnly creates a new id field, properties are optional ( defaults: random generated id, false)
BooleanField new BooleanField() defaultVal, readOnly creates a new Boolean field, properties are optional
IntegerField new IntegerField() defaultVal, readOnly creates a new Integer field (accepts floats as well), properties are optional
ArrayField new ArrayField({type: new IntegerField()}) defaultVal, readOnly, type* creates a new Array field, properties defaultVal and readOnly are optional ( defaults: null, false) type is required and must be a initiated Field Class (new IntegerField() ) type
ModelField new ModelField({ModelClass: SomeTnModel }) defaultVal, readOnly, many, ModelClass* creates a new Model field, properties defaultVal and readOnly are optional ( defaults: null, false, false) Model Class is required and must Class Tpye (Not a class Insance), many here will map and call the fromAPI method

About

Pure JavaScript library for creating data model and API services to support front end applications.

License:MIT License


Languages

Language:JavaScript 100.0%