Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nanocomponent

Package Overview
Dependencies
Maintainers
5
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nanocomponent - npm Package Compare versions

Comparing version 5.0.3 to 6.0.0-0

CHANGELOG.md

7

example/index.js

@@ -7,8 +7,7 @@ // adapted from https://github.com/timwis/choo-leaflet-demo/blob/master/src/index.js

var choo = require('choo')
var Leaflet = require('./leaflet.js')
css('./leaflet.css')
css('leaflet')
var leaflet = Leaflet()
var leaflet = new Leaflet()
var app = choo()

@@ -34,3 +33,3 @@

<main>
${leaflet.render({ coords: state.coords })}
${leaflet.render(state.coords)}
</main>

@@ -37,0 +36,0 @@ </body>

@@ -15,48 +15,35 @@ // // adapted from https://github.com/timwis/choo-leaflet-demo/blob/master/src/map.js

this._log = nanologger('leaflet')
this.state.map = null
this.state.zoom = 12
this.map = null // capture leaflet
this.coords = [0, 0] // null island
}
Leaflet.prototype = Object.create(Nanocomponent.prototype)
Leaflet.prototype._render = function () {
var self = this
Leaflet.prototype._render = function (coords) {
this.coords = coords
return html`
<div style="height: 500px">
<div id="map"></div>
</div>
`
}
if (!this.state.map) {
this._element = html`<div style="height: 500px"></div>`
if (this._hasWindow) this._createMap()
} else {
Leaflet.prototype._update = function (coords) {
if (!this.map) return this._log.warn('missing map', 'failed to update')
if (coords[0] !== this.coords[0] || coords[1] !== this.coords[1]) {
var self = this
onIdle(function () {
self._updateMap()
self.coords = coords
self._log.info('update-map', coords)
self.map.setView(coords, 12)
})
}
return this._element
return false
}
Leaflet.prototype._update = function (props) {
return props.coords[0] !== this.props.coords[0] ||
props.coords[1] !== this.props.coords[1]
}
Leaflet.prototype._load = function () {
this.state.map.invalidateSize()
this._log.info('load')
}
Leaflet.prototype._unload = function () {
this._log.info('unload')
this.state.map.remove()
this.state = {}
this._element = null
}
Leaflet.prototype._createMap = function () {
var element = this._element
var coords = this.props.coords
var zoom = this.state.zoom
Leaflet.prototype._willRender = function (el) {
var coords = this.coords
this._log.info('create-map', coords)
var map = leaflet.map(element).setView(coords, zoom)
var map = leaflet.map(el).setView(coords, 12)
leaflet.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.{ext}', {

@@ -69,9 +56,16 @@ attribution: 'Map tiles by <a href="https://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',

}).addTo(map)
this.state.map = map
this.map = map
}
Leaflet.prototype._updateMap = function () {
var coords = this.props.coords
this._log.info('update-map', coords)
this.state.map.setView(coords)
Leaflet.prototype._load = function () {
this._log.info('load')
this.map.invalidateSize()
}
Leaflet.prototype._unload = function () {
this._log.info('unload')
this.map.remove()
this.map = null
this.coords = [0, 0]
}

@@ -0,86 +1,109 @@

var document = require('global/document')
var morph = require('nanomorph')
var onload = require('on-load')
var assert = require('assert')
var KEY = 'ncid-' + (new Date() % 9e6).toString(36)
var INDEX = 0
module.exports = Nanocomponent
function makeID () {
return 'ncid-' + Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
}
function Nanocomponent () {
this._hasWindow = typeof window !== 'undefined'
this._ID = KEY + '-' + INDEX++
this._placeholder = null
this._onload = onload
this._element = null
this._loaded = false
this.props = {}
this.oldProps = null
this.state = {}
}
this._id = null // represents the id of the root node
this._ncID = null // internal nanocomponent id
this._proxy = null
this._args = []
this._loaded = false // Used to debounce on-load when child-reordering
Nanocomponent.prototype._ensureID = function () {
// Get ID - needed for nanomorph child element reordering
var id = this._element.getAttribute('id')
if (!id) this._element.setAttribute('id', this._ID)
else this._ID = id
}
this._handleLoad = this._handleLoad.bind(this)
this._handleUnload = this._handleUnload.bind(this)
Nanocomponent.prototype._rerender = function (props) {
this.oldProps = this.props
this.props = props
this._element = this._render()
this._ensureID()
var self = this
Object.defineProperty(this, 'element', {
get: function () {
var el = document.getElementById(self._id)
if (el) return el.dataset.nanocomponent === self._ncID ? el : undefined
}
})
}
Nanocomponent.prototype.render = function (props) {
assert.equal(typeof this._render, 'function', 'nanocomponent: this._render should be implemented')
assert.equal(typeof this._update, 'function', 'nanocomponent: this._update should be implemented')
Nanocomponent.prototype.render = function () {
var self = this
var len = arguments.length
var args = new Array(len)
for (var i = 0; i < len; i++) args[i] = arguments[i]
var args = new Array(arguments.length)
for (var i = 0; i < arguments.length; i++) args[i] = arguments[i]
if (!this._hasWindow) {
this._rerender(props)
return this._element
} else if (!this._element) {
this._rerender(props)
this._onload(this._element, function () {
if (self._loaded) return
self._loaded = true
if (self._load) {
window.requestAnimationFrame(function () {
self._load()
})
}
}, function () {
if (document.body.contains(self._element)) return
self._loaded = false
if (self._unload) {
window.requestAnimationFrame(function () {
self._unload()
})
}
}, this._ID)
return this._element
} else {
var shouldUpdate = this._update(props)
return this._render.apply(this, args)
} else if (this.element) {
var shouldUpdate = this._update.apply(this, args)
if (shouldUpdate) {
this._rerender(props)
this._args = args
morph(this.element, this._handleRender(args))
if (this._didUpdate) window.requestAnimationFrame(function () { self._didUpdate(self.element) })
}
if (!this._placeholder) this._placeholder = this._createPlaceholder()
return this._placeholder
if (!this._proxy) { this._proxy = this._createProxy() }
return this._proxy
} else {
this._ncID = makeID()
this._args = args
this._proxy = null
var el = this._handleRender(args)
if (this._willRender) this._willRender(el)
if (this._load || this._unload) {
onload(el, this._handleLoad, this._handleUnload, this)
}
return el
}
}
Nanocomponent.prototype._createPlaceholder = function () {
var el = document.createElement('div')
el.setAttribute('data-nanocomponent', '')
el.setAttribute('id', this._ID)
Nanocomponent.prototype._handleRender = function (args) {
var el = this._render.apply(this, args)
assert(el instanceof window.HTMLElement, 'nanocomponent: _render should return a DOM node')
return this._brandNode(this._ensureID(el))
}
Nanocomponent.prototype._createProxy = function () {
var proxy = document.createElement('div')
var self = this
el.isSameNode = function (el) {
return el === self._element
this._brandNode(proxy)
proxy.id = this._id
proxy.isSameNode = function (el) {
return (el && el.dataset.nanocomponent === self._ncID)
}
return el
return proxy
}
Nanocomponent.prototype._brandNode = function (node) {
node.setAttribute('data-nanocomponent', this._ncID)
return node
}
Nanocomponent.prototype._ensureID = function (node) {
if (node.id) this._id = node.id
else node.id = this._id = this._ncID
return node
}
Nanocomponent.prototype._handleLoad = function () {
var self = this
if (this._loaded) return // Debounce child-reorders
this._loaded = true
if (this._load) window.requestAnimationFrame(function () { self._load() })
}
Nanocomponent.prototype._handleUnload = function () {
var self = this
if (this.element) return // Debounce child-reorders
this._loaded = false
if (this._unload) window.requestAnimationFrame(function () { self._unload() })
}
Nanocomponent.prototype._render = function () {
throw new Error('nanocomponent: _render should be implemented!')
}
Nanocomponent.prototype._update = function () {
throw new Error('nanocomponent: _update should be implemented!')
}
{
"name": "nanocomponent",
"version": "5.0.3",
"description": "Create performant HTML elements",
"version": "6.0.0-0",
"description": "Native DOM components that pair nicely with DOM diffing algorithms",
"main": "index.js",
"scripts": {
"build": "bankai build example --optimize",
"deps": "dependency-check . && dependency-check . --extra --no-dev -i yo-yoify",
"start": "bankai start example",
"test": "standard && npm run deps",
"test:cov": "standard && npm run deps"
"deps": "dependency-check . && dependency-check . --extra --no-dev",
"test": "standard *.js && npm run deps && NODE_ENV=test node test | tap-format-spec",
"start": "bankai start example"
},
"repository": "yoshuawuyts/nanocomponent",
"repository": {
"type": "git",
"url": "git+https://github.com/choojs/nanocomponent.git"
},
"keywords": [
"dom",
"node",
"universal"
"bel",
"choo",
"element",
"thunk",
"cache",
"perf",
"nanomorph",
"morphdom",
"nanocomponent",
"cache-component"
],
"author": "Trainspotters",
"contributors": [
"Bret Comnes <bcomnes@gmail.com> (http://bret.io)"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/choojs/nanocomponent/issues"
},
"homepage": "https://github.com/choojs/nanocomponent#readme",
"dependencies": {
"global": "^4.3.1",
"nanomorph": "^5.1.2",
"on-load": "^3.2.0"
},
"devDependencies": {
"bankai": "^5.5.2",
"bel": "^4.6.0",
"choo": "^5.1.4",
"choo-log": "^6.0.0",
"dependency-check": "^2.7.0",
"inherits": "^2.0.3",
"istanbul": "^0.4.5",
"leaflet": "^1.0.3",
"microbounce": "^1.0.0",
"nanologger": "^1.0.2",
"on-idle": "^1.0.0",
"standard": "^8.6.0",
"tachyons": "^4.6.1",
"tape": "^4.6.3",
"uglifyify": "^3.0.4",
"unassertify": "^2.0.4",
"yo-yoify": "^3.5.0"
"@tap-format/spec": "^0.2.0",
"bankai": "^8.1.1",
"bel": "^5.0.0",
"choo": "^5.6.2",
"choo-log": "^7.0.1",
"dependency-check": "^2.6.0",
"envify": "^4.0.0",
"leaflet": "^1.1.0",
"nanologger": "^1.2.0",
"on-idle": "^3.1.0",
"standard": "^10.0.0",
"tape": "^4.6.0",
"microbounce": "^1.0.0"
}
}

@@ -5,123 +5,310 @@ # nanocomponent [![stability][0]][1]

`1kb` library to wrap native DOM libraries to work with DOM diffing algorithms.
Native DOM components that pair nicely with DOM diffing algorithms.
## Features
- Isolate native DOM libraries from DOM diffing algorithms
- Makes rendering elements _very fast™_ by avoiding unnecessary rendering
- Component nesting and state update passthrough
- Implemented in only a few lines
- Only uses native DOM methods
- Class based components offering a familiar component structure
- Works well with [bel][bel] and [yoyoify][yoyoify]
## Usage
```js
// Implementer API
// button.js
var Nanocomponent = require('nanocomponent')
var html = require('bel')
function MyButton () {
if (!(this instanceof MyButton)) return new MyButton()
function Button () {
if (!(this instanceof Button)) return new Button()
this._color = null
Nanocomponent.call(this)
}
MyButton.prototype = Object.create(Nanocomponent.prototype)
Button.prototype = Object.create(Nanocomponent.prototype)
MyButton.prototype._render = function () {
if (!this._element) {
// initial render
Button.prototype._render = function (color) {
this._color = color
return html`
<button style="background-color: ${color}">
Click Me
</button>
`
}
// Override default shallow compare _update function
Button.prototype._update = function (newColor) {
return newColor !== this._color
}
```
```js
// index.js
var choo = require('choo')
var Button = require('./button.js')
var button = Button()
var app = choo()
app.route('/', mainView)
app.mount('body')
function mainView (state, emit) {
return html`
<body>
${button.render(state.color)}
</body>
`
}
app.use(function (state, emitter) {
state.color = 'green'
})
```
## Patterns
These are some common patterns you might encounter when writing components.
### Standalone
Nanocomponents is part of the choo ecosystem, but works great standalone!
```js
var Button = require('./button.js')
var button = new Button()
// Attach to DOM
document.body.appendChild(button.render('green'))
// Update mounted component
button.render('green')
button.render('red')
// Log a reference to the mounted dom node
console.log(button.element)
```
### Binding event handlers as component methods
Sometimes it's useful to be pass around prototype methods into other functions.
This can be done by binding the method that's going to be passed around:
```js
var Nanocomponent = require('nanocomponent')
var html = require('bel')
function Component () {
if (!(this instanceof Button)) return new Component()
Nanocomponent.call(this)
// Bind the method so it can be passed around
this._handleClick = this._handleClick.bind(this)
}
Component.prototype = Object.create(Nanocomponent.prototype)
Component.prototype._handleClick = function () {
console.log('element is', this.element)
}
Component.prototype._render = function () {
return html`<div>My component</div>`
}
```
### ES6 Class Syntax
Because Class syntax is just sugar for prototype code, Nanocomponent can be
written using Classes too:
```js
var Nanocomponent = require('nanocomponent')
var html = require('bel')
class Component extends Nanocomponent {
constructor () {
super()
this._color = null
}
_render (color) {
this._color = color
return html`
<button style="background-color: ${this.props.color}">
Click Me
</button>
<div style="background-color: ${color}">
Color is ${color}
</div>
`
} else {
// mutate this._element
this._element.style.backgroundColor = this.props.color
}
_update (newColor) {
return newColor !== this._color
}
}
```
MyButton.prototype._update = function (props) {
return props.color !== this.props.color
### Mutating the components instead of re-rendering
Sometimes you might want to mutate the element that's currently mounted, rather
than performing DOM diffing. Think cases like third party widgets that manage
themselves.
```js
var Nanocomponent = require('nanocomponent')
var html = require('bel')
function Component () {
if (!(this instanceof Button)) return new Component()
Nanocomponent.call(this)
this._text = ''
}
Component.prototype = Object.create(Nanocomponent.prototype)
Component.prototype._render = function (text) {
this._text = text
return html`<h1>${text}</h1>`
}
Component.prototype._update = function (text) {
if (text !== this._text) {
this._text = text
this.element.innerText = this._text // Directly update the element
}
return false // Don't call _render again
}
Component.prototype._unload = function (text) {
console.log('No longer mounted on the DOM!')
}
```
### Nested components and component containers
Components nest and can skip renders at intermediary levels. Components can
also act as containers that shape app data flowing into view specific
components.
```js
// Consumer API
var MyButton = require('./my-button.js')
var myButton = MyButton()
document.body.appendChild(myButton.render())
var Nanocomponent = require('nanocomponent')
var html = require('bel')
var Button = require('./button.js')
function Component () {
if (!(this instanceof Button)) return new Component()
Nanocomponent.call(this)
this._button1 = new Button ()
this._button2 = new Button ()
this._button3 = new Button ()
}
Component.prototype = Object.create(Nanocomponent.prototype)
Component.prototype._render = function (state) {
var colorArray = this._shapeData(state)
return html`
<div>
${this._button1.render(colorArray[0])}
${this._button2.render(colorArray[1])}
${this._button3.render(colorArray[2])}
</div>
`
}
Component.prototype._update = function (state) {
var colorArray = this._shapeData(state) // process app specific data in a container
this._button1.render(colorArray[0]) // pass processed data to owned children components
this._button2.render(colorArray[1])
this._button3.render(colorArray[2])
return false // always return false when mounted
}
Component.prototype._shapeData = function (state) {
return [state.colors.color1, state.colors.color2, state.colors.color3]
}
```
## Implementing higher level APIs
No matter the language, inheritance is tricky. Each layer adds more
abstractions and can make it hard to understand what's going on. That's why we
don't recommend doing more than one level of inheritance. However, this means
that any API built on top of Nanocomponent directly shouldn't also expose a
prototypical API.
## FAQ
### Where does this run?
Make sure you're running a diffing engine that checks for `.isSameNode()`, if
it doesn't you'll end up with super weird results because proxy nodes will
probably be rendered which is not what should happen. Probably make sure you're
using [morphdom][md] or [nanomorph][nm]. Seriously.
Instead we recommend people use an interface that somewhat resembles Node's
`require('events').EventEmitter` API.
### What's a proxy node?
It's a node that overloads `Node.isSameNode()` to compare it to another node.
This is needed because a given DOM node can only exist in one DOM tree at the
time, so we need a way to reference mounted nodes in the tree without actually
using them. Hence the proxy pattern, and the recently added support for it in
certain diffing engines:
```js
var MyComponent = require('./my-component')
var myComponent = MyComponent()
var html = require('bel')
myComponent.on('render', function () {
console.log('rendered')
})
var el1 = html`<div>pink is the best</div>`
var el2 = html`<div>blue is the best</div>`
myComponent.on('load', function () {
console.log('loaded on DOM')
})
// let's proxy el1
var proxy = html`<div></div>`
proxy.isSameNode = function (targetNode) {
return (targetNode === el1)
}
myComponent.on('unload', function () {
console.log('removed from DOM')
})
document.body.appendChild(myComponent.render())
el1.isSameNode(el1) // true
el1.isSameNode(el2) // false
proxy.isSameNode(el1) // true
proxy.isSameNode(el2) // false
```
This API allows consumers of the `MyComponent` to hook into the event system
without needing to inherit. It also allows `MyComponent` to expose more hooks
with little cost. See
[yoshuawuyts/microcomponent](https://github.com/yoshuawuyts/microcomponent) for
an example of how to create a higher level interface.
### How does it work?
[Morphdom][md] is a diffing engine that diffs real DOM trees. It runs a series
of checks between nodes to see if they should either be replaced, removed,
updated or reordered. This is done using a series of property checks on the
nodes.
Since [v2.1.0][210] `morphdom` also runs `Node.isSameNode(otherNode)`. This
allows us to override the function and replace it with a custom function that
proxies an existing node. Check out the code to see how it works. The result is
that if every element in our tree uses `nanocomponent`, only elements that have
changed will be recomputed and re-rendered making things very fast.
`nanomorph`, which saw first use in choo 5, has supported `isSameNode` since
its conception.
## API
### `Nanocomponent.prototype()`
Inheritable Nanocomponent prototype. Should be inherited from using
`Nanococomponent.call(this)` and `prototype =
Object.create(Nanocomponent.prototype)`.
### `component = Nanocomponent()`
Create a new Nanocomponent instance. Additional methods can be set on the
prototype.
Internal properties are:
### `component.render([…arguments])`
Render the component. Returns a proxy node if already mounted on the DOM. Proxy
nodes make it so DOM diffing algorithms leave the element alone when diffing.
- `this._placeholder`: placeholder element that's returned on subsequent
`render()` calls that don't pass the `._update()` check.
- `this._element`: rendered element that should be returned from the first
`._render()` call. Used to apply `._load()` and `._unload()` listeners on.
- `this._hasWindow`: boolean if `window` exists. Can be used to create
elements that render both in the browser and in Node.
- `this._loaded`: boolean if the element is currently loaded on the DOM.
- `this._onload`: reference to the [on-load][on-load] library.
- `this.props`: the current `props` passed to `render()`
- `this.oldProps`: the previous `props`
- `this.state`: any out of band state to be stored
### `component.element`
A [getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
property that returns the component's DOM node if its mounted in the page and
`null` when its not.
### `DOMNode|placeholder = Nanocomponent.prototype.render(props)`
Create an instance of the component. Calls `prototype._render()` if
`prototype._update()` returns `true`. As long as the element is mounted on the
DOM, subsequent calls to `.render()` will return a placeholder element with a
`.isSameNode()` method that compares arguments with the previously rendered
node. This is useful for diffing algorithms like
[nanomorph](https://github.com/yoshuawuyts/nanomorph) which use this method to
determine if a portion of the tree should be walked.
### `DOMNode = Nanocomponent.prototype._render([arguments…])`
__Must be implemented.__ Component specific render function. Optionally cache
argument values here. Run anything here that needs to run along side node
rendering. Must return a DOMNode. Use `_willRender` to run code after
`_render` when the component is unmounted.
### `Nanocomponent.prototype._render(props)`
__Must be implemented.__ Render an HTML node with arguments. For
`prototype._load()` and `prototype._unload()` to work, make sure you return the
same node on subsequent renders. The Node that's initially returned is saved as
`this._element`.
### `Boolean = Nanocomponent.prototype._update([arguments…])`
__Must be implemented.__ Return a boolean to determine if
`prototype._render()` should be called. The `_update` method is analogous to
React's `shouldComponentUpdate`. Called only when the component is mounted in
the DOM tree.
### `Nanocomponent.prototype._update(props)`
__Must be implemented.__ Return a boolean to determine if `prototype._render()`
should be called. Not called on the first render.
### `Nanocomponent.prototype._willRender(el)`
A function called right after `_render` returns with `el`, but before the fully rendered
element is returned to the `render` caller. Run any first render hooks here. The `_load` and
`_unload` hooks are added at this stage.
### `Nanocomponent.prototype._load()`
Called when the component is mounted on the DOM.
### `Nanocomponent.prototype._load(el)`
Called when the component is mounted on the DOM. Uses [on-load][onload] under
the hood.
### `Nanocomponent.prototype._unload()`
Called when the component is removed from the DOM.
### `Nanocomponent.prototype._unload(el)`
Called when the component is removed from the DOM. Uses [on-load][onload] under
the hood.
### `Nanocomponent.prototype._didUpdate(el)`
Called after a mounted component updates (e.g. `_update` returns true). You can use this hook to call
`element.scrollIntoView` or other dom methods on the mounted component.
## Installation

@@ -133,5 +320,4 @@ ```sh

## See Also
- [choojs/choo](https://github.com/choojs/choo)
- [shama/bel](https://github.com/shama/bel)
- [yoshuawuyts/nanomorph](https://github.com/yoshuawuyts/nanomorph)
- [yoshuawuyts/nanoraf](https://github.com/yoshuawuyts/nanoraf)
- [shama/on-load](https://github.com/shama/on-load)

@@ -142,4 +328,2 @@ - [yoshuawuyts/observe-resize](https://github.com/yoshuawuyts/observe-resize)

- [yoshuawuyts/on-idle](https://github.com/yoshuawuyts/on-idle)
- [yoshuawuyts/nanobounce](https://github.com/yoshuawuyts/nanobounce)
- [yoshuawuyts/nanoframe](https://github.com/yoshuawuyts/nanoframe)

@@ -158,6 +342,6 @@ ## Similar Packages

[3]: https://npmjs.org/package/nanocomponent
[4]: https://img.shields.io/travis/yoshuawuyts/nanocomponent/master.svg?style=flat-square
[5]: https://travis-ci.org/yoshuawuyts/nanocomponent
[6]: https://img.shields.io/codecov/c/github/yoshuawuyts/nanocomponent/master.svg?style=flat-square
[7]: https://codecov.io/github/yoshuawuyts/nanocomponent
[4]: https://img.shields.io/travis/choojs/nanocomponent/master.svg?style=flat-square
[5]: https://travis-ci.org/choojs/nanocomponent
[6]: https://img.shields.io/codecov/c/github/choojs/cache-component/master.svg?style=flat-square
[7]: https://codecov.io/github/choojs/nanocomponent
[8]: http://img.shields.io/npm/dm/nanocomponent.svg?style=flat-square

@@ -167,4 +351,10 @@ [9]: https://npmjs.org/package/nanocomponent

[11]: https://github.com/feross/standard
[adapt]: https://github.com/yoshuawuyts/nanocomponent-adapters/
[on-load]: https://github.com/shama/on-load
[bel]: https://github.com/shama/bel
[yoyoify]: https://github.com/shama/yo-yoify
[md]: https://github.com/patrick-steele-idem/morphdom
[210]: https://github.com/patrick-steele-idem/morphdom/pull/81
[nm]: https://github.com/yoshuawuyts/nanomorph
[ce]: https://github.com/yoshuawuyts/cache-element
[class]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
[isSameNode]: https://github.com/choojs/nanomorph#caching-dom-elements
[onload]: https://github.com/shama/on-load

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc