Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
ampersand-app
Advanced tools
Simple instance store for managing instances without circular dependency issues in ampersand apps.
Part of the Ampersand.js toolkit for building clientside applications.
Simple instance store and event channel that allows different modules within your app to communicate without requiring each other directly. The entire module is only ~30 lines of code, you can read the source here to see exactly what it does.
Whenever you require('ampersand-app')
it returns the same instance of a plain 'ol JavaScript Object
.
This is called the Singleton pattern.
This object it returns is nothing special. It's just a plain old JavaScript Object
that has been decorated with ampersand-events methods as well as an extend
and reset
method.
That's it!
It's quite common to create an app
global to store collections and models on and then to reference that global whenever you need to look up related model instance from another module within your app. However, this creates many indirect interdependencies within your application which makes it more difficult to test isolated parts of your application.
It's also quite common to need "application-level" events that any number of pieces of your app may need to handle. For example, navigation events, or error events that could be triggered by any number of things within your app but that you want to handle by a single module that shows them as nice error dialogs.
This module provides a pattern to address both those cases without having to rely on globals, or have circular dependency issues within your apps. It also means you don't have to adjust code linting rules to ignore that app
global.
Before ampersand-app
Module "A" (app.js):
var MyModel = require('./models/some-model');
// explicitly create global
window.app = {
init: function () {
this.myModel = new MyModel();
}
};
window.app.init();
Module "B" (that needs access to app
):
// note we're not requiring anything
module.exports = View.extend({
someMethod: function () {
// reference app and models directly
app.myModel.doSomething():
}
});
With ampersand-app
you'd do this instead:
Module "A" (app.js):
// it just requires ampersand-app too!
var app = require('ampersand-app');
var MyModel = require('./models/some-model');
// Here we could certainly *chose* to attach it to
// window for better debugging in the browser
// but it's no longer necessary for accessing the
// app instance from other modules.
app.extend({
init: function () {
this.myModel = new MyModel();
}
};
app.init();
Module "B" (that needs access to app
):
// this just requires ampersand-app too!
var app = require('ampersand-app');
module.exports = View.extend({
someMethod: function () {
// reference app that we required above
app.myModel.doSomething():
// now as a bonus, since `app` supports events
// we've also got a global "pubsub" mechanism
// for app events, that any other modules can
// listen to.
app.trigger('some custom event');
}
});
Now when we go to write tests for module "B" we can easily mock things that it expects from app
.
So our tests for module B might look like this:
var test = require('tape');
var ModuleB = require('../module-b');
// note we just require ampersand-app here
// and make sure it has what module b expects
var app = require('ampersand-app');
test('test module B', function (t) {
// each test can clear it.
app.reset();
// stub out what it might need for the
// test.
app.myModel = {
doSomething: function () {}
};
// check to make sure calling
// `someMethod` fires event on app
app.on('some custom event', function () {
t.pass('custom event fired');
// app also has a `reset` for testing
// purposes that purges it to start over
// so this could be used to reset before each test
app.reset();
t.end();
});
var view = new ModuleB();
t.doesNotThrow(function () {
view.someMethod();
}, 'make sure calling some method does not explode');
});
test('next test', function () {
// now we can use `reset` if we want
// to make sure we clear that state
app.reset();
// etc. etc.
});
If you're writing a re-usable module for distribution on npm it should not have ampersand-app
as a dependency.
Doing so makes assumptions about how you want it to be used.
Say you want to make an error
event handling module, that requires ampersand-app
listens for error
events from that app
and shows a nice error dialog.
Rather than make all those assumptions about how its going to be used, just make the nice error dialog view and suggest in the readme how someone might use ampersand-app
as an event channel to trigger them.
This allows people who don't use this particular application pattern to still use your npm module and leaves the event names, and application architecture up to the person building the app.
npm install ampersand-app
The app
object is an event object so it contains all the methods as described in the ampersand-events docs.
The app
object becomes a handy way to communicate within your app so various modules can notify each other about "app-level" events such as user navigation, etc.
app.extend(obj, [*objs])
Convenience method for attaching multiple things to the app at once. This is simply an alias for amp-extend
that pre-fills the app
as the object being extended.
obj
{Object} copy properties from this object onto app
. You can pass as many objects to this as you want as additional arguments.var app = require('ampersand-app');
var UserCollection = require('./models/user-collection');
var MeModel = require('./models/me');
app.extend({
me: new MeModel(),
users: new UserCollection(),
router: new Router(),
init: function () {
this.router.history.start({pushState: true});
}
});
app.reset()
Resets the app singleton to its original state, clearing all listeners, and deleting everything you've added to it, but keeping the same object instance.
This is primarily for simplifying unit testing of modules within your app. Whenever you require('ampersand-app')
you get the same object instance (this is the Singleton pattern). So, having app.reset()
lets you mock app state required for testing a given module.
Created by @HenrikJoreteg.
MIT
FAQs
Simple instance store for managing instances without circular dependency issues in ampersand apps.
The npm package ampersand-app receives a total of 467 weekly downloads. As such, ampersand-app popularity was classified as not popular.
We found that ampersand-app demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers 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
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.