Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
ng-current
Advanced tools
Relational context manager for Angular 1.x
Services
and their related components$digest
cycle (check out this post on $broadcast
for details)Have you ever encountered challenges or annoyances with managing
your Angular 1.X application's context of related currently selected Service
entities?:
$watch
to ensure new defaults are selected properly
$digest
cycle in order to help guarantee the "latest and greatest"Services
and other components in order to support state-dependent features that become relevant at a later pointServices
, which by design, do not integrate with the $digest
cycle and often result in one or more of the aforementioned issuesManaging this current context is trivial when you're only working
with a single disjoint entity (say for instance, an extremely basic User
),
especially when you can determine the state from a canonical source like a URL:
http://example.io/user/3449538
However, modern web applications are typically more complicated
and almost always involve multiple relationships and/or hierarchies
between resource and/or Service
entities.
For example, a User
of say a construction management portal may add Contact
s and be able
to generate multiple construction Sites
, each which may have multiple Quotes
. It is often
the case that one entity of each type may be currently selected in the
application at a time (like when viewing a specific Quote
, the others
are arguably irrelevant):
User
|
+-----------------------------+
| |
v v
Site Contact
|
|
v
Quote
As an application grows, it typically becomes unorthodox to place every relevant entity's identification info in the URL:
http://example.io/user/3449538/quote/34324234/site/9883748
One can argue that since the IDs should be unique across the API, the above URL should be reducible to:
http://exaple.io/site/9883748
In other words, you should only need to know the last entity in the chain since all of the others can be inferred from it.
Deriving the other entities in this way can become difficult. For instance, a user can technically visit the page from any other page, and thus the proper state of the new page must be accessible and/or determinable from the state of any page preceding it (assuming all data is loaded asynchronously, satisfying SPA)
This issue is not unique URL/cache-based state systems - it presents itself anytime a hierarchy of non-canonical entity states needs to be managed.
Tools such as angular-ui-router
have some success with alleviating this, but in my experience force the user to be overly verbose with redundant generator methods, and worse of all needing to jump through several hoops in order to make the correct data/state accessible to deeply nested components. This stems from the fact that state (and thus isolated scope-bound instances of Services) is exclusively controlled by the current URL
, and this often makes supporting contextual features that don't quite fit into the URL scheme difficult and complex.
In order to track the other selected entities (such as Site
and Quote
),
you have a couple of idiomatic options:
Provider
, Service
, or Factory
(which by design do NOT
integrate with the $digest
cycle)Provider
)$rootScope
which sacrifices readibility and, justifiably, makes most developers cringeThese can be tolerated for a while, but pretty much all of these will require either the
use of $watch
, monolthic controllers, or repetitive/redundant bindings throughout the app in order to guarantee that your components show only the data that is relevant to the user's current selections (at least without forcing a page refresh,
which breaks SPA and in my opinion damages the user experience and quality of your application).
More examples on the challenges involved with SPAs can be found in Gooey's README. Gooey is a small JS library that takes a hierarchical, bi-directional PubSub approach for generic data synchronization and involves no polling mechanisms whatsoever.
ng-current
allows you to define a hierarchy of related contexts that that synchronize
with your already-existant Service
s and components non-invasively.
By establishing the following properties:
this.name
(required) a unique name to identify the service (often lowercase version of service)this.model
(optional) pseudo-constructor function that's refreshed on updates to your Service entitiesthis.rels
(optional) collection of immediate child entities, order independentand then registering the service at the end of your definition:
// inject `Contexts` service which serves as a transparent state orchestrator for our `Service`(s)
module.service('User', function(Contexts) {
var self = this
this.name = 'user' // rel name to use as primary lookup and to establish relations
this.rels = ['site', 'contact'] // services that have an immediate relationship / dependency to this service
this.model = function(user) {
// model logic for a single `User` entity
user.firstName = function() {
return user.givenName + ' ' + user.familyName
}
return user
}
// arbitrary user defined generator method -
// typically something using `$http` or `$resource` with cache.
// multiple users are considered here because
// more than one user may use the application
// in a single window session (asynchronous re-authentication)
this.all = function() {
return [
{id: 1, name: 'bob'},
{id: 2, name: 'donna'}
]
}
// defines how to determine the "current" user -
// can be from url, a token, anything!
// because I'm lazy, this example simply
// returns the first in the array
this.current = function() {
return self.all().then(function(users) {
return Contexts.getOr('user', users[0])
})
}
// required as the final statement of your `Service`.
// registers your Service with the global pool
Contexts.register(this)
})
We must also define Site
, Contact
and Quote
services that resemble User
, but are of course free to have their own implementations and functionality:
module.service('Site', function(Contexts) {
var self = this
this.name = 'site'
this.rels = ['quote']
this.model = function(site) {
site.label = function() {
return site.street_number + ' ' + site.street_name + ', ' + site.city + ', ' + site.state
}
return site
}
this.all = function() {
return [
{id: 1, street_number: '123', street_name: 'Magic Way', city: 'San Francisco', state: 'CA' },
{id: 2, street_number: '456', street_name: 'JavaS Way', city: 'San Francisco', state: 'CA' }
]
}
this.current = function() {
return self.all().then(function(sites) {
return Contexts.getOr('site', sites[0])
})
}
Contexts.register(this)
})
Once our Services
are defined and wired together, any components or directives that inherit their contexts will be synchronized accordingly whenever anything related to the context is published or updated.
To explain more concretely, any updates to User
will delegate to Site
and Contact
, but they will also reach Quote
beause Quote
is related to Site
which is related to User
. Every controller, directive or component dependent on these contexts will also receive the udpates:
module.directive('currentQuote', function(Contexts, Quote, $log) {
return {
restrict: 'EA',
template: '<h1>Selected Quote</h1><p>{{ quote | json }}</p>',
controller: function(scope) {
// this callback will trigger whenever a new `User`, `Site`, or `Quote` is selected :D
Quote.use('current', function(quote) {
$log.info('New quote selected', quote)
scope.quote = quote
})
}
}
})
To see a working example, check out this Plunker.
npm install ng-current
ES5
var Current = require('ng-current')
ES6
import Current from 'ng-current'
Be sure to require angular
first so that it's accessible to ng-current
:
import angular
import Current from 'ng-current'
Then add it to your own module:
angular.module('myModule', ['ng-current'])
If you aren't using a package tool like webpack
or browserify
, then you can of course fall back to the traditional method:
Full
<script type="text/javascript" src="/node_modules/ng-current/ng-current.js"></script>
Minified
<script type="text/javascript" src="/node_modules/ng-current/ng-current.min.js"></script>
FAQs
Relational context manager for Angular
The npm package ng-current receives a total of 3 weekly downloads. As such, ng-current popularity was classified as not popular.
We found that ng-current 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
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.