@forrestjs/core
Advanced tools
Comparing version 5.0.0-alpha.8 to 5.0.0-alpha.9
{ | ||
"name": "@forrestjs/core", | ||
"description": "ForrestJS is the Javascript plugin syste.", | ||
"version": "5.0.0-alpha.8", | ||
"version": "5.0.0-alpha.9", | ||
"main": "src/index.js", | ||
@@ -34,3 +34,3 @@ "author": "Marco Pegoraro <marco.pegoraro@gmail.com", | ||
}, | ||
"gitHead": "4641fba2f1c825abd64608fc8a433e39cd9c8d22", | ||
"gitHead": "9ebb71ecc490eeb9578a71a0db622babe67ea020", | ||
"devDependencies": { | ||
@@ -37,0 +37,0 @@ "jest": "^28.1.0" |
const { traceAction } = require('./tracer'); | ||
const { logAction } = require('./logger'); | ||
const { logAction, getLevelNumber } = require('./logger'); | ||
const scalars = ['number', 'string', 'boolean']; | ||
const spreadArgs = (args) => | ||
scalars.includes(typeof args) ? args : { ...args }; | ||
/** | ||
* TEMPORARY: | ||
* So far App context is passed as second parameter | ||
* | ||
* Lifecycle methods send in the ctx as first parameter as well, | ||
* so we have to detect this situation and replace with the | ||
* decorated context. | ||
* | ||
* TODO: Remove this check in v6x when the CTX will always | ||
* go as first parameter. | ||
* | ||
* @param {*} args | ||
* @param {*} ctx | ||
* @returns | ||
*/ | ||
const spreadArgs = (args, ctx) => { | ||
if (typeof args === 'object' && args.log && args.getContext) | ||
return [ctx, ctx]; | ||
return [scalars.includes(typeof args) ? args : { ...args }, ctx]; | ||
}; | ||
const conditionalLogger = ({ logLevel }, { context }) => { | ||
// Handle usage of isolated actions: | ||
if (!context || !context.log) { | ||
return null; | ||
} | ||
const { log } = context; | ||
// Handle pass-through scenarios: | ||
if (logLevel === true || (!logLevel && logLevel !== false)) { | ||
return log; | ||
} | ||
// Shut down the logger | ||
// It creates a dummy instance that implements all the | ||
if (logLevel === false) { | ||
const fakeLogger = () => {}; | ||
Object.keys(log).forEach((key) => { | ||
if (typeof log[key] === 'function') { | ||
fakeLogger[key] = () => {}; | ||
} | ||
}); | ||
return fakeLogger; | ||
} | ||
// Try to create a clone with a different log level | ||
if (log.cloneWithLogLevel) { | ||
return log.cloneWithLogLevel(logLevel); | ||
} | ||
return log; | ||
}; | ||
const runAction = async (action, options) => { | ||
@@ -13,4 +64,10 @@ logAction('run', action); | ||
traceAction(action, options); | ||
const args = spreadArgs(options.args); | ||
const result = await action.handler(args, options.context); | ||
// console.log('@callASync'); | ||
const args = spreadArgs(options.args, { | ||
...options.context, | ||
log: conditionalLogger(action, options), | ||
}); | ||
const result = await action.handler(...args); | ||
return [result, action, options]; | ||
@@ -26,4 +83,10 @@ } catch (err) { | ||
traceAction(action, options); | ||
const args = spreadArgs(options.args); | ||
const result = action.handler(args, options.context); | ||
// console.log('@callSync'); | ||
const args = spreadArgs(options.args, { | ||
...options.context, | ||
log: conditionalLogger(action, options), | ||
}); | ||
const result = action.handler(...args); | ||
return [result, action, options]; | ||
@@ -30,0 +93,0 @@ } catch (err) { |
@@ -7,2 +7,3 @@ const dotted = require('@marcopeg/dotted').default; | ||
const constants = require('./constants'); | ||
const { makeLogger, LOG_LEVELS } = require('./logger'); | ||
const { | ||
@@ -77,9 +78,7 @@ ForrestJSGetConfigError, | ||
...context, | ||
registerAction: (ag1, ag2, ag3 = {}) => { | ||
// Handle definition as an object | ||
return registeredExtensions.push({ | ||
...ag1, | ||
name: `${prefix}${ag1.name || integrationName}`, | ||
}); | ||
}, | ||
registerAction: ({ name, ...config }) => | ||
registeredExtensions.push({ | ||
...config, | ||
name: `${prefix}${name || integrationName}`, | ||
}), | ||
}) | ||
@@ -113,3 +112,2 @@ : service; | ||
} | ||
// Register all the actions declared by the integrations that have been executed | ||
@@ -155,6 +153,9 @@ registeredExtensions.forEach(context.registerAction); | ||
/** | ||
* TODO: In v5.0.0 we can destructure the appManifest as so to provide | ||
* code hints through VSCode | ||
* @param {} appManifest | ||
* @returns | ||
* Create a ForrestJS App Context | ||
* @param {IntegrationObject[]} services List of services that compose theapp | ||
* @param {IntegrationObject[]} features List of features that compose theapp | ||
* @param {Object | Function} settings Settings object or async function that produces a settings object | ||
* @param {Object} context Application initial context | ||
* @param {string} logLevel Log level for the default logger | ||
* @returns {Promise} App instance | ||
*/ | ||
@@ -168,2 +169,3 @@ const createApp = | ||
trace = null, | ||
logLevel = process.env.LOG_LEVEL || 'info', | ||
} = {}) => | ||
@@ -173,3 +175,3 @@ async () => { | ||
// or automatically register the provided settings callback | ||
const internalSettings = | ||
const computedSettings = | ||
typeof settings === 'function' | ||
@@ -179,2 +181,15 @@ ? registerSettingsExtension(settings) | ||
// Decorates the application settings with the logger | ||
// configuration | ||
const internalSettings = { | ||
...computedSettings, | ||
// Provide default logging settings: | ||
logger: { | ||
level: logLevel, | ||
levelsMap: LOG_LEVELS, | ||
transport: console.log, | ||
...(computedSettings.logger || {}), | ||
}, | ||
}; | ||
// Context bound list of known Extensions | ||
@@ -195,2 +210,8 @@ const targetsRegistry = createRegistry(constants); | ||
const internalContext = { | ||
// Add basic logging mechanism | ||
// (could be replaced by extensions) | ||
log: makeLogger(internalSettings.logger.level, { | ||
levelsMap: internalSettings.logger.levelsMap, | ||
transport: internalSettings.logger.transport, | ||
}), | ||
...context, | ||
@@ -287,4 +308,12 @@ ...targetsRegistry, | ||
trace = null, | ||
logLevel, | ||
} = {}) => { | ||
const app = createApp({ services, features, settings, context, trace }); | ||
const app = createApp({ | ||
services, | ||
features, | ||
settings, | ||
context, | ||
trace, | ||
logLevel, | ||
}); | ||
return app(); | ||
@@ -291,0 +320,0 @@ }; |
@@ -82,7 +82,5 @@ const { runAction, runActionSync } = require('./actions'); | ||
return new Promise(async (resolve, reject) => { | ||
// console.log('@@@@ SERIE', name); | ||
try { | ||
const results = []; | ||
for (const action of actions) { | ||
// console.log('>>>', action); | ||
results.push(await runAction(action, options)); | ||
@@ -89,0 +87,0 @@ } |
@@ -25,2 +25,94 @@ // memoize log level at request time because it might be loaded | ||
module.exports = { log, logAction }; | ||
const LOG_LEVELS = { | ||
error: 0, | ||
warn: 1, | ||
info: 2, | ||
http: 3, | ||
verbose: 4, | ||
debug: 5, | ||
silly: 6, | ||
}; | ||
/** | ||
* Converts a log level name into a log level number | ||
* @param {String} level log level name | ||
* @param {Object} levels log levels map | ||
* @param {Number} defaultValue default value in case the level is not mapped | ||
* @returns | ||
*/ | ||
const getLevelNumber = (level, levels = LOG_LEVELS, defaultValue = 0) => | ||
levels[String(level).toLowerCase()] || defaultValue; | ||
/** | ||
* Creates a logger instance that logs to the console | ||
* @param {String} LOG_LEVEL max level to log | ||
* @param {Function} transport a logger function | ||
* @returns | ||
*/ | ||
const makeLogger = ( | ||
logLevel = 'info', | ||
{ transport = console.log, levelsMap = LOG_LEVELS } = {}, | ||
) => { | ||
const logNumber = getLevelNumber(logLevel, levelsMap); | ||
/** | ||
* Generic logger function | ||
* @param {String} level desired logger level | ||
* @param {...any} args params to forward to the transport | ||
*/ | ||
const logger = (level, ag1, ...args) => { | ||
if (getLevelNumber(level, levelsMap) <= logNumber) { | ||
if (typeof ag1 === 'string') { | ||
const [ag2, ...argsRest] = args; | ||
if (ag2) { | ||
if (typeof ag2 === 'object') { | ||
transport( | ||
`${level}: ${ag1}`, | ||
{ | ||
...ag2, | ||
level, | ||
}, | ||
...argsRest, | ||
); | ||
} else { | ||
transport( | ||
`${level}: ${ag1}`, | ||
{ | ||
level, | ||
}, | ||
ag2, | ||
...argsRest, | ||
); | ||
} | ||
} else { | ||
transport(`${level}: ${ag1}`, { level }, ...args); | ||
} | ||
} else { | ||
const { message, ...ag1Rest } = ag1; | ||
transport( | ||
`${level}: ${message}`, | ||
...[ | ||
{ | ||
...ag1Rest, | ||
level, | ||
}, | ||
...args, | ||
], | ||
); | ||
} | ||
} | ||
}; | ||
// Add the shortcut methods | ||
Object.keys(levelsMap).forEach((key) => { | ||
logger[key] = (...args) => logger(key, ...args); | ||
}); | ||
// Create a custom logger clone | ||
logger.cloneWithLogLevel = (logLevel) => | ||
makeLogger(logLevel, { transport, levelsMap }); | ||
return logger; | ||
}; | ||
module.exports = { log, logAction, makeLogger, getLevelNumber, LOG_LEVELS }; |
@@ -23,2 +23,3 @@ /** | ||
optional = false, | ||
logLevel = null, | ||
...meta | ||
@@ -63,2 +64,3 @@ } = {}) => { | ||
optional, | ||
logLevel, | ||
}; | ||
@@ -65,0 +67,0 @@ |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
39210
1064
2