1.1.0 • Published 6 years ago

aria-configurator v1.1.0

Weekly downloads
2
License
ISC
Repository
github
Last release
6 years ago

aria-configurator

Aria configurator is a simple package that parses a set of JSONs files and creates a set of configuration parameters that are being exposed to the rest of the application.

API

It is fairly easy to use this package. You just pass along the path to the target folder that contains the JSONs files.

const aria = require('aria-configurator')
var configuration = aria('/lib/configuration/production/')

Instead of JSON files, you may specify a way to retrieve the same information from MongoDB documents!

const aria = require('aria-configurator')
var mongoConnection = { url: 'mongoConnectionUri', collection: 'collectionName' }
var configuration = aria(mongoConnection)

About mongo connection URI:

About mongo collection:

  • the collection property specifies the collection that will be queried
  • aria will attempt to read 2 documents. One that has a property type: 'parameters and one type: 'constants'
  • if any of the two documents is missing, aria will return some default values
  • if more than one docs are found with type: 'parameters or type: 'constants', the first one will be used

Also, you may pollute the global space by attaching the configuration there:

const aria = require('aria-configurator')
aria('/lib/configuration/production/', 'conf')
var configuration = global.conf

Requirements

In order to successfully create a configuration object, the target folder should include:

  • constants.json
  • parameters.json

If any of these files is missing, the library returns an error.

You may include anything you desire in these JSON files but some choices will affect the final configuration object. Lets see how will this happen:


Parameters

Parameters from parameters.json will ne available ubder the configuration.parameters object.

Constants

Constants from constants.json will be available under the configuration.constants object.

A localization option is supported. The way this work is the following:

  • parameters.json should include a default locale property
  • parameters.json should inclide a list of supported locales
defaults: {
  locale: 'en'
},
locales: ['en', 'fr', 'gr']

If default locale is included in the supported locales array, then the package attempts to localize the constants JSON file such as: Every property that:

  • is an object
  • has a property named equal to the default locale
application: {
  name: {
    en: 'English',
    fr: 'French',
    gr: 'Greek'
  }
}

is transformed as:

application: {
  name: 'English'
}

You may incude as many languages as you want or embedded your properties as much you want. It should be noted that there are some corner cases. Given the fact that the default locale is 'en':

  • If an object has a property called 'en' that's an object, and not a string or array, it's ignored.
  • If an object does not include a property called 'en', it stays untouched.

Errors

You may include a set of errors inside the parameters.json file such as:

errors: {
  unavailable: {
    name: 'BUSY',
    code: 987
  }
}

These errors will be available under configuration.errors. It is required to include the properties name and code in order for them to appear here.

You may include a set of error messages inside constants.json file such as:

errors: {
  unavaiable: {
    message: 'Server is busy',
    suggestion: 'Try again later'
  }
}

If the same error property is found in both parameters.json and constants.json, the properties are merged under configuration.errors and you get:

configuration: {
  errors: {
    unavailable: {
      name: 'BUSY',
      code: 987,
      message: 'Server is busy',
      suggestion: 'Try again later'
    }
  }
}

It is advised to use this method to declare errors, but you can simply ignore it and use your own structure under configuration.parameters.errors. Also, the error messages under constants.json may also be localized!

Finally, a set of default errors is also included and can be overwritten. These are:

internal: { name: 'INTERNAL', code: 900 },
validation: { name: 'VALIDATION', code: 901 },
duplicate: { name: 'DUPLICATE', code: 902 },
business: { name: 'BUSINESS', code: 903 },
notFound: { name: 'NOT_FOUND', code: 904 },
invalid: { name: 'INVALID', code: 905 }

Scope

Another object is attached under configuration.scope which includes useful variables based on the scope parameter you have included in the parameters.json file. Three (3) scopes are supported:

  • development
  • production
  • qa

The generated properties are:

environment: 'development',
debug: true,
errors: {
  codes: true,
  messages: true,
  suggestions: true,
  stackTrace: true
},
logLevel: 'development'
environment: 'production',
debug: false,
errors: {
  codes: false,
  messages: true,
  suggestions: false,
  stackTrace: false
},
logLevel: 'production'
environment: 'qa',
debug: false,
errors: {
  codes: true,
  messages: true,
  suggestions: true,
  stackTrace: false
},
logLevel: 'qa'

Settings - Authorization

If parameters.json includes the following properties

authorization: {
  enabled: true,
  tactic: 'jsonToken',
  passePartout: 'admin'
}

these are passed along under configuration.settings.authorization. If no authorization is found, a false flag is returned under authorization.enabled.

Settings - Connection

Under configuration.settings.connection you will find a set of object that describe connections, categorized by the property type. If parameters.json includes an object connection, each sub-object will categorized into the following categories:

  • backend
  • database
  • frontend
  • other
  • services
  • storage

An example would be to declare connections in the parameters.json such as:

connection: {
  imgur: {
    type: 'storage',
    ...
  },
  mongo: {
    type: 'database',
    ...
  }
}

which will be included in the configuration.settings.connection as:

database: {
  mongo: {
    ...
  }
},
storage: {
  imgur: {
    ...
  }
}

Process

Under configuration.settings.process you will find the following properties available for your convinience:

arguments: process.argv.slice(2),
environment: process.env,
pid: process.pid,
platform: process.platform,
root: process.cwd(),
version: process.version

Additionally, if parameters.json has a property called proccess you may include the sub-properties:

process: {
  cluster: {
    enabled: true,
    instances: 2
  },
  logs: {
    enabled: true,
    path: '/temp/logs/'
  }
}

Settings - Storage

Again, for your convinience, if parameters.json includes a storage object it is exported under configuration.settings.storage. If no such object is found, an empty placeholder is returned in order to guide the user on how to fill a set of useful settings. The placeholder is:

directory: '',
files: {
  formats: [],
  naming: {
    unique: false,
    prefix: ''
  }
},
host: ''

Settings - Time

A unique instance of MomentJS is exposed under configuration.settings.time. You may included a format and a timezone in the parameters.json file, under time property. The returned object may look like:

moment: Function,
timezone: 'Europe/London',
format: 'YYYY-MM-DD'

It should be noted that the moment function uses the given timezone and format!

Methods

Three (3) methods are exposed from the configuration file. These are:

  • changeLocale: takes a locale as an argument, for example 'fr' and returns the constants.json localized. The catch is that the requested locale should be included in the parameters.json file, inside the locales array.
  • moment: the same method that is available under configuration.settings.time.moment.
  • read: this methods works as lookup inside the configuration.parameters object. It returns the first property that is found in the tree.

Example

An example configuration would be:

  • parameters.json
{
  "authorization": {
    "enabled": true,
    "tactic": "jsonToken",
    "passePartout": "admin1234"
  },
  "connections": {
    "imgur": {
      "type": "storage"
    },
    "mongo": {
      "type": "database",
      "host": "localhost:27017"
    }
  },
  "defaults": {
    "locale": "en"
  },
  "errors": {
    "highTraffic": {
      "name": "HIGH_TRAFFIC",
      "code": 902
    }
  },
  "locales": ["en", "fr"],
  "process": {
    "cluster": {
      "enabled": true,
      "instances": 2
    },
    "logs": {
      "enabled": true,
      "path": "usr/logs"
    }
  },
  "scope": "development",
  "storage": {
    "directory": "",
    "files": {
      "formats": [
        "png",
        "jpg",
        "jpeg"
      ],
      "naming": {
        "unique": true,
        "prefix": "asset_"
      }
    },
    "host": "imgur"
  },
  "time": {
    "timezone": "Europe/London",
    "format": "YYYY-MM-DD"
  }
}
  • constants.json
{
  "application": {
    "name": {
      "en": "Aria",
      "fr": "French Aria"
    }
  },
  "errors": {
    "highTraffic": {
      "message": {
        "en": "Server is busy",
        "gr": "Ο διακομιστής είναι απασχολημένος"
      },
      "suggestion": {
        "en": "Try again later",
        "fr": "Δοκιμάστε αργότερα"
      }
    },
    "invalid": {
      "message": {
        "en": "An invalid request was received",
        "fr": "Λανθασμένο αίτημα"
      },
      "suggestion": {
        "en": "Contact the administrator",
        "fr": "Επικοινωνήστε με τον διαχειριστή του συστήματος"
      }
    }
  }
}
  • and the returned configuration object:
{ methods: 
   { changeLocale: [Function],
     moment: { now: [Function: now], moment: [Function: moment] },
     read: [Function] },
  settings: 
   { authorization: { enabled: true, tactic: 'jsonToken', passePartout: 'admin1234' },
     connection: 
      { backend: {},
        database: { mongo: { type: 'database', host: 'localhost:27017' } },
        frontend: {},
        other: {},
        services: {},
        storage: { imgur: { type: 'storage' } } },
     process: 
      { arguments: [],
        cluster: { enabled: true, instances: 2 },
        environment: {},
        logs: { enabled: true, path: 'usr/logs' },
        pid: 4624,
        platform: 'win32',
        root: 'C:\\aria-configurator',
        version: 'v8.1.3' },
     storage: 
      { directory: '',
        files: 
         { formats: [ 'png', 'jpg', 'jpeg' ],
           naming: { unique: true, prefix: 'asset_' } },
        host: 'imgur' },
     time: 
      { moment: { now: [Function: now], moment: [Function: moment] },
        timezone: 'Europe/London',
        format: 'YYYY-MM-DD' } },
  constants: 
   { application: { name: 'Aria' },
     errors: 
      { highTraffic: { message: 'Server is busy', suggestion: 'Try again later' },
        invalid: 
         { message: 'An invalid request was received',
           suggestion: 'Contact the administrator' } } },
  errors: 
   { internal: { name: 'INTERNAL', code: 900 },
     validation: { name: 'VALIDATION', code: 901 },
     duplicate: { name: 'DUPLICATE', code: 902 },
     business: { name: 'BUSINESS', code: 903 },
     notFound: { name: 'NOT_FOUND', code: 904 },
     invalid: 
      { name: 'INVALID',
        code: 905,
        message: 'An invalid request was received',
        suggestion: 'Contact the administrator' },
     highTraffic: 
      { name: 'HIGH_TRAFFIC',
        code: 902,
        message: 'Server is busy',
        suggestion: 'Try again later' } },
  parameters: 
   { authorization: { enabled: true, tactic: 'jsonToken', passePartout: 'admin1234' },
     connections: 
      { imgur: { type: 'storage' },
        mongo: { type: 'database', host: 'localhost:27017' } },
     defaults: { locale: 'en' },
     errors: 
      { highTraffic: 
         { name: 'HIGH_TRAFFIC',
           code: 902,
           message: 'Server is busy',
           suggestion: 'Try again later' } },
     locales: [ 'en', 'fr' ],
     process: 
      { cluster: { enabled: true, instances: 2 },
        logs: { enabled: true, path: 'usr/logs' } },
     scope: 'development',
     storage: 
      { directory: '',
        files: 
         { formats: [ 'png', 'jpg', 'jpeg' ],
           naming: { unique: true, prefix: 'asset_' } },
        host: 'imgur' },
     time: { timezone: 'Europe/London', format: 'YYYY-MM-DD' } },
  scope: 
   { environment: 'development',
     debug: true,
     errors: 
      { codes: true,
        messages: true,
        suggestions: true,
        stackTrace: true },
     logLevel: 'development' } }