Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

structr

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

structr

Clean OO structure for Javascript.

  • 0.2.4
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

Structr - Structure for Javascript

Structr is a framework with the following goals:

  • Lightweight.

Fast.

  • Provide as few new concepts as possible coming from OOP.
  • Easy to learn.
  • Help develop re-useable, clean, and consistent code.
  • Reduce the amount of reduntant/boilerplate code.

Supported Operators:

  • _super
  • inheritance
  • overloading methods
  • Implicit / Explicit getters & setters
  • Override, and Static
  • abstract methods
  • add your own custom operators (mixins)

Third-party mixins

  • asyngleton - asynchronous singletons
  • step

Installation

Node.js:

npm install structr
	   
	

.structr([...parents], classObject)


var EventEmitter = require("events").EventEmitter,
structr          = require("structr");
 
/**
 * create a mouse class which extends the node.js event emitter
 */

var Mouse = structr(EventEmitter, {  

	/**
	 */

	"__construct": function() {
		this._super();

		//initial coords
		this.move(0, 0);
	},

	/**
	 * moves the mouse
	 */

	"move": function(x, y) {
		this.position({ x: x, y: y});
	},

	/**
	 * second version of move incase an object is provided
	 */

	"second move": function(position) {
		this.position(position);
	},

	/**
	 * getter / setter for the position
	 */

	"explicit position": {
		"get": function() {
			return this._position;
		},
		"set": function(value) {
			this._position = value;
			this.emit("move");
		}
	} 
});                      

var mouse = new Mouse();

//listen for when the mouse has moved
mouse.on("move", function() {
	console.log("mouse moved!");
})

//move 100 px left, and 100 px from the top
mouse.move(100, 100);

Class.extend(target, [...mixins]);

Extends a class


var fs  = require("fs"),
structr = require("structr"),
mkdirp  = require("mkdirp"),
path    = require("path");

//mixin the singleton plugin
structr.mixin(require("asyngleton"));

/**
 * base cache interface
 */

var AbstractCache = structr({
	
	/**
	 * returns a cached value
	 */

	"abstract get": function(key, onGet) { },

	/**
	 * sets a cached value
	 */

	"abstract set": function(key, value, onSet) { }
});

/**
 * memory cache
 */

var MemoryCache = AbstractCache.extend({
	
	/**
	 */

	"__construct": function() {
		this._collection = {};
	},

	/**
	 */

	"get": function(key, onGet) {
		onGet(null, this._collection[key]);
	},

	/**
	 */

	"set": function(key, value, onSet) {
		this._collection[key] = value;
		if(onSet) onSet(null, value);
	}
});


/**
 */

var FsCache = MemoryCache.extend({
		
	/**
	 */

	"override __construct": function(path) {
		this._path = path;
		this._super();
	},

	/**
	 */

	"override set": function() {
		this._super.apply(this, arguments);
		this._save();
	},

	/**
	 */

	"override get": function(key, onKey) {
		var _super = this._super;

		//load the fs cache before getting the value - this only happens ONCE 
		//since _load is an asynchronous singleton.
		this._load(function() {
			_super(key, onKey);
		});
	},


	/**
	 * saves the collection to disc
	 */

	"_save": function() {
		if(this._saving) return;
		this._saving = true;

		var self = this;

		//make the directory incase it doesn't exist. 
		this._mkdir(path.dirname(this._path), function() {

			//write the json file, with the json content
			fs.writeFile(self._path, JSON.parse(self._collection), function(err result) {

				//give some time before unlocking the save method. 
				//We don't want to hit fs.write on each set
				setTimeout(function() {
					self._saving = false;
				}, 2000);
			});
		});
	},

	/**
	 * loads the fs cache into memory
	 */

	"singleton _load": function(onLoad) {
		try {
			this._collection = require(this._path);
		} catch(e) {
			//do nothing - the file doesn't exist
		}
		onLoad();
	},

	/**
	 * makes the fs cache directory incase it's nested. Only happens ONCE on save.
	 */

	"singleton _mkdir": function(onMkdir) {
		mkdirp(path.dirname(this._path), onMkdir);
	}
});


var cache = new FsCache(__dirname + "/test.json");


cache.get("name", function(err, name) {

	if(name) {
		return console.log("hello %s!", name);
	}

	cache.set("name", "craig", function() {
		console.log("saved!");
	});
});

Modifiers

Overriding Methods

Methods overridden have access to the _super property.


"override __construct": function ()
{
	this._super();
}

Overwriting Methods

Faster if you don't plan on using _super.


"__construct": function ()
{
	//cannot access _super __construct
}

Overloading Methods (Experimental)

Overloading methods allows you to write methods which are mapped out depending on the number of parameters used. You must provide your own identifier (it could be anything) for each overloaded method, otherwise you'll simply be overwriting methods. For this example, I separate methods based on their order, e.g. one, two, three, etc.


var Person = Structr({

	"sayHello": function (name, callback)
	{
		this._name = name;
		this.sayHello(callback);
	},

	"second sayHello": function (callback)
	{
		callback(this.sayHello());
	},

	"third sayHello": function ()
	{
		return 'Hello ' + this._name;
	}
});

var SubPerson = Person.extend({

	"override sayHello": function (callback)
	{
		callback(this.sayHello() + " Do you like italian food?");
	},

	"override second sayHello": function ()
	{
		return "Hello " + this._name + ", how are you doing today?";
	}
});


var p = new SubPerson();
p.sayHello("Craig", function(message)
{
	alert(message); //Hello Craig. how are you doing today? Do you like italian food?
});

Static Keyword

Properties, and methods set to the class versus objects instantiated.


var Singleton = Structr({
	
	"static getInstance": function ()
	{
		return this._instance || (this._instance = new Singleton());
	}
});

var test1 = Singleton.getInstance();
var test2 = Singleton.getInstance();
test2.name = 'Craig';

console.log(test1.name); //Craig

Getters & Setters

Both Implicit / Explicit methods are supported, however implicit getters & setters aren't supported in all browsers. Use implicit get/set if you're doing any development under a specific platform such as Node.js, or Appcelerator Titanium.


var GSTestClass = Structr({

	"explicit explicitValue": {
		"get": function ()
		{
			return this._name;
		},
		"set": function (value)
		{
			this._name = value;
		}
	},
	
	"implicit implicitValue": {
		"get": function ()
		{
			return this._name;
		},
		"set": function (value)
		{
			this._name = value;
		}
	},
	
	"explicit explicitValue2":true
});


var test = new GSTestClass();
test.explicitValue('Craig'); 
console.log(test.explicitValue());

test.implicitValue = 'Tim';
console.log(test.implicitValue);//Tim
console.log(test.explicitValue());//Tim

test.explicitValue2('hello world');
console.log(test.explicitValue2());//hello world
	

Metadata

Custom modifiers are considered metadata. Use them to identify how specific methods should be handled.



var MetadataTestClass = Structr({
	
	"myCustomMetadata test": function ()
	{
		return "Hello Test";
	}
}));


console.log(MetadataTestClass.prototype.test.myCustomMetadata); //true

###Bindable Metadata

To add. Makes a property bindable for change. Psuedocode:


var Person = Structr({
	
	"__construct": function(name)
	{
		this.name(name);
		
		Bindable.apply(this);
	},
	
	"bindable explicit name": 1
});


var person1 = new Person("craig");

//listen for any change to name
person1.name.subscribe(function(newName)
{
	alert('Name changed to '+newName);
});

//on change the subscribers will be triggered
person1.name("Craig");

###Setting Metadata

To add. Easy way to store settings on the user's computer. Psuedocode:


var User = Structr({

	"__construct": function ()
	{
		SettingManager.apply(this);
	},
	
	"login": function ()
	{
		
		//set the account info which will be saved as a cookie
		this.accountInfo({ name: "Craig", last: "Condon", token: "XXXXXXXXXX" })
	},
	
	"setting explicit accountInfo": 1
});


var u = new User();

//this gets passed once
if(!u.accountInfo)
{
	u.login();
}
else
{
	//pulled from local computer
	alert(u.accountInfo.name);
}

Tips:

  • Wrap methods / properties in single, or double quotes.
  • Avoid the over-use of override, or overloaded methods.
  • Only use Structr where you would create prototyped classes.

To Do:

  • change _super(...) to _super({ method: [args] }), or _super('method').call(...);

FAQs

Package last updated on 17 Oct 2013

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc