3.0.1 • Published 6 years ago

@sasm/system v3.0.1

Weekly downloads
2
License
MIT
Repository
-
Last release
6 years ago

SasmSystem

Base system for SASM products.

NPM Version Node Version Express Version Sasm Version

Install

npm i @sasm/system

Usage

Getting started with SASM is as simple as requiring the system and starting.

const sasm = require('@sasm/system');
sasm.
	start().
    registerRoot(__dirname).
    listen();

All methods of system return the system, so can be chained as demonstrated above. The first thing you should do is invoke the start() method.

Root Directory

It's important to give Sasm Version a root directory. The root may be registered at any point during the runtime cycle, but it's recommended you register the root directory before registering any extensions.

sasm.registerRoot(__dirname);

Using Extensions

Sasm Version is extensible. You probably also want to use the router extension, Sasm Router, so we'll use that as an example. It's also useful to create custom extensions, but we'll get into that later.

@Sasm Extensions must be installed just like the system.

npm i @sasm/router

Once installed, you may use extensions with Sasm Version simply by registering the name of the NPM module:

sasm.registerExtension('@sasm/router');

Or by requiring the module, and then registering a reference to it:

const router = require('@sasm/router');
sasm.registerExtension(router);

It's important to note that extensions should be registered after running sasm.start() and before running sasm.listen(). You may use sasm.extensions to access the registered extensions, as in this example:

const sasm = require('@sasm/system');
const router = require('@sasm/router');
sasm.
	start().
	registerRoot(__dirname).
	registerExtension(router).
	listen();
console.log("extensions:", sasm.extensions);

Possible Output: (connection address is subject to local machine preferences)

extensions: { SasmRouter: [Function: SasmRouter] }
Listening on: 6::::8080

Running an HTTP server

See the Sasm Router module for further documentation on setting up the routing end of the HTTP server.

To start the HTTP server, simply run sasm.listen().

You may pass a callback to sasm.listen(), but it is not necessary.

Configuration

It's possible to configure your HTTP and MongoDB connection preferences. The default configuration is:

{
	"connection": {
		"hostname": "localhost",
		"ip4": "127.0.0.1",
		"ip6": null,
		"port": 8080
	},
	"database": {
		"username": null,
		"password": null,
		"address": [
			{
				"host": "localhost",
				"port": 27017
			}
		],
		"name": "sasm",
		"options": {}
	}
}

You can pass your own configuration to sasm.start() (not recommended), or modify the default configuration (recommended). The default configuration is accessed using sasm.prep.config.

Example: Changing the HTTP port to 80:

const sasm = require('@sasm/system');
sasm.prep.config.connection.port = 80;
sasm.start();
// ...

Example: Passing default configuration to sasm.start()

const myConfig = {
	"connection": {
		"hostname": "localhost",
		"ip4": "127.0.0.1",
		"ip6": null,
		"port": 8080
	},
	"database": {
		"username": null,
		"password": null,
		"address": [
			{
				"host": "localhost",
				"port": 27017
			}
		],
		"name": "sasm",
		"options": {}
	}
};

const myRequirements = {
	"bcrypt": "bcrypt",
	"express": "express",
	"io": "socket.io",
	"mongojs": "mongojs"
};
const myPrep = {
    config: myConfig,
    requirements: myRequirements
}

sasm.start(myPrep);

As you can see, requirements are bundled into prep with configuration. You can add requirements if needed, and they will be required and assigned as expected...

{
    "[name]": "[require]"
}

Requirements can be accessed directly from the sasm variable. For example, to get the socket.io reference, you would use sasm.io.

Note: you must invoke sasm.start() for requirements to be loaded.

Custom Extensions

Sasm extensions are simply JavaScript functions/classes whom take the sasm system as their sole argument. Extensions may add to, modify, and use anything branching off of sasm. With that said, one should be careful not to conflict with other extensions and anything on the namespace of sasm. It's common practice to create a sub-namespace for your extension, so not to conflict with other extensions.

Let's create a simple Hello World extension and register it.

const sasm = require('@sasm/system');

class HelloWorld {
	constructor (sasm) {
		console.log("Hello, World!");
	}
}

sasm.
	start().
	registerExtension(HelloWorld);
console.log("extensions:", sasm.extensions);

Output:

Hello, World!
extensions: { HelloWorld: [Function: HelloWorld] }

Using SASM in Extensions

That's all easy enough, but let's think of a more useful example. Say we have some data for raw materials in our inventory, and we want to send it to a dynamic file accessible through a web browser. We'll call the module requestMaterialData.

The document layout for this example is as follows:

erp>
	server.js
    plugins>
    	requestMaterialData>
        	package.json
			index.js
    public>
    	index.html

server.js has the following code:

const sasm = require('@sasm/system');
const requestMaterialData = require("./plugins/requestMaterialData");
sasm.
	start().
	registerRoot(__dirname).
	registerExtension("@sasm/router").
	registerExtension(requestMaterialData).
	listen();
console.log("extensions:", sasm.extensions);

The server requires the sasm system and our custom extension module. We simply start sasm, set the root, and register the router extension and our requestMaterialData extension. Then we set up the listener and log the extensions to make sure we created our extension correctly.

For our module to work properly, we need to create the folder plugins/requestMaterialData and the file plugins/requestMaterialData/index.js. After that, we enter the folder in the terminal and run the command:

npm init

With that, we simply answer a few questions and we are given the following package.json (or something similar depending on what you answered): ./plugins/requestMaterialData/package.json

{
  "name": "@sasm/requestmaterialdata",
  "version": "1.0.0",
  "description": "Supply material data on HTTP request.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Spencer A. Lockhart",
  "license": "MIT"
}

Once that's done, we can write some code for our new extension: ./plugins/requestMaterialData/index.js

const materials = [
	{
		"id": 0,
		"name": "case",
		"count": 900
	},
	{
		"id": 1,
		"name": "poly",
		"count": 1000
	},
	{
		"id": 2,
		"name": "tape",
		"count": 10000
	}
];

class RequestMaterialData {
	constructor (sasm) {
		const self = this;
		self.sasm = sasm;

		sasm.app.get('/requestMaterialData', function (req, res) {
			res.send(materials);
		});
	}
}

module.exports = RequestMaterialData;

First, we create a psuedo materials data structure- an array of objects, where each object is material data containing an id, a name, and a count.

After the data is established, we create the class RequestMaterialData. We simply put a constructor in there that takes sasm as an argument, and we use sasm.app from Express Version to send the data when the url /requestMaterialData is requested.

  1. It's good practice to assign this to a variable, such as a constant named self, so that we do not confuse this in inner functions.
  2. It's useful to assign sasm to self.sasm so that we can access it from other methods in our class.

When we run server.js, we should get the following output in our terminal:

extensions: { SasmRouter: [Function: SasmRouter],
  RequestMaterialData: [Function: RequestMaterialData] }
Listening on: 6::::8080

Also, when we visit http://localhost:8080/requestMaterialData in our web browser, we get our unformatted JSON data:

[{"id":0,"name":"case","count":900},{"id":1,"name":"poly","count":1000},{"id":2,"name":"tape","count":10000}]

Adding to SASM

With this example so far, you learned how to use sasm.app from express in a custom module. But let's say we want to make the data available to other extensions on the server- not just HTTP requests. To do that, we have to add to sasm. To do that, we just add a single line to our constructor:

class RequestMaterialData {
	constructor (sasm) {
		const self = this;
		self.sasm = sasm;
		sasm.requestMaterialData = materials;
		sasm.app.get('/requestMaterialData', function (req, res) {
			res.send(materials);
		});
	}
}

Important Note: As of SasmSystem 3.0.0, a fatal error will be thrown if an extension adds anything to sasm that is not allowed. Allowed names are one of: 1. Extension class name. (example, SasmRouter) 2. Extension class name with the first letter lower-case. (example, sasmRouter) 3. Extension class name, minus "Sasm" (example, Router) 4. Extension class name, minus "Sasm", with first letter lower-case (example, router)

An attempt to assign something to sasm that is not an allowed name for that extension, and/or an attempt to assign more than one thing to sasm will result in a fatal error.

In a real system, we would use a database to store data for materials. But for this example, we're keeping it simple by using static JSON data. Communicating with a database would require quite a bit more code and a way to get/set data. But since we're just using plain JSON, one line makes it possible for other extensions and stuff on our server to read, write, and remove material data.

To test this, let's modify server.js to log our material data to the terminal:

const sasm = require('@sasm/system');
const requestMaterialData = require("./plugins/requestMaterialData");
sasm.
	start().
	registerRoot(__dirname).
	registerExtension("@sasm/router").
	registerExtension(requestMaterialData).
	listen();
console.log(sasm.requestMaterialData);

Now, when we run our server, we get the following output:

[ { id: 0, name: 'case', count: 900 },
  { id: 1, name: 'poly', count: 1000 },
  { id: 2, name: 'tape', count: 10000 } ]
Listening on: 6::::8080

Now you've seen how to create an extension that uses Sasm and adds to Sasm. There's much to be done with this, but do be careful not to pollute the Sasm namespace, and use best practices. In future versions of sasm, there is no guarentee that anything not specifically allowed on sasm will be okay, and may result in a fatal error. Remember, every extension gets a single, clear, allowed property on sasm.

3.0.1

6 years ago

3.0.0

6 years ago

2.0.4

6 years ago

2.0.3

6 years ago

2.0.2

6 years ago

2.0.1

6 years ago

2.0.0

6 years ago

1.1.5

6 years ago

1.1.4

6 years ago

1.1.3

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago