New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@stringstack/core

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stringstack/core - npm Package Compare versions

Comparing version
0.1.3
to
0.2.0
+32
test/lib/class.log.a.js
'use strict';
const TestBase = require( './class.base' );
class TestLogA extends TestBase {
constructor( deps ) {
super( deps, 'TestLogA' );
this._logger = deps.get( 'logger' );
this._logger( 'info', 'TestLogA constructor', { meta: 'data' } );
this._logb = deps.get( './test/lib/class.log.b' );
}
init( done ) {
this._logger( 'debug', 'TestLogA init', { meta: 'data' } );
this._logger( 'warn', 'TestLogA init warn' );
this._logger( 'warning', 'TestLogA init warning' );
super.init( done );
}
dinit( done ) {
this._logger( 'debug', 'TestLogA dinit', { meta: 'data' } );
super.dinit( done );
}
}
module.exports = TestLogA;
'use strict';
const TestBase = require( './class.base' );
class TestLogB extends TestBase {
constructor( deps ) {
super( deps, 'TestLogB' );
this._logger = deps.get( 'logger' );
this._logger( 'info', 'TestLogB constructor', { meta: 'data' } );
this._logger( 'verbose', 'TestLogB constructor', { meta: 'data' } );
}
init( done ) {
this._logger( 'debug', 'TestLogB init', { meta: 'data' } );
super.init( done );
}
dinit( done ) {
this._logger( 'debug', 'TestLogB dinit', { meta: 'data' } );
this._logger( 'information', 'TestLogB information' );
super.dinit( done );
}
}
module.exports = TestLogB;
+12
-1

@@ -5,3 +5,3 @@ 'use strict';

constructor( path, loader ) {
constructor( path, loader, logger ) {

@@ -14,5 +14,16 @@ // the path of the module that got this loader

this._logger = logger;
}
get( path ) {
if ( path === 'logger' ) {
return ( level, message, meta ) => {
this._logger( level, this._path, message, meta );
};
}
return this._loader.get( this._path, path );

@@ -19,0 +30,0 @@ }

+50
-15
'use strict';
const async = require( 'async' );
const Loader = require( './loader' );

@@ -9,6 +8,4 @@ const nconfProvider = require( 'nconf' ).Provider;

constructor( config ) {
constructor() {
this._config = config;
}

@@ -18,10 +15,2 @@

let appConfig = config;
if ( this._config ) {
appConfig = this._config;
} else if ( !appConfig ) {
appConfig = {};
}
class App {

@@ -33,5 +22,49 @@

this._config = appConfig;
this._loader = new Loader();
if ( typeof config.log !== 'function' ) {
config.log = () => {
// NO-OP
};
}
this._logger = ( level, component, message, meta ) => {
if ( typeof level !== 'string' ) {
return;
}
// normalize log levels
level = level.toLowerCase();
switch ( level ) {
case 'emergency':
level = 'emerg';
break;
case 'critical':
level = 'crit';
break;
case 'err':
level = 'error';
break;
case 'warn':
level = 'warning';
break;
case 'information':
level = 'info';
break;
}
try {
config.log( level, component, message, meta );
} catch ( e ) {
console.error( 'user log method threw an exception', e );
// re-throw this bad boy, let it all burn!
throw e;
}
};
this._loader = new Loader( this._logger );
this._loader.set( 'app', 'env', env );

@@ -42,3 +75,3 @@

let rootComponents = this._config.rootComponents;
let rootComponents = config.rootComponents;

@@ -54,2 +87,4 @@ if ( !Array.isArray( rootComponents ) ) {

this._logger( 'notice', 'app', 'instantiated' );
}

@@ -56,0 +91,0 @@

@@ -9,4 +9,6 @@ 'use strict';

constructor() {
constructor( logger ) {
this._logger = logger;
this._instantiateCurrent = null;

@@ -23,2 +25,4 @@ this._instantiateStack = [];

this._logger( 'notice', 'loader', 'begin initializing components' );
// clone then reverse the initialize stack

@@ -33,2 +37,3 @@ let components = this._initializeStack.slice( 0 ).reverse();

if ( !component ) {
this._logger( 'warn', 'loader', 'possible bug in stringstack/core, component not found in init stack ' + path );
return done();

@@ -44,2 +49,3 @@ }

if ( component.initialized ) {
this._logger( 'info', 'loader', 'initialized component ' + path );
return done();

@@ -59,2 +65,3 @@ }

this._logger( 'info', 'loader', 'initialized component ' + path );
return done();

@@ -69,2 +76,3 @@

this._logger( 'info', 'loader', 'initialized component ' + path );
component.initialized = true;

@@ -75,4 +83,14 @@ done();

}, done );
}, ( err ) => {
if ( err ) {
this._logger( 'error', 'loader', 'error initializing components', err );
return done( err );
}
this._logger( 'notice', 'loader', 'finished initializing components' );
done();
} );
}

@@ -82,2 +100,4 @@

this._logger( 'notice', 'loader', 'begin d-initializing components' );
let components = this._dinitializeStack;

@@ -91,2 +111,4 @@

if ( !component ) {
this._logger( 'warn',
'loader', 'possible bug in stringstack/core, component not found in d-init stack ' + path );
return done();

@@ -102,2 +124,3 @@ }

if ( !component.initialized ) {
this._logger( 'info', 'loader', 'd-initialized component ' + path );
return done();

@@ -116,2 +139,3 @@ }

this._logger( 'info', 'loader', 'd-initialized component ' + path );
return done();

@@ -126,2 +150,3 @@

this._logger( 'info', 'loader', 'd-initialized component ' + path );
component.initialized = false;

@@ -132,4 +157,14 @@ done();

}, done );
}, ( err ) => {
if ( err ) {
this._logger( 'error', 'loader', 'error d-initializing components', err );
return done( err );
}
this._logger( 'notice', 'loader', 'finished d-initializing components' );
done();
} );
}

@@ -187,6 +222,9 @@

let container = new Container( targetPath, this );
let container = new Container( targetPath, this, this._logger );
let instance = null;
if ( typeof Module === 'function' ) {
this._logger( 'info', 'loader', 'instantiating class component: ' + targetPath );
instance = new Module( container );
} else {

@@ -197,6 +235,12 @@ instance = Module;

if ( typeof Module === 'object' && Module && typeof Module.load === 'function' ) {
this._logger( 'info', 'loader', 'loading singleton component: ' + targetPath );
Module.load( container );
} else {
this._logger( 'info', 'loader', 'imported static component: ' + targetPath );
}
}
this._instantiateStack.pop();

@@ -292,6 +336,4 @@

path = path.trim();
if ( path.endsWith( '.js' ) ) {

@@ -298,0 +340,0 @@ path = path.replace( /\.js$/, '' ); // don't need this, require adds if needed

{
"name": "@stringstack/core",
"description": "StringStack Core",
"version": "0.1.3",
"version": "0.2.0",
"repository": {

@@ -6,0 +6,0 @@ "type": "git",

+113
-1

@@ -374,2 +374,114 @@ # StringStack Core

# Logging
StringStack/core provides a logging facility that you can use to tap into your favorite logging tool. Simply pass a
logger function to the config for createApp() and get all the log writes from all components. Do so like this.
```javascript
const Core = require('@stringstack/core');
const Winston = require( 'winston' );
// log to stdout/stderr
let winston = new (Winston.Logger)( {
transports: [
new Winston.transports.Console( {
timestamp: true,
colorize: true,
level: process.env.NODE_LOG_LEVEL || 'info' // default to info, unless environment overrides
} )
]
} );
let winstonLogger = function ( level, path, message, meta ) {
// pass the event to your favorite logger, such as https://www.npmjs.com/package/winston OR, just console it.
if ( meta instanceof Error ) {
meta = ` ${message.message}: ${message.stack}`;
}
winston.log( level, `[${process.pid}] ${path}: ${message}: ${typeof meta === 'string' ? meta : JSON.stringify( meta )}`);
}
let core = new Core();
const App = core.createApp( {
log: winstonLogger,
rootComponents: [
// ...
]
} );
// daemonix also has a log facility which could easily be used in conjunction with your StringStack/core app
const daemonix = require( 'daemonix' );
daemonix( {
app: App,
log: function (level, message, meta) {
winstonLogger(level, 'daemonix', message, meta);
}
} );
```
The handler function will receive a log level, the full path to the component triggering the log event, a string message
and a meta object with relevant data about the log message. Meta might be an instance of Error, a random object literal,
or some other piece of data to describe the log event beyond the message. However,
The component loader and the generated app, both parts of StringStack/core, will generate some log entries, as well as
all StringStack/* components built by the StringStack team. The logs events generated will conform to the following
practices as it pertains to log level. We use the same log level semantics recommended by RFC5424,
https://www.npmjs.com/package/winston, and Linux' syslog.
```json
{
emerg: 0, // emergency: System is unusable. Complete system failure.
alert: 1, // alert: Action must be taken immediately. Potential data loss or curroption eminent.
crit: 2, // critical: Major system component failing, such as device IO error, network unreachable, etc.
error: 3, // error: An error occurred, but the system should be able to keep running otherwise.
warning: 4, // warning: Something less than ideal occurred, deprecated function call, bad request, etc.
notice: 5, // notice: Something significant happened, but is not a problem. This is startup, shutdown, etc.
info: 6, // information: Something common happened, is not a problem.
debug: 7, // debug: Tracking as much detail as possible on the actions of the code, incudling sensative data.
silly: 8 // silly: Tracking every detail of code, including sensative data.
}
```
The recommended frequency with which log level should be called is as follows.
```json
{
emerg: 0, // emergency: Should trigger at any time, and should be logged any time it happens.
alert: 1, // alert: Should trigger at any time, and should be logged any time it happens.
crit: 2, // critical: Should trigger at any time, and should be logged any time it happens.
error: 3, // error: Should trigger at any time, and should be logged any time it happens.
warning: 4, // warning: Should trigger at any time, and should be logged any time it happens.
notice: 5, // notice: Should only trigger a finite amount of time relative to process lifetime and to a given time window. Should not fire with frequency congruent with system load.
info: 6, // information: Should only trigger a finite amount of time relative to system load. Where notice rate < frequency rate <= load/N, where N is some real number.
debug: 7, // debug: May trigger with every system event with frequency >= load * N, where N is some real number.
silly: 8 // silly: Will trigger multiple times with every event with frequency >= load * N, where N is some real number > 1.
}
```
Recommended actions for each log level are as follows.
```json
{
emerg: 0, // emergency: Shutdown the system and investigate.
alert: 1, // alert: Shutdown the system and investigate.
crit: 2, // critical: Shutdown the system and investigate.
error: 3, // error: Investigate the error.
warning: 4, // warning: Investigate the warning.
notice: 5, // notice: Nothing, non-problem event.
info: 6, // information: Nothing, non-problem event.
debug: 7, // debug: For development and debuging only. Do not run in production under normal conditions.
silly: 8 // silly: For development and debuging only. Do not run in production under normal conditions.
}
```
# Daemonix for Linux Signal Management

@@ -399,3 +511,3 @@

let daemonix = require( 'daemonix' );
const daemonix = require( 'daemonix' );

@@ -402,0 +514,0 @@ daemonix( { app: App } );

@@ -480,79 +480,2 @@ 'use strict';

it( 'should allow config to pass to Core()', function ( done ) {
let core = new Core( {
rootComponents: [
'./test/lib/class.a'
]
} );
let App = core.createApp();
let app = new App( 'test' );
// init/dinit over and over. It is up to the actual modules to ensure they reset their internal state
// correctly on subsequent init/dinit cycles.
async.series( [
checkInitialized( app, false ),
( done ) => {
app.init( done );
},
checkInitialized( app, true ),
( done ) => {
app.dinit( done );
},
checkInitialized( app, false ),
( done ) => {
let actualEvents = getComponentManually( app, './test/lib/class.f' )._getEvents();
let expectedEvents = [
"TestA:instantiate",
"TestB:instantiate",
"TestDatabase:instantiate",
"TestConfig:instantiate",
"TestC:instantiate",
"TestD:instantiate",
"TestE:instantiate",
"StaticH:instantiate",
"TestF:instantiate",
"TestG:instantiate",
"TestConfig:init",
"TestDatabase:init",
"TestG:init",
"TestF:init",
"StaticH:init",
"TestE:init",
"TestD:init",
"TestC:init",
"TestB:init",
"TestA:init",
"TestA:dinit",
"TestB:dinit",
"TestC:dinit",
"TestD:dinit",
"TestE:dinit",
"StaticH:dinit",
"TestF:dinit",
"TestG:dinit",
"TestDatabase:dinit",
"TestConfig:dinit"
];
try {
assert.deepStrictEqual( actualEvents,
expectedEvents,
'log of instantiation, initialization and d-initialization is not correct' );
} catch ( e ) {
return done( e );
}
done();
}
], done );
} );
it( 'should allow multiple root components', function ( done ) {

@@ -887,4 +810,215 @@

it( 'should handle log events', function ( done ) {
let logHistory = [];
let core = new Core();
let App = core.createApp( {
rootComponents: [
'./test/lib/class.log.a'
],
log: ( level, path, message, meta ) => {
logHistory.push( [ level, path, message, meta ] );
}
} );
let app = new App( 'test' );
async.series( [
( done ) => {
app.init( done );
},
checkInitialized( app, true ),
( done ) => {
app.dinit( done );
},
checkInitialized( app, false ),
( done ) => {
try {
// console.log( 'logHistory', JSON.stringify( logHistory, null, 4 ) );
let dir = process.cwd();
assert.deepStrictEqual( logHistory, [
[
"info",
"loader",
"instantiating class component: " + dir + "/test/lib/class.log.a",
undefined
],
[
"info",
dir + "/test/lib/class.log.a",
"TestLogA constructor",
{
"meta": "data"
}
],
[
"info",
"loader",
"instantiating class component: " + dir + "/test/lib/class.log.b",
undefined
],
[
"info",
dir + "/test/lib/class.log.b",
"TestLogB constructor",
{
"meta": "data"
}
],
[
"verbose",
dir + "/test/lib/class.log.b",
"TestLogB constructor",
{
"meta": "data"
}
],
[
"notice",
"app",
"instantiated",
undefined
],
[
"notice",
"loader",
"begin initializing components",
undefined
],
[
"debug",
dir + "/test/lib/class.log.b",
"TestLogB init",
{
"meta": "data"
}
],
[
"info",
"loader",
"initialized component " + dir + "/test/lib/class.log.b",
undefined
],
[
"debug",
dir + "/test/lib/class.log.a",
"TestLogA init",
{
"meta": "data"
}
],
[
"warning",
dir + "/test/lib/class.log.a",
"TestLogA init warn",
undefined
],
[
"warning",
dir + "/test/lib/class.log.a",
"TestLogA init warning",
undefined
],
[
"info",
"loader",
"initialized component " + dir + "/test/lib/class.log.a",
undefined
],
[
"info",
"loader",
"initialized component config",
undefined
],
[
"info",
"loader",
"initialized component env",
undefined
],
[
"notice",
"loader",
"finished initializing components",
undefined
],
[
"notice",
"loader",
"begin d-initializing components",
undefined
],
[
"info",
"loader",
"d-initialized component env",
undefined
],
[
"info",
"loader",
"d-initialized component config",
undefined
],
[
"debug",
dir + "/test/lib/class.log.a",
"TestLogA dinit",
{
"meta": "data"
}
],
[
"info",
"loader",
"d-initialized component " + dir + "/test/lib/class.log.a",
undefined
],
[
"debug",
dir + "/test/lib/class.log.b",
"TestLogB dinit",
{
"meta": "data"
}
],
[
"info",
dir + "/test/lib/class.log.b",
"TestLogB information",
undefined
],
[
"info",
"loader",
"d-initialized component " + dir + "/test/lib/class.log.b",
undefined
],
[
"notice",
"loader",
"finished d-initializing components",
undefined
]
], 'should pass log events to logger' );
} catch ( e ) {
return done( e );
}
done();
}
], done );
} );
} );
} );