Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Fount is a promise based DI container for Node.js.
npm install fount -S
var fount = require( 'fount' );
Fount supports two styles of identifying dependency: string array (like AMD) and by argument names (like Angular).
Example:
// string array
fount.inject( [ 'one', 'two', 'three' ], function( one, two, three ) {
// your code here
} );
// argument name
fount.inject( function( one, two, three ) {
// your code here
} );
The second approach is easier to read when starting out, but consider how fragile it is. If someone were to come along and refactor your generic arguments to be more expressive and not change the keys the dependencies were registered against, it would break a lot of code.
You get to choose the style you prefer, just keep in mind there's more risk with argument name only.
Fount supports multiple containers. If you don't specify one when making calls, it will use the 'default' container. Most examples in this doc use the default container implicitly.
You can use a named container in two ways:
fount( 'myContainer' ).resolve( 'myKey' ).then( function( value ) {
// do something cool
} );
// same as above, but terser
fount.resolve( 'myContainer.myKey' ).then( function( value ) {
// do something cool
} );
Chances are you won't need this - you'll register dependencies and resolve them and never think about lifecycle or scope. When you do need more control, fount allows you to supply lifecycle arguments during registration and an optional scope name during resolution that give you more granular control over resolution.
A scope is just a simple name that can affect how a function dependency is resolved if it was specified with a scoped
lifecycle. When resolving a dependency with a scoped
lifecycle, a default
will be used when resolving dependencies. (see the Registering section for examples)
Think of a scope in Fount like a second level of caching (because that's exactly what it is). You can purge a scope anytime with purgeScope
:
fount.purgeScope( 'myScope' );
A lifecycle tells fount how long the result of a function dependency is good for. Static is the the default.
Registering is simple - provide a string name and then supply either a value, function or promise. See each section for more detail.
// lifeCycle is optional and 'static' by default
fount.register( 'name', value | function | promise, [lifeCycle] );
Once a value is registered, fount will always supply that value to any resolve call. It doesn't actually make sense to provide a lifecycle option with a value or promise since it has no effect, but fount doesn't freak out if you forget and do this by accident.
fount.register( 'port', 8080 );
Registering a function with fount will cause it to invoke the function during resolution and return the result with two exceptions:
In these exceptional scenarios, fount will resolve the dependency with the function itself rather than calling it for you.
fount.register( 'factory', function() { return 'a thing!' } );
If you want fount to inject dependencies into the function when calling it, you'll need to provide a string array of the dependencies in the order they should be supplied to the function:
// AMD users should feel right at home with this style
fount.register( 'factory', [ 'a', 'b', 'c' ], function( a, b, c ) {} );
// Angular fans and dare-devils may enjoy this style
// dependencies are 'read' out of the argument list
fount.register( 'factory', function( a, b, c ) {} );
You may want to register a function as a value (confused yet?) so that fount returns the function as a dependency rather than executing it for you. If that's what you're looking for, try this:
fount.register( 'calculator', function() { return function( x, y ) { return x + y; }; } );
Registering a promise looks almost identical to registering a function. From a consuming perspective, they're functionally equivalent since fount will wrap raw function execution in a promise anyway.
fount.register( 'todo', when.promise( function( reject, resolve ) {
resolve( 'done' );
} ) );
Resolving is pretty simple - fount will always return a promise to any request for a dependency.
fount.resolve( 'gimme' ).then( function( value ) { // do something } );
fount.resolve( 'gimme', 'custom' ).then( function( value ) { // value for scope 'custom' } );
// resolve multiple dependencies at once!
fount.resolve( [ 'one', 'two' ] ).then( function( results ) {
// results is a hash, not an array
} );
// resolve multiple dependencies ACROSS containers
fount.resolve( [ 'a.one', 'b.two' ] ).then( function( results ) {
// results is a hash, not an array
} );
You can also check in advance whether or not fount is able to resolve a dependency using canResolve
:
fount.canResolve( 'key1' );
fount.canResolve( [ 'key1', 'key2' ] );
Injecting is how you get fount to invoke a function on your behalf with resolved dependencies. If you're familiar with AMD, it's somewhat similar to how define works.
// where 'a' and 'b' have been registered
fount.inject( [ 'a', 'b' ], function( a, b ) { ... } );
// within custom scope -- requires a and/or b to have been registered with 'scoped' lifecycle
fount.inject( [ 'a', 'b' ], function( a, b ) { ... }, 'myScope' );
// using keys across multiple containers
fount.inject( [ 'one.a', 'two.b' ], function( a, b ) { ... } );
// alternate support for multiple containers
fount.inject( function( one_a, two_b ) { ... } );
Configuration of multiple containers, keys and values can be accomplished via a configuration hash passed to fount. The format of the hash is as follows:
{
[containerName]: {
[keyName]: [value],
[keyName]: {
[scope]: [value]
}
}
}
example
fount( {
default: {
a: 1,
b: function() {
return 2;
}
},
other: {
c: { scoped: 3 },
d: { scoped: function() {
return 4;
}
},
e: { static: 5 },
f: { factory: function() {
return 6;
} }
}
} );
Right now this is pretty weak, but if you call log
, Fount will dump the containers and scopes out so you can see what keys are present. Got ideas for more useful ways to troubleshoot? I'd love a PR :smile:!
gulp
starts both the test
and watch
tasks, so you'll see the tests re-run any time you save a file under src/
or spec/
.gulp coverage
will run istanbul and create a coverage/
folder.gulp show-coverage
will run istanbul and open the browser-based coverage report.FAQs
A source from which dependencies flow
The npm package fount receives a total of 2,067 weekly downloads. As such, fount popularity was classified as popular.
We found that fount demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.