This framework is based loosely on the api of laravel, trying to replicate the routing, models, controllers and templates using node and mongodb for storage. Any large running processes like dealing with large arrays is delegated to a separate web workers so node will be able to manage a high number of users without breaking a sweat.
package: Request
Routing for the application uses regular expression pattern matching allowing you to specify your own url patters and the controllers that handle the request.
Routes are defined in app.js
. They allow you to define the way the framework processes your request and delegate the functionality to a controller or to a method of a controller.
Request.get( controller, urlpattern );
Request.post( controller, urlpattern );
Request.put( controller, urlpattern );
Request.patch( controller, urlpattern );
Request.delete( controller, urlpattern );
when specifying your route you can tell the framework that you intend to pull a value from the url and use it in your request.
To do so you simply need to prepend the url slug with a colon eg ':capture'
.
If you need to fire a different callback for a different type you can specify it before the colon eg. 'string:capture'
you can use string|int
when declaring the type.
Request.get('/user/:id', function( id ){
// do something with the id
});
You can specify multiple routes at the same time with the routes
method. You need to provide an array of routes that target methods on the controller.
Request.routes( namespace: string, controller: String, routes: Array )
Request.routes('user', 'UserController', [
['GET', 'index', ''],
['GET', 'show', '/:id'],
['POST', 'store', '/:id'],
[...]
]);
| param | type | example | description
| namespace | String |'user'
| using a namespace will wrap the routes under a common parent |
| controller | String | 'UserController'
| a string identifier of the controller that will handle the request |
| routes | Array | [['request method', 'controller method', 'url pattern']]
| a multidimensional array that holds the routes |
this method will create all the standard restful routes, get, post, put, patch, delete, and allow you to add additional routes using a routes array
Request.restful( namespace: string, controller: String, routes: Array )
the framework uses on ORM to manage relationships between data object so you don't ever need to touch mongo if you don't need anything more complicated that most standard queries, but you can get deep into mongo if you need to.
To make creating models that inherit from the Model class the elegant
factory has been created to streamline the process, while giving you access to extend your models with any desired behavior you require.
var MyClass = elegant( constructor, instance, methods, errorHandlers );
var MyClass = elegant(
function MyClass(){
this.__proto__.constructor.call( this );
},
function myclass(){},
{
relation: elegant.hasOne('Relation')
},
{
set: function setErrorHandler( err ) { ... }
get: function getErrorHandler( err ) { ... }
}
);
./lib/models.js
;
elegant.hasMany( model, foreign, primary );
elegant.hasOne( model, foreign, primary );
elegant.belongsTo( model, foreign, primary );
Extending the Model
class through elegant
will make your class inherit all of it's functionality.
Model.find( id );
Model.all();
Model.exists( key );
Model.missing( key );
Model.between( key, min, max );
Model.larger( key, value );
Model.where( query );
Model.limit( max );
Model.skip( count );
Model.not( ...columns )
Model.get( ...columns );
Model.attach( obj );
Model.save();
// the following methods will tell the framework that your query is
// finished being built and it's time to get the data from mongo
Model.success( callback );
Model.toArray( callback );
Model.toObject( callback );
Model.toCursor( callback );
Model.toStream( callback );
Model.toInstance( callback );
// perform an action on the database but don't wait for a response
Model.exec();
Methods on the model modify the underlying query object that get's passed to the mongo instance.
By default models are fluent, so all query parameters can be chained to mutate the query object in a predictable way.
retrieve a document from a collection by the id provided.
retrieve all documents from a collection in mongo
include documents from a collection where key
exits in the document
include documents from a collection where key
does not exist in the document
include documents from a collection where a key
is between the min
and max
values
include documents from a collection where key
as a value larger than max
include documents where query
passes. query
can be any mongo query
Limit will stop the mongo collection results from being larger than max
Skip is used in pagination to allow you to seperate large result sets into smaller more manageable ones.
get will whitelist the parameters that will be returned
not will blacklist the fields that are returned
attach will look to the model for a relationship, asynchronously perform the query and attach the result to the current response.
save will tell the framework that the model it's called on should save it's internal state to mongo
Success will fire the mongo query and on success it will return an array of results
Model.success(( results ) => {
results.map( ( result ) => { ... } );
});
find 10
users whose age is greater than 31
but skip the first 5 results
User
.larger('age', 31)
.not('password')
.limit(10)
.skip(5)
.success(function( result ){
// do something with the result
});
as well as using the native methods you can invoke joins between data structures that you have declared when you constructed your Model class
find all 'posts'
by the user with an id of 1
User
.find(1)
.posts()
.toArray(function( result ){
// do something with the users posts
});
find the user with id of 1
and attach all their 'posts'
to the response
User
.find(1)
.attach('posts')
.toInstance(function( result ){
// do something with the users posts
});
constrollers are used to handle the functionality for a route. They have automatic dependancy injection if you specify more than the required arguments.
The following are the standard restful methods that will be called if you use the Request.restful
method to create your routes
{
index: function( req, res, Template, injectModules... ) {
return function(){ ... }
},
create: function( req, res, Template, injectModules... ) {
return function(){ ... }
},
show: function( req, res, Template, injectModules... ) {
return function( id ){ ... }
},
store: function( req, res, injectModules... ) {
return function( params ){ ... }
},
edit: function( req, res, Template, injectModules... ) {
return function( id ){ ... }
},
update: function( req, res, Template, injectModules... ) {
return function( id ){ ... }
},
destroy: function( req, res, injectModules... ) {
return function( id ){ ... }
}
}
The framework also includes a templating engine that has a twist. Once a template is parsed it's just transformed into a callable pure function. It's no react virtual dom, but it's pretty cool and very efficient for creating dynamic templates as compared to using just regex to replace placeholders in the template like mustache.
Template creation timestamps are also checked to see if the html template has changed since the last compile while the framework is in developer mode. If the file has changed the template function will be rebuilt ready for use.
The templating language is very basic, providing only variable replacement and forEach loops to allow printing collections of data. You can even run any javascript function in scope on the template variables.
{{include file='something.html'}}
<ul class="{{variable}}">
{{foreach things as thing}}
<li>
<span>{{someFunction(thing.variable)}}</span>
</li>
{{/foreach}}
</ul>
the filenames with the routes are dependent on being called the same thing as their controller method.
- public
-- templates
-- {{ module }}
--- index
--- show
--- list
--- create
--- edit