Category Filtering: 'nodejs'

gadget-ui v 7.0.0 - Part II - uploading images to a NodeJS app using FileUploader

gadget-ui, NodeJS, Open Source

In Part I of the look at the 7.0.0 release of gadget-ui, I discussed some of the new features of the library and provided some insight into the new NodeJS-based test system.  I left out the discussion of the new FileUploader example written in NodeJS. In short, the new NodeJS test system includes code to demonstrate the FileUploader functionality using NodeJS as a backend. While it isn't necessarily a production-ready solution, it should give you enough code to implement the FileUploader against a NodeJS server without any significant obstacles.


gadget-ui v 7.0.0 - Part I - NodeJS support

gadget-ui, NodeJS, Open Source

gadget-ui, my open source JavaScript component library, has reached a new milestone- v 7.0.0. This release contains several new features, the most significant of which have to do with NodeJS support. Recent versions of the library have required users to set up a CFML engine such as Lucee or ColdFusion to fully test all of the components in the library. The 7.0.0 release now includes a NodeJS-based solution for testing all of the library components.


The Altseven View Component and the Rendering Queue in 3.2.x

altseven, JavaScript, NodeJS, Open Source

As of altseven 3.2.x, I have made some changes to the way view components listen for changes and register for rendering with the render queue. The first changes come in the config() function inside the View component. The bubbling of mustRender events from child to parent has been removed. The render queue now tracks what components are being rendered and ensures that parent views are rendered before their children.

As a result, the setState() function in the View component now fires the mustRender event for all views, and the mustRender handler add the view to the queue.

setState: function( args ){
    this.state = args;
    // setting state requires a re-render
    this.fireEvent( 'mustRender' );
},

and the mustRender event handler, which now queues views for rendering:

this.on( "mustRender", function(){
    a7.ui.enqueueForRender( this.props.id );
}.bind( this ));

 

Essentially, the complexity of managing the rendering queue has largely been moved from the View component to the a7.ui component. Let's look at the enqueueForRender method. As with other methods in components in altseven, enqueueForRender references an internal component method, _enqueueForRender:

_enqueueForRender = function( id ){
  if( ! _stateTransition ){
    a7.log.info( 'enqueue: ' + id );
    if( ! _queue.length ){
      a7.log.trace( 'add first view to queue: ' + id );
      _queue.push( id );
      // wait for other possible updates and then process the queue
      setTimeout( _processRenderQueue, 18 );
    }else{
      let childIds = _getChildViewIds( id );
      if( _views[ id ].props.parentID === undefined ){
        // if the view is a root view, it should be pushed to the front of the stack
        a7.log.trace( 'add to front of queue: ' + id );
        _queue.unshift( id );
      }else{
        let parentIds = _getParentViewIds( id );

        let highParent = undefined;
        if( parentIds.length ){
          highParent = parentIds.find( function( parentId ){
            return _queue.indexOf( parentId ) >= 0;
          });
        }

        // only add if there is no parent in the queue, since parents will render children
        if( highParent === undefined ){

          a7.log.trace( 'add to end of queue: ' + id );
          _queue.push( id );
        }
      }

      // remove child views from the queue, they will be rendered by the parents
      childIds.forEach( function( childId ){
        if( _queue.indexOf( childId ) >= 0 ){
          a7.log.trace( 'remove child from queue: ' + childId );
          _queue.splice( _queue.indexOf( childId ), 1 );
        }
      });
    }
  }else{
    _deferred.push( id );
  }
},

First, let's see what variables we're using, and what they are doing. We have _stateTransition, which is a boolean value that tracks whether the current queue is rendering. If the queue is not rendering, the process will look to add the requested view to the queue, which is held in an array of string IDs in a variable called _queue. If the current queue is rendering, the view ID is instead added to another Array called _deferred. Once the current queue is rendered, _queue will be emptied and the IDs in _deferred will be added to _queue.

Next we have childIds, which holds an array of IDs of all child views of the current view being processed. The function uses this array to remove any child views of the current view from the rendering queue. Since parents render their own children by default using the rendered event handler, we don't want the children in the render queue or they will be rendered more than once.

We also have parentIds, which as you might expect holds an array of view IDs for the parents of the current view being processed, and highParent, which is the highest parent view in the chain of parentIds. We use these values in conjunction to verify that we do not add views to the queue if the view has a parent already in the queue. As with childIds, we only want to add the highest level view in a given subtree to the queue; we'll leave child view rendering to the rendered event handler.

_getChildViewIds and _getParentViewIds are functions that the enqueueForRender function calls to return these child and parent view ID arrays. Like much of the newest functionality in altseven, these functions do their jobs, but they are not optimized or expected to be particularly efficient. I don't expect deep nesting of view components in altseven apps, so I don't see optimization as a particular priority in this case.

As you can see at the beginning of the function, if the _queue.length property is 0, the function adds the view ID as the first element of _queue and then schedules the queued to be processed using setTimeout(). It leaves just enough time ( 18 ms ) for related views to register themselves for rendering as needed.

Processing the Rendering Queue

Let's look at _processRenderQueue.

    _processRenderQueue = function(){
      a7.log.trace( 'processing the queue' );
      _stateTransition = true;

      _queue.forEach( function( id ){
          _views[ id ].render();
      });
      _queue = [];
      _stateTransition = false;
      _deferred.forEach( function( id ){
        _enqueueForRender( id );
      });
      _deferred = [];
    },

Once the setTimeout function fires _processRenderQueue sets _stateTransition to true, which signals to _enqueueForRender that it should queue requested updates in the _deferred queue. It then iterates through _queue and calls the render() function for the given view ID in _views. What is significant here is that the array of views in _views is the original array that was registered by a7.ui.register(). Altseven works by registering all the views in the application, which places the views in this _views array for the duration of the application. Views are always referenced by this variable, which can be called outside the a7.ui component using the property a7.ui.views. Unlike early iterations of the framework, altseven 3.2.x does not pass views around or attempt to copy them. Once they are in a7.ui.views, that's where they stay until they are destroyed.

 

 


Embracing ReactJS-style UI rendering in altseven with ES6 Template Literals - Part III

altseven, JavaScript, NodeJS, Open Source

Update

------------

Parts of this post are no longer accurate, as altseven 3.2.x has changed the way components queue for rendering. See The Altseven View Component and the Rendering Queue in 3.2.x for updated information about the rendering queue.

------------

 

I first started building the altseven JavaScript framework in order to bring together various bits of functionality that I had built for earlier applications. I started with some general ideas about how I wanted to do things and a few tools in my toolbox with which to do them.

The Constructor

I had previously built a component to create objects in a consistent way, and I wanted to use its ability to bind custom events to created objects in altseven. The component creates objects using a given prototype and Object.create. It then assigns custom event handlers to the created object based on the object prototype. Let's look at the Constructor function:

function Constructor( constructor, args, addBindings ) {
	var returnedObj,
		obj;

	// add bindings for custom events
	// this section pulls the bindings ( on, off, fireEvent ) from the
	// EventBindings object and add them to the object being instantiated
	if( addBindings === true ){
		//bindings = EventBindings.getAll();
 		EventBindings.getAll().forEach( function( binding ){
			if( constructor.prototype[ binding ] === undefined ) {
				constructor.prototype[ binding.name ] = binding.func;
			}
		});
	}

	// construct the object
	obj = Object.create( constructor.prototype );

	// this section adds any events specified in the prototype as events of
	// the object being instantiated
	// you can then trigger an event from the object by calling:
	// <object>.fireEvent( eventName, args );
	// args can be anything you want to send with the event
	// you can then listen for these events using .on( eventName, function(){});
	// <object>.on( eventName, function(){ })
	if( addBindings === true ){
		// create specified event list from prototype
		obj.events = {};
		if( constructor.prototype.events !== undefined ){
			constructor.prototype.events.forEach( function( event ){
				obj.events[ event ] = [ ];
			});
		}
	}

	returnedObj = constructor.apply( obj, args );
	if( returnedObj === undefined ){
		returnedObj = obj;
	}
	//returnedObj.prototype = constructor.prototype;
	return returnedObj;
}

The Constructor function pulls the methods from the EventBindings mixin object. ( The mixin provides for a way to assign the methods of one object to an arbitrary object or prototype ). Next, if the given prototype has an array of events defined, the Constructor assigns those events to the generated object as bindable events.

When the Constructor is done, it returns an object with the methods and properties of the prototype, the on(), off(), and fireEvent() methods of the EventBindings mixin, and bindable events listed in the object prototype.

The View function

As of v. 3.x of altseven, the View function, which provides the base for rendered UI elements in altseven, has been expanded to handle some of the functionality that was centralized in the a7.ui.setView() method. The events for the View function:

events : ['mustRender','rendered', 'mustRegister', 'registered']

provide hooks for registering and rendering components, as well as hooks to execute functions when registration and rendering finish. View now has a prototype method called config that registers event handlers for these events:

	config: function(){

		this.on( "mustRegister", function( parent ){
			this.props.parentID = parent.props.id;
			a7.ui.register( this );
		}.bind( this ) );

		this.on( "mustRender", function(){
			// only render root views from here, children will be rendered by parents through bubbling of events
			if( this.props.parentID === undefined ){
				this.render();
			}
		}.bind( this ));

		this.on( "rendered", function(){
			this.onRendered();
		}.bind( this ));

		this.on( "registered", function(){
			// register children
			if( this.props !== undefined ){
				for( var prop in this.props ){
					if( this.props[ prop ] !== null && this.props[ prop ].type !== undefined && this.props[ prop ].type === "View" ){
						if( a7.ui.getView( this.props[ prop ].props.id ) === undefined ){
							this.props[ prop ].fireEvent( "mustRegister", this);
						}
					}
				}
			}
			if( this.props.parentID === undefined ){
				// only fire render event for root views, children will render in the chain
				this.fireEvent( "mustRender" );
			}
		}.bind( this ));

		// bubble up event
		if( this.props !== undefined ){
			for( var prop in this.props ){
				if( this.props[ prop ].type !== undefined && this.props[ prop ].type === 'View' ){
					this.props[ prop ].on( "mustRender", function(){
						this.fireEvent( "mustRender" );
					}.bind( this ));
				}
			}
		}
	},

We have four event handlers in the config() function corresponding to our four events- mustRegister, mustRender, registered, and rendered. I've thought about making views self-registering, so every view, when instantiated, would fire mustRegister. At the moment, views in the root of a DOM subtree  (those with no parents in altseven) must be registered manually, while children of root views are registered automatically when the root view handles the registered event, as you can see above. I am assigning a parentID to child views in each DOM subtree.

But isn't that a virtual DOM? I don't think it qualifies, at least not quite yet. I'm keeping track of each view, it's HTMLElement, and its parent. If I add a render queue, I should probably start keeping track of whether state is dirty or not. Does that make it a virtual DOM? I'm not getting stuck on semantics ...

Looking at the event handlers, you might notice that only root views actually call this.render() inside the mustRender event handler. Child views are handled elsewhere because they need the rendered HTML from the parent to exist in order for their selectors to return an HTMLElement using document.querySelector(). They are handled inside the onRendered() function, which is called from the rendered event handler.

You might also notice that the registered event handler fires mustRender for root views. It doesn't need to fire it for child views; remember, they are rendered in turn by their parents.

The last thing to notice is the note about bubbling up events. Parent views are bound to the mustRender events of their children, and they in turn fire a mustRender event. The net effect of this bubbling is that a mustRender event fired in the lowest child view will bubble up and eventually fire the root view in the chain. If you are familiar with React, you'll understand why React uses a rendering queue to enhance performance.

Without any changes to this code, every event in a DOM subtree is going to re-render the entire subtree. That might not matter in a small application, but in a large one it could create significant performance issues. Adding a rendering queue would allow us to check if a render process is already queued and if so whether there are duplicates being queued and in what order they should be called.

OK, so it looks a lot more like a virtual DOM with those features. I'm still not getting stuck on semantics.

Nested Rendering

The last thing I want to do for this post is show the onRendered() function.

	onRendered: function(){
		if( this.props !== undefined ){
			for( var prop in this.props ){
				if( this.props[ prop ].type !== undefined && this.props[ prop ].type === "View" ){
					this.props[ prop ].props.element = document.querySelector( this.props[ prop ].props.selector );
					this.props[ prop ].render();
				}
			}
		}
	}

What this bit of code does is to loop through the props of a view to see if there are any child views. If there are, it pulls the HTML element from the DOM using the cached selector string. Remember, we need to wait until this point to guarantee that the selector, when queried, will pull an element. It then calls the child view's render() function, which in turns will run this code again to check for children and render them as well.

That's it for now. As you might have guessed, I'm working on the rendering queue to improve performance and eliminate duplicate rendering. Watch my Twitter feed (@robertdmunn) for news about the next iteration of the altseven codebase.


Setting up and Running the Tasklist altseven example app

altseven, JavaScript, NodeJS, Open Source

Since I am covering the tasklist application in some detail, I'd like to walk you through the process of setting it up so you can run it yourself.

 

1. Clone from GitHub

$ cd ~/git
$ git clone https://github.com/robertdmunn/tasklist
$ cd tasklist

I like to put my git repos in a folder called (you guessed it) git inside my home folder. Clone the repo to whatever location works for you. Once you have cloned the repo, you should see something like this in the ./tasklist folder:

 

2. Create the database

The database is pretty simple- two tables in MySQL or MariaDB. You'll need a copy of one of them running somewhere to proceed.

Create an empty database in your db server. Call it whatever you like. I use UTF-8 collation as standard practice.

Open the database folder and open the script.sql file inside it. Execute that script against the database you just created. You should end up with two tables in your database. Create a username and password to access the database.

From the command line, run:

$ node hashpassword.js

Copy the console output into a command to update the password for your user in the users table:

$ update users set password = '<hash_value>' where userID = 1;

 

3. Modify the configuration

Open the config folder. Open the dbconfig.js file in a text editor. It should look like this:


var mysql = require( 'mysql' );

const pool = mysql.createPool({
  connectionLimit : 50,
  host            : 'localhost',
  user            : 'root',
  password        : 'password',
  database        : 'project_master'
});

module.exports = {
  pool: pool
};

Modify the host, user, password, and database values to match your environment.

 

4. Install dependencies

Go to the command line inside the ./tasklist folder. Install the npm dependencies, and then (optionally) install Bower dependencies.

$ npm install
$ bower install

 

Pre-requisites:

You will need Bower and npm installed and configured on your system. Check npm for instructions on installing npm in your OS. Once you have npm installed, get Bower:

$ npm install -g bower

 

5. Run the app

Once you have everything installed, you should be able to type:

$ node index.js

in the root of ./tasklist, then open the home page in your browser:

http://127.0.0.1:4000/

You should see something like this:

The Console Window on the right show debugging information from the altseven framework. You can use a7.log.(info|trace|error|fatal|warn)(message) to log information to this console in your application. There isn't much set up in the tasklist app, so mostly you will see the altseven framework debugging information. Later on I might add server-side logging to push to the console to demonstrate how that works.

Log in with the provided user and password. If the login fails, check your users table in the database to be sure the default user was inserted by the database script.

When you login, you should see something like this:

Add some entries. You should now see your tasks on the screen:

That's it! You should be able to complete and delete tasks as well. Give it a try and see what happens.

This app shows you how to build something small but useful in altseven using NodeJS as a back end. The client side application, apart from dependencies, is 500 lines long.


Embracing ReactJS-style UI rendering in altseven with ES6 Template Literals - Part II

altseven, JavaScript, NodeJS, Open Source

Eighteen days seems like forever in the Internet age. It was only eighteen days ago that I wrote Part I of this article about challenges solving some problems with building a React-style rendering solution in the altseven JavaScript framework. I promised to blog again about solutions to some of these challenges that I created in altseven v 1.20. Well, eighteen days and two additional versions of altseven later, I've solved all of the challenges I wanted to solve and added some useful new features to the framework.

Event Handlers

The first challenge I faced was to add event handlers to ES6 template literals and have them bind to the DOM when rendered. The key there is that you have to wait until the template literal is rendered into the DOM to bind the events. Once I realized that bit of truth, it was easy enough to devise a means of writing event handlers that could be bound after rendering. Let's look at a Header component written using ES6 template literals:

    function Header(props) {
      var header = a7.components.Constructor(a7.components.View, [props], true);

      header.state = {
        user: props.user
      };

      header.eventHandlers = {
	  logout: function(){
            a7.events.publish( 'auth.logout', { callback: app.auth.authenticate }) ;
	  }
	};

      header.template = function(){
		return `Welcome, ${Setting: header.state.user.firstName not found} <a name="signout" data-onclick="logout">[ Sign out ]</a>`;
	};

      return header;
    }

As a reminder, I'm using Douglas Crockford's method of stuffing a function's prototype methods into another object using a constructor function. From there, I create the initial state of the object. Then we see a couple of new methods and the removal of another. header.eventHandlers is an object with named keys of functions that respond to events in the template literal. In this case, I have a logout function that responds to the click event in header link.

However, because we're dealing with a template literal and not an actual rendered DOM node ( yet ), I can't just bind the handler to the event. Instead, and in order to stay compliant with standard HTML and JavaScript ( one of my keys goals ), I have added a "data-onclick" attribute to the <a name="signout"> link. When the view renders, a process will examine all the "data-on" attributes in the rendered HTML and bind the event handlers to the corresponding elements. Did you notice that render() is what was missing from the Header function? The View component now houses the render function, and that's where a lot of action occurs. Let's look at it:

	render: function(){
		if( this.props.element === undefined || this.props.element === null ){
			this.props.element = document.querySelector( this.props.selector );
		}
		if( !this.props.element ) throw( "You must define a selector for the view." );
		this.props.element.innerHTML = ( typeof this.template == "function" ? this.template() : this.template );

		var eventArr = [];
		a7.ui.getEvents().forEach( function( eve ){
			eventArr.push("[data-on" + eve + "]");
		});
		var eles = this.props.element.querySelectorAll( eventArr.toString() );

		eles.forEach( function( sel ){
			for( var ix=0; ix < sel.attributes.length; ix++ ){
				var attribute = sel.attributes[ix];
				if( attribute.name.startsWith( "data-on" ) ){
					var event = attribute.name.substring( 7, attribute.name.length );
					sel.addEventListener( event, this.eventHandlers[ sel.attributes["data-on" + event].value ] );
				}
			}
		}.bind( this ));

		this.fireEvent( "rendered" );
	}

I'll gloss over the section that sets the rendered HTML for now. After it gets set, the function iterates over a7.ui.getEvents() to build a long (very long) query selector that pulls all elements with data-on* attributes from the rendered HTML. By default, a7.us.getEvents() contains a list of all standard DOM events listed on the Mozilla Developer Network browser Events page. Since most applications will only use a fraction of those events, you can set an array of only the events used in your application in the altseven configuration object. Doing so will improve performance in your application.

Once the elements are pulled into the eles variable, the function iterates over the elements and then loops over its attributes looking for data-on* attributes. While nested looping isn't ideal, it gets the job done. An improvement to this process, if possible, would be good for performance, especially on HTML like rendered lists of data with click handlers on each row/cell.

When the function finds a data-on* attribute, it checks the value of the attribute against eventHandler keys in the created object. If there is a match, it adds a listener for the event and sets the handler to the proper eventHandler function.

Going back to the Header object, you can see in the eventHandlers.logout function that, because the function is defined inside the Header object, it has access to the a7 namespace and the app namespace (the namespace of the application). Although it isn't used in this example, it also has access to the object namespace, in this case header. Also not listed, since logout is an event handler, it could be written as:

logout: function( event )

Since the event will be passed to the handler by the browser, giving us access to the Event object as well.

By writing the event handlers inline but deferring binding them to the DOM until we know the HTML for the object is rendered - we can write our functions using standard syntax and scopes and still be guaranteed that they will be available in the rendered HTML.

I hedged about using data-on* attributes to hold the values of the eventHandlers required for a given element, but ultimately, I decided that, since it met my goal of using standard HTML and Javascript, it would be an acceptable solution.

In Part III, I will go over how altseven v. 3.x uses events to automate several processes including rendering on state change.


tasklist - Client Application for a NodeJS REST API- Part I

JavaScript, NodeJS

A few days ago, I posted a NodeJS application built around a REST API, and some further thoughts around architecture with the NodeJS mysql package. I have pushed the complete tasklist application to GitHub. If you want to grab it and see it run, clone the repo:

$ git clone https://github.com/robertdmunn/tasklist

Today, I am going to start a short series of posts going into some detail about the client application and how it interacts with the REST API.

Warning

Before I get started, let me be clear about what I am showing. The client application is an example implementation of a JavaScript framework I wrote last year (now almost two years ago) as an academic exercise, general exploration of some features of JavaScript, and bringing together of some things I had written in the past. That framework, called altseven, is now available on GitHub:

$ git clone https://github.com/robertdmunn/altseven

and can be installed through npm:

$ npm install altseven

altseven relies on several external packages, including an experimental UI+ library called gadget-ui I started a few years ago and have worked on sporadically ever since. Also available separately on GitHub and npm, if you are interested.

There might be an element or two of gadget-ui being run in production, but mostly it's just a playground for ideas that I have toyed with. You can see my posts about the gadgetui.input.FileUploader component, which is one of the things that might actually be in production use. 

Enough with the warnings, let's look at some code.

Serving Static Content with NodeJS

In my previous posts about the REST API in NodeJS,  I left out a piece of code in the index.js that serves static content for the client application, since it wasn't relevant to the topic. Here is the index file with the missing code:

index.js
----------


const express = require( 'express' );

const app = express();

// map our client-side libraries
app.use( express.static( 'client' ) );
app.use( "/lib/gadget-ui", express.static( 'node_modules/gadget-ui' ) );
app.use( "/lib/altseven", express.static( 'node_modules/altseven' ) );
app.use( "/lib/modlazy", express.static( 'node_modules/modlazy' ) );
app.use( "/lib/velocity", express.static( 'bower_components/velocity' ) );
app.use( "/lib/mustache.js", express.static( 'bower_components/mustache.js' ) );
app.use( "/lib/open-iconic", express.static( 'node_modules/open-iconic' ) );

// routes for the API
require( './routes/tasks.js' )(app);

// set our listener
var server = app.listen( 4000, function(){

});

Let's examine what's going on here.

First, you can see we're using Express in the Node application. Fortunately, Express includes the app.use() and express.static() functions to make it easy. To serve static content to the root of the application, we see the first line:

app.use( express.static( 'client' ) );

By passing the express.static( 'client' ) argument without a corresponding path to app.use(), we set the 'client' folder as the root of the static content that will be served by NodeJS.

Following the root folder, we specify both a path from the root and a static folder to serve on that path:

app.use( "/lib/gadget-ui", express.static( 'node_modules/gadget-ui' ) );

But why not use Browserify or Webpack? That's certainly something that can be done, and I'll cover it in a future post. For now, app.use() with express.static() is an easy way to serve static assets from NodeJS without a Web server.

Now let's look at the "old school" index.html, complete with dependency loader.

index.html
--------------

<html>
  <head>
    <title>
      NodeJS Task List
    </title>
    <script src="/lib/modlazy/dist/modlazy.min.js"></script>
    <script>
      modlazy.load(["/js/app.components.js < /js/app.remote.js < /js/app.utils.js < /js/app.main.js < /js/app.events.js < /lib/altseven/dist/a7.js < /lib/gadget-ui/dist/gadget-ui.js < /lib/velocity/velocity.js ",
        "/lib/mustache.js/mustache.js", "/css/styles.css", "/lib/altseven/dist/a7.css",
        "/lib/gadget-ui/dist/gadget-ui.css",
        "/lib/open-iconic/font/css/open-iconic.css"
      ], function() {
        var
          options = {
            auth: { // sessionTimeout: ( 60 * 15 * 1000 ) // default time in  milliseconds to refresh system auth
            },
            console: {
              enabled: true,
              wsServer: 'ws://127.0.0.1:8000',
              top: 100,
              left: 800,
              height: 300,
              width: 500
            },
            logging: {
              logLevel: "INFO,ERROR,FATAL,TRACE"
            },
            remote: {
              modules: app.remote,
              useTokens: false // defaults to true for the auth system
            },
            ui: { // renderer: // renderer is implicitly set by existence of the templating library, currently Mustache or Handlebars
              templates: "/templates.html"
            }
          };
        var p = new Promise(function(resolve,
          reject) {
          a7.init(options, resolve, reject);
        });
        p.then(function(state) {
          app.main.init(state);
        });
        p['catch'](function(message) {
          console.log(
            "Something went wrong.");
        });
      });
    </script>
  </head>

  <body>
    <div name="main">
  		<div name="app" >

  		</div>

  	</div>

  </body>
</html>

We don't need to spend too much time on the loading of the assets. modlazy is a dependency loader that guarantees loading of your JS dependencies in the correct order. The arrows "<" indicate dependency, so assets to the left of the arrow only load once assets to the right of the arrow have loaded. For assets like CSS files that have no dependencies, you can simply specify them in a quoted list, as shown.

More importantly, let's focus on defining the options for our application and the a7.init() function. As you can see in the options{} definition, altseven is divided into a number of packages- components, console, error, events, logging, model, remote, security, ui, and util. (auth is technically not a package but a function in the remote package, but it has a configuration option for session timeout).

Console is a package that renders as a floating window pane in the application. It displays a running list of entries from the log package. Optionally, it can also be configured to display a running list of log entries pushed from a web socket server. You can see a simple NodeJS socket server in my post Real-time server debug info using NodeJS, jQuery, Websockets and Logbox. I plan on coming back to this topic later, so feel free to ignore it for now. The gist of it is that you can include server-side logging information - or anything that can be pushed to a socket connection - in the console.

The logging package does just what it says- handles log statements in the application code. logLevel specifies what log levels from the code will be parsed and sent to the console.

The model package isn't listed in the options for this application, but it has a configuration option that can be used to set the model to any model package of your choosing. By default it uses the model in the gadget-ui library.

The remote package handles remote calls to the server. It has a built-in auth function that can be used with the built-in components.User object to provide authentication services against a server and set the application into secure mode. We're not using it in the tasklist application, but I will re-visit it later. Specify the application's remote modules using the modules option. The useTokens option can be set to true if you need an authenticated session with the server. It handles auth tokens that can be set by the server and passed back and forth for secure sessions.

The ui package handles ui templating and objects. It currently supports Mustache and Handlebars, but might include React support soon (hint hint). Load the Mustache library as part of your application to use Mustache, load Handlebars to use Handlebars.

Lastly for this post, the a7.init() call for altseven needs to be made inside a Promise. The a7.init() call resolves or rejects the promise and allows you to then proceed with running your application.

That's it for now. Next, I'll cover the client application code in more detail.


Exploring Architecture with the NodeJS mysql package

JavaScript, MySQL, NodeJS

In software design, architectural choices have a significant influence on the maintainability of your code base. Choosing the proper toolkit, while important, is not enough to guarantee a maintainable solution. Frameworks attempt to solve this problem by imposing an architecture on your code base that (hopefully) uses best practice patterns in software design to help you build a maintainable code base. I will return to the issue of frameworks (and their strengths and weaknesses) another day. 

Meanwhile, let's explore some architectural design choices we can make with the NodeJS mysql package when building CRUD applications. You can refer to my post on Creating a NodeJS REST API with Express and MySQL as a base design blueprint for building a CRUD application using the MySQL package. The application in the post makes several design choices that are not explained in any detail. Let's explore them now.


Creating a NodeJS REST API with Express and MySQL

JavaScript, NodeJS, Open Source, Web Development

NodeJS offers the ability to build Web apps using JavaScript. Today, I will show you how to build a NodeJS REST API for a task list using Express and MySQL.


Categories


Recent Entries

Entries Search