npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@pryv/boiler

v1.2.4

Published

Logging and config boilerplate library for Node.js apps and services at Pryv

Downloads

5

Readme

Pryv config and logging boilerplate for Node.js

Usage

Initialization

The "boiler" must be initialized with the application name and configuration files settings, before invoking getConfig() or getLogger():

require('@pryv/boiler').init({
  appName: 'my-app', // This will will be prefixed to any log messages
  baseFilesDir: path.resolve(__dirname, '..'), // use for file:// relative path if not give cwd() will be used
  baseConfigDir: path.resolve(__dirname, '../config'),
  extraConfigs: [{
    scope: 'extra-config',
    file: path.resolve(__dirname, '../config/extras.js')
  }]
});

Configuration

We use nconf.

Base config directory structure

During initialization default-config.yml and ${NODE_ENV}-config.yml will be loaded if present in baseConfigDir.

Loading order and precedence

The order configuration sources are loaded is important. Each source is loaded with a "scope" name, which can be used to replace the source's contents at any point of time.

The configuration sources are loaded in the following order, the first taking precedence:

  1. 'test': Empty slot reserved for tests to override any other config parameter
  2. 'argv': Command line arguments
  3. 'env': Environment variables
  4. 'base': File ${NODE_ENV}-config.yml (if present) or specified by the --config command line argument
  5. 'extra-config': Additional source(s) as specified by the extraConfigs option (see below)
  6. Defaults:
    • 'default-file': ${baseConfigDir}/default-config.yml
    • 'defaults': Hard-coded defaults for logger

Extra configurations

Additional configuration sources can be set or reserved at initialization with the extraConfigs option, which expects an array of objects with one of the following structures:

  • File: {scope: <name>, file: <path to file> }. Accepts .yml, .json and .js files. Note .js content is loaded with require(<path to file>).
  • Data: {scope: <name>, key: <optional key>, data: <object> }. If key is provided, the content of data will be accessible by this key, otherwise it is loaded at the root of the configuration.
  • Remote URL: {scope: <name>, key: <optional key>, url: <URL to json content> }. The JSON contents of this URL will be loaded asynchronously.
  • URL from key: {scope: <name>, key: <optional key>, urlFromKey: <key> }. Similar to remove URL, with the URL obtained from an existing configuration key.

Working with the configuration

Retrieving the configuration object:

// synchronous loading
const { getConfigUnsafe } = require('@pryv/boiler'); // Until all asynchronous sources such as URL are loaded, items might not be available
const config = await getConfigUnsafe();

// asynchronous loading
const { getConfig } = require('@pryv/boiler');
const config = await getConfig(); // Here we can be sure all items are fully loaded

Retrieving settings:

// configuration content is {foo: { bar: 'hello'}};
const foo = config.get('foo'); // {bar: 'hello'}
const bar = config.get('foo:bar'); // 'hello'

const barExists = config.has('bar'); // true

Assigning settings:

// configuration content is {foo: { bar: 'hello'}};
config.set('foo', 'bye bye'); // {bar: 'hello'}
const foo = config.get('foo'); // 'bye bye'

Changing a scope's contents:

// configuration content is {foo: { bar: 'hello'}};
config.get('foo'); // {bar: 'hello'}
// replace 'test' existing content (test is always present as the topmost configuration source)
config.replaceScopeConfig('test', {foo: 'test'});
config.get('foo'); // 'test'
// reset content of 'test' scope
config.replaceScopeConfig('test', {});
config.get('foo'); // {bar: 'hello'}

// Note: for 'test' scope there is a "sugar" function with config.injectTestConfig(object)

Finding out from which scope a key applies: As nconf is hierachical sometimes you migth want to search from which scope the value of a key is issued.

config.getScopeAndValue('foo'); 
// returns {value: 'bar', scope: 'scopeName'; info: 'From <file> or Type <env, '}

"Learn" mode

To help detect unused configuration settings, a "learn" mode can be activated to track all calls to config.get() in files.

Example when running tests:

export CONFIG_LEARN_DIR="{absolute path}/service-core/learn-config"
yarn test

Note, if CONFIG_LEARN_DIR is not given {process.cwd()}/learn-config will be used

Logging

All messages are prefixed by the appName value provided at initialization (see above)). appName can be postfixed with a string by setting the environment variable PRYV_BOILER_SUFFIX, which is useful when spawning several concurrent processes of the same application.

Using the logger

const {getLogger} = require('@pryv/boiler');

logger.info('Message', item); // standard log
logger.warn('Message', item); // warning
logger.error('Message', item); // warning
logger.debug('Message', item); // debug

logger.getLogger('sub'); // new logger name spaced with parent, here '{appName}:sub'

logger.info(), logger.warn() and logger.error() use Winston logger.debug() is based on debug.

Outputting debug messages

Set the DEBUG environment variable. For example: DEBUG="*" node app.js will output all debug messages.

As "debug" is a widely used package, you might get way more debug lines than expected, so you can use the appName property to only output messages from your application code: DEBUG="<appName>*" node app.js

Using a custom logger

A custom logger can be used by providing logs:custom information to the configuration. A working sample of custom Logger is provided in ./examples/customLogger.

The module must implement async init(settings) and log(level, key, message, meta)

Log configuration sample

logs: {
    console: {
      active: true,
      level: 'info',
      format: {
        color: true,
        time: true,
        aligned: true
      }
    },
    file: {
      active: true,
      path: 'application.log'
    },
    custom: { 
      active: true,
      path 'path/to/node/package',
      settings: { /* settings passed to the custom logger */}
    }
  }

TODO

  • Make config an eventEmitter ? // to track when read or if config changes
  • FIX realtive PATH logic for config.loadFromFile()

Contributing

npm run lint lints the code with Semi-Standard.

npm run license updates license information.

License

BSD-3-Clause