1.0.0 • Published 5 years ago

attune v1.0.0

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

Attune

Micro-framework for reasoning about the stateful pieces of your software.

  • Provides a simple interface for starting & stopping individual services
  • Facilitates a declarative approach to configuration
  • Is cognizant of dependency ordering
  • Offers opt-in validation for user input

Getting Started

Install Attune using NPM

$ npm install attune

Create a setup file called index.js

$ touch index.js

Require Attune and the HTTP module

var http = require('http')
var { System } = require('attune')

Create a configuration object

// Specification of configuration data for all services (best stored as JSON)
// Top-level keys designate a service name
// The "depends" key states that the "server" is dependent on the "handler" service
// If multiple dependencies exist, "depends" may also be an array of service names
var config = {
  handler: { message: 'Hello World\n' },
  server: { port: 3000, depends: 'handler' } // depends: ['handler', 'another']
}

Create a functions object

// Specification of behavioral data for all services
// Top-level keys designate a service name
// Each service should have a start function, and optionally a stop function
var fns = {
  handler: { start: startHandler },
  server: { start: startServer, stop: stopServer }
}

Create a validation flag

// Validation flag used by the System constructor function
// An error will be thrown if the configuration or functions object is deemed invalid
var validate = true

Create a start function for the "handler" service

// The "handler" service start function
// Start functions have two parameters:
// - The entire configuration object
// - An object consisting of any dependent services
// The value of the "handler" service will be a handler function
function startHandler({ handler: { message } }, deps) {
  return function handler(req, res) {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/plain')
    res.end(message)
  }
}

Create a start function for the "server" service

// The "server" service start function
// The port number is passed in through the configuration object
// The handler function is passed in through the dependencies object
// The value of the service will be an HTTP server
function startServer({ server: { port } }, { handler }) {
  return http.createServer(handler).listen(port)
}

Create a stop function for the "server" service

// The "server" service stop function
// Stop functions have two parameters:
// - The value of the service (returned from the start function)
// - An object consisting of any dependent services
// The return value of a stop function is discarded
// This function closes the HTTP server
function stopServer(server, deps) {
  server.close()
}

Open the Node.js REPL

$ node

Load the setup file

> .load index.js

Construct a system object

// Instantiate a system
// System constructor functions have three parameters:
// - The configuration object
// - The functions object
// - An optional validation flag (false, if not specified)
> var sys = System(config, fns, validate)

Start the "handler" service

// Start a specific service by name
> sys.start('handler')

Notice the value of the "handler" service

// Retrieve a service value
> sys.handler

Start all services

// Start all services by order of dependency
> sys.start()

Notice the string representation of the system object

// Print the string representation of a system
// Running services are denoted in curly braces
> sys.toString()

Stop the "server" service

// Stop a specific service by name
> sys.stop('server')

Stop all services

// Stop all services by order of dependency
> sys.stop()

Notice the JSON representation of the system object

// Print the configuration object as JSON
> sys.toJSON()

See example for a single-file implementation

License

This project is licensed under the MIT License

Acknowledgments

  • Inpsired by Integrant
  • Tested on Node.js v11.12.0