Nightly Procrastination Machine

    @postmates/front

    1.0.15 • Public • Published

    front

    A package that desperately needs to be renamed

    Overview

    This package contains the Model and ModelListener classes that make up the core of how data is passed around Postmates. Model sets up a living data contract between frontend services, transforming and validating data, sending events on changes, and setting up rules for model hierarchy and initialization. ModelListener is a wrapper around React.Component that takes over the duty of storing information on the view layer and keeps it in the model layer, setting up binding routes on the way. Any time a model updates, the view updates, and the view can send information to the model to allow it to modify the underlying data model. Setting all this up removes the siloing of data structure definition in the view (props) and allows that structure to be used in services, api calls, application logic, etc.

    Model

    Model has a simple interface, all documented in the source code, but sometimes examples are easier to parse. The most basic constructor looks like this:

    class MyFirstModel extends Model {
    	constructor(data) {
    		super({
    			id: 0,
    			name: ''
    		});
    
    		this.fill(data);
    	}
    }

    This example creates a model called MyFirstModel that defines it having the fields id and name with default values and hydrates based on it's constructor parameters.

    hierarchy

    You can add hierarchy to models by including the class name as a default parameter:

    class Name extends Model {
    	constructor(data) {
    		super({
    			first: '',
    			last: ''
    		});
    
    		this.fill(data);
    	}
    
    	fullName() {
    		return this.first + ' ' + this.last;
    	}
    }
    
    class Permission extends Model {
    	constructor(data) {
    		super({
    			id: 0,
    			code: '',
    			name: ''
    		});
    
    		this.fill(data);
    	}
    }
    
    class AuthUser extends Model {
    	constructor(data) {
    		super({
    			name: Name,
    			perms: [ Permission ]
    		});
    
    		this.fill(data);
    	}
    
    	can(perm) {
    		for (var i = 0; i < this.perms.length; i++) {
    			if (this.perms[i].code === perm) {
    				return true;
    			}
    		}
    
    		return false;
    	}
    }
    
    var MyAuth = new AuthUser({
    	name: {
    		first: 'super',
    		last: 'dev'
    	},
    	perms: [{
    		id: 12,
    		code: 'delete',
    		name: 'User can delete posts'
    	}, {
    		id: 64,
    		code: 'edit',
    		name: 'User can edit posts'
    	}]
    });
    
    console.log(MyAuth.can('edit')); // outputs true
    console.log(MyAuth.name.fullName()); // outputs 'super dev'

    inheritance

    If you want to inherit from a model, you can use the extend function:

    class Animal extends Model {
    	constructor(data) {
    		super({
    			species: '',
    			name: ''
    		});
    
    		this.fill(data);
    	}
    }
    
    class LoudAnimal extends Animal {
    	constructor(data) {
    		super().extend({
    			sound: '',
    			level: 0
    		});
    
    		this.fill(data);
    	}
    }

    transformation

    Sometimes data doesn't always come in clean. Sometimes you want to represent your data differently inside of your application logic than outside. There are even times when you have to take a data format and tear it to a million pieces to make it work. You can do this by overwriting the model's fill function. The out function works exactly the same, but in reverse.

    class MyFirstTransform extends Model {
    	constructor(data) {
    		super({
    			name: '',
    			itemCount: 0
    		});
    
    		this.fill(data);
    	}
    
    	fill(data) {
    		if (!data) {
    			return this;
    		}
    
    		if (data.hasOwnProperty('items')) {
    			data.itemCount = data.items.length;
    			delete data.items;
    		}
    
    		super.fill(data);
    		return this;
    	}
    }

    ModelListener

    The point of the ModelListener is to be as transparent as possible. If you want to reuse your data layer across your application, you need only to extend from ModelListener instead of React.Component and pass that data contract as prop model. This will instantly send all model updates to the view using the model's internal dirty flag and rate limiter. Lets look at a simple example:

    class MyComponent extends ModelListener {
    	static defaultProps = {
    		model: MyFirstModel
    	};
    
    	render() {
    		return <div>{ this.model.name }</div>
    	}
    }
    
    React.createElement(<MyComponent model={ { name: 'super dev' } } />);

    A two way street

    The ModelListener also provides a way to update your model from the view through the update function. Here we are pumping the value from the input field into the model's name field.

    class MyComponent extends ModelListener {
    	static defaultProps = {
    		model: MyFirstModel
    	};
    
    	update(field, evt) {
    		super.update(field, evt.target.value);
    	}
    
    	render() {
    		return (
    			<input defaultValue={ this.model.name }
    				onChange={ this.update.bind(this, 'name') } />
    		);
    	}
    }

    Install

    npm i @postmates/front

    DownloadsWeekly Downloads

    0

    Version

    1.0.15

    License

    MIT

    Unpacked Size

    32.6 kB

    Total Files

    9

    Last publish

    Collaborators

    • mager
    • postmates-frontend
    • apapirovski
    • mnowik
    • postmates-fleet
    • cvanderschuere