Socket
Socket
Sign inDemoInstall

@uppy/react

Package Overview
Dependencies
Maintainers
6
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uppy/react - npm Package Compare versions

Comparing version 3.1.2 to 3.1.3

7

CHANGELOG.md
# @uppy/react
## 3.1.3
Released: 2023-07-13
Included in: Uppy v3.12.0
- @uppy/react: allow `id` from props (Merlijn Vos / #4570)
## 3.1.0

@@ -4,0 +11,0 @@

12

lib/Dashboard.js

@@ -6,2 +6,3 @@ import { createElement as h, Component } from 'react';

import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js';
/**

@@ -16,3 +17,2 @@ * React Component that renders a Dashboard for an Uppy instance. This component

}
componentDidUpdate(prevProps) {

@@ -24,3 +24,4 @@ // eslint-disable-next-line react/destructuring-assignment

} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const options = { ...this.props,
const options = {
...this.props,
target: this.container

@@ -32,7 +33,5 @@ };

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -51,3 +50,2 @@ const {

}
uninstallPlugin(props) {

@@ -57,3 +55,2 @@ if (props === void 0) {

}
const {

@@ -64,3 +61,2 @@ uppy

}
render() {

@@ -75,5 +71,3 @@ return h('div', {

}
}
Dashboard.propTypes = basePropTypes;

@@ -80,0 +74,0 @@ Dashboard.defaultProps = {

@@ -7,2 +7,3 @@ import { createElement as h, Component } from 'react';

import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js';
/**

@@ -17,3 +18,2 @@ * React Component that renders a Dashboard for an Uppy instance in a Modal

}
componentDidUpdate(prevProps) {

@@ -25,3 +25,2 @@ const {

} = this.props;
if (prevProps.uppy !== uppy) {

@@ -31,3 +30,4 @@ this.uninstallPlugin(prevProps);

} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const options = { ...this.props,
const options = {
...this.props,
onRequestCloseModal: onRequestClose

@@ -38,3 +38,2 @@ };

}
if (prevProps.open && !open) {

@@ -46,9 +45,8 @@ this.plugin.closeModal();

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {
const {
id = 'react:DashboardModal',
uppy,

@@ -93,6 +91,5 @@ target,

locale // eslint-disable-line no-shadow
} = this.props;
const options = {
id: 'react:DashboardModal',
id,
target,

@@ -134,11 +131,8 @@ closeModalOnClickOutside,

};
if (!options.target) {
options.target = this.container;
}
delete options.uppy;
uppy.use(DashboardPlugin, options);
this.plugin = uppy.getPlugin(options.id);
if (open) {

@@ -148,3 +142,2 @@ this.plugin.openModal();

}
uninstallPlugin(props) {

@@ -154,3 +147,2 @@ if (props === void 0) {

}
const {

@@ -161,3 +153,2 @@ uppy

}
render() {

@@ -172,5 +163,3 @@ return h('div', {

}
}
DashboardModal.propTypes = {

@@ -215,4 +204,4 @@ uppy: uppyPropType.isRequired,

locale
}; // Must be kept in sync with @uppy/dashboard/src/Dashboard.jsx.
};
// Must be kept in sync with @uppy/dashboard/src/Dashboard.jsx.
DashboardModal.defaultProps = {

@@ -219,0 +208,0 @@ metaFields: [],

@@ -7,2 +7,3 @@ import { createElement as h, Component } from 'react';

import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js';
/**

@@ -17,3 +18,2 @@ * React component that renders an area in which files can be dropped to be

}
componentDidUpdate(prevProps) {

@@ -25,3 +25,4 @@ // eslint-disable-next-line react/destructuring-assignment

} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const options = { ...this.props,
const options = {
...this.props,
target: this.container

@@ -33,7 +34,5 @@ };

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -61,3 +60,2 @@ const {

}
uninstallPlugin(props) {

@@ -67,3 +65,2 @@ if (props === void 0) {

}
const {

@@ -74,3 +71,2 @@ uppy

}
render() {

@@ -85,5 +81,3 @@ return h('div', {

}
}
DragDrop.propTypes = {

@@ -96,4 +90,4 @@ uppy: propTypes.uppy.isRequired,

note: PropTypes.string
}; // Must be kept in sync with @uppy/drag-drop/src/DragDrop.jsx.
};
// Must be kept in sync with @uppy/drag-drop/src/DragDrop.jsx.
DragDrop.defaultProps = {

@@ -100,0 +94,0 @@ locale: null,

@@ -5,2 +5,3 @@ import { createElement as h, Component } from 'react';

import * as propTypes from './propTypes.js';
/**

@@ -15,3 +16,2 @@ * React component that renders an area in which files can be dropped to be

}
componentDidUpdate(prevProps) {

@@ -24,7 +24,5 @@ // eslint-disable-next-line react/destructuring-assignment

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -48,3 +46,2 @@ const {

}
uninstallPlugin(props) {

@@ -54,3 +51,2 @@ if (props === void 0) {

}
const {

@@ -61,3 +57,2 @@ uppy

}
render() {

@@ -71,5 +66,3 @@ return h('div', {

}
}
FileInput.propTypes = {

@@ -80,4 +73,4 @@ uppy: propTypes.uppy.isRequired,

inputName: PropTypes.string
}; // Must be kept in sync with @uppy/file-input/src/FileInput.jsx
};
// Must be kept in sync with @uppy/file-input/src/FileInput.jsx
FileInput.defaultProps = {

@@ -84,0 +77,0 @@ locale: undefined,

// List taken from React.HTMLAttributes supported properties:
// https://unpkg.com/@types/react@17.0.22/index.d.ts:1821
const reactSupportedHtmlAttr = [// React-specific Attributes
'defaultChecked', 'defaultValue', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'dangerouslySetInnerHTML', // Standard HTML Attributes
'accessKey', 'className', 'contentEditable', 'contextMenu', 'dir', 'draggable', 'hidden', 'id', 'lang', 'placeholder', 'slot', 'spellCheck', 'style', 'tabIndex', 'title', 'translate', // Unknown
'radioGroup', // WAI-ARIA
'role', // RDFa Attributes
'about', 'datatype', 'inlist', 'prefix', 'property', 'resource', 'typeof', 'vocab', // Non-standard Attributes
'autoCapitalize', 'autoCorrect', 'autoSave', 'color', 'itemProp', 'itemScope', 'itemType', 'itemID', 'itemRef', 'results', 'security', 'unselectable', // Living Standard
'inputMode', 'is', // Clipboard Events
'onCopy', 'onCopyCapture', 'onCut', 'onCutCapture', 'onPaste', 'onPasteCapture', // Composition Events
'onCompositionEnd', 'onCompositionEndCapture', 'onCompositionStart', 'onCompositionStartCapture', 'onCompositionUpdate', 'onCompositionUpdateCapture', // Focus Events
'onFocus', 'onFocusCapture', 'onBlur', 'onBlurCapture', // Form Events
'onChange', 'onChangeCapture', 'onBeforeInput', 'onBeforeInputCapture', 'onInput', 'onInputCapture', 'onReset', 'onResetCapture', 'onSubmit', 'onSubmitCapture', 'onInvalid', 'onInvalidCapture', // Image Events
'onLoad', 'onLoadCapture', 'onError', // also a Media Event
'onErrorCapture', // also a Media Event
const reactSupportedHtmlAttr = [
// React-specific Attributes
'defaultChecked', 'defaultValue', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'dangerouslySetInnerHTML',
// Standard HTML Attributes
'accessKey', 'className', 'contentEditable', 'contextMenu', 'dir', 'draggable', 'hidden', 'id', 'lang', 'placeholder', 'slot', 'spellCheck', 'style', 'tabIndex', 'title', 'translate',
// Unknown
'radioGroup',
// WAI-ARIA
'role',
// RDFa Attributes
'about', 'datatype', 'inlist', 'prefix', 'property', 'resource', 'typeof', 'vocab',
// Non-standard Attributes
'autoCapitalize', 'autoCorrect', 'autoSave', 'color', 'itemProp', 'itemScope', 'itemType', 'itemID', 'itemRef', 'results', 'security', 'unselectable',
// Living Standard
'inputMode', 'is',
// Clipboard Events
'onCopy', 'onCopyCapture', 'onCut', 'onCutCapture', 'onPaste', 'onPasteCapture',
// Composition Events
'onCompositionEnd', 'onCompositionEndCapture', 'onCompositionStart', 'onCompositionStartCapture', 'onCompositionUpdate', 'onCompositionUpdateCapture',
// Focus Events
'onFocus', 'onFocusCapture', 'onBlur', 'onBlurCapture',
// Form Events
'onChange', 'onChangeCapture', 'onBeforeInput', 'onBeforeInputCapture', 'onInput', 'onInputCapture', 'onReset', 'onResetCapture', 'onSubmit', 'onSubmitCapture', 'onInvalid', 'onInvalidCapture',
// Image Events
'onLoad', 'onLoadCapture', 'onError',
// also a Media Event
'onErrorCapture',
// also a Media Event
// Keyboard Events
'onKeyDown', 'onKeyDownCapture', 'onKeyPress', 'onKeyPressCapture', 'onKeyUp', 'onKeyUpCapture', // Media Events
'onAbort', 'onAbortCapture', 'onCanPlay', 'onCanPlayCapture', 'onCanPlayThrough', 'onCanPlayThroughCapture', 'onDurationChange', 'onDurationChangeCapture', 'onEmptied', 'onEmptiedCapture', 'onEncrypted', 'onEncryptedCapture', 'onEnded', 'onEndedCapture', 'onLoadedData', 'onLoadedDataCapture', 'onLoadedMetadata', 'onLoadedMetadataCapture', 'onLoadStart', 'onLoadStartCapture', 'onPause', 'onPauseCapture', 'onPlay', 'onPlayCapture', 'onPlaying', 'onPlayingCapture', 'onProgress', 'onProgressCapture', 'onRateChange', 'onRateChangeCapture', 'onSeeked', 'onSeekedCapture', 'onSeeking', 'onSeekingCapture', 'onStalled', 'onStalledCapture', 'onSuspend', 'onSuspendCapture', 'onTimeUpdate', 'onTimeUpdateCapture', 'onVolumeChange', 'onVolumeChangeCapture', 'onWaiting', 'onWaitingCapture', // MouseEvents
'onAuxClick', 'onAuxClickCapture', 'onClick', 'onClickCapture', 'onContextMenu', 'onContextMenuCapture', 'onDoubleClick', 'onDoubleClickCapture', 'onDrag', 'onDragCapture', 'onDragEnd', 'onDragEndCapture', 'onDragEnter', 'onDragEnterCapture', 'onDragExit', 'onDragExitCapture', 'onDragLeave', 'onDragLeaveCapture', 'onDragOver', 'onDragOverCapture', 'onDragStart', 'onDragStartCapture', 'onDrop', 'onDropCapture', 'onMouseDown', 'onMouseDownCapture', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseMoveCapture', 'onMouseOut', 'onMouseOutCapture', 'onMouseOver', 'onMouseOverCapture', 'onMouseUp', 'onMouseUpCapture', // Selection Events
'onSelect', 'onSelectCapture', // Touch Events
'onTouchCancel', 'onTouchCancelCapture', 'onTouchEnd', 'onTouchEndCapture', 'onTouchMove', 'onTouchMoveCapture', 'onTouchStart', 'onTouchStartCapture', // Pointer Events
'onPointerDown', 'onPointerDownCapture', 'onPointerMove', 'onPointerMoveCapture', 'onPointerUp', 'onPointerUpCapture', 'onPointerCancel', 'onPointerCancelCapture', 'onPointerEnter', 'onPointerEnterCapture', 'onPointerLeave', 'onPointerLeaveCapture', 'onPointerOver', 'onPointerOverCapture', 'onPointerOut', 'onPointerOutCapture', 'onGotPointerCapture', 'onGotPointerCaptureCapture', 'onLostPointerCapture', 'onLostPointerCaptureCapture', // UI Events
'onScroll', 'onScrollCapture', // Wheel Events
'onWheel', 'onWheelCapture', // Animation Events
'onAnimationStart', 'onAnimationStartCapture', 'onAnimationEnd', 'onAnimationEndCapture', 'onAnimationIteration', 'onAnimationIterationCapture', // Transition Events
'onKeyDown', 'onKeyDownCapture', 'onKeyPress', 'onKeyPressCapture', 'onKeyUp', 'onKeyUpCapture',
// Media Events
'onAbort', 'onAbortCapture', 'onCanPlay', 'onCanPlayCapture', 'onCanPlayThrough', 'onCanPlayThroughCapture', 'onDurationChange', 'onDurationChangeCapture', 'onEmptied', 'onEmptiedCapture', 'onEncrypted', 'onEncryptedCapture', 'onEnded', 'onEndedCapture', 'onLoadedData', 'onLoadedDataCapture', 'onLoadedMetadata', 'onLoadedMetadataCapture', 'onLoadStart', 'onLoadStartCapture', 'onPause', 'onPauseCapture', 'onPlay', 'onPlayCapture', 'onPlaying', 'onPlayingCapture', 'onProgress', 'onProgressCapture', 'onRateChange', 'onRateChangeCapture', 'onSeeked', 'onSeekedCapture', 'onSeeking', 'onSeekingCapture', 'onStalled', 'onStalledCapture', 'onSuspend', 'onSuspendCapture', 'onTimeUpdate', 'onTimeUpdateCapture', 'onVolumeChange', 'onVolumeChangeCapture', 'onWaiting', 'onWaitingCapture',
// MouseEvents
'onAuxClick', 'onAuxClickCapture', 'onClick', 'onClickCapture', 'onContextMenu', 'onContextMenuCapture', 'onDoubleClick', 'onDoubleClickCapture', 'onDrag', 'onDragCapture', 'onDragEnd', 'onDragEndCapture', 'onDragEnter', 'onDragEnterCapture', 'onDragExit', 'onDragExitCapture', 'onDragLeave', 'onDragLeaveCapture', 'onDragOver', 'onDragOverCapture', 'onDragStart', 'onDragStartCapture', 'onDrop', 'onDropCapture', 'onMouseDown', 'onMouseDownCapture', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseMoveCapture', 'onMouseOut', 'onMouseOutCapture', 'onMouseOver', 'onMouseOverCapture', 'onMouseUp', 'onMouseUpCapture',
// Selection Events
'onSelect', 'onSelectCapture',
// Touch Events
'onTouchCancel', 'onTouchCancelCapture', 'onTouchEnd', 'onTouchEndCapture', 'onTouchMove', 'onTouchMoveCapture', 'onTouchStart', 'onTouchStartCapture',
// Pointer Events
'onPointerDown', 'onPointerDownCapture', 'onPointerMove', 'onPointerMoveCapture', 'onPointerUp', 'onPointerUpCapture', 'onPointerCancel', 'onPointerCancelCapture', 'onPointerEnter', 'onPointerEnterCapture', 'onPointerLeave', 'onPointerLeaveCapture', 'onPointerOver', 'onPointerOverCapture', 'onPointerOut', 'onPointerOutCapture', 'onGotPointerCapture', 'onGotPointerCaptureCapture', 'onLostPointerCapture', 'onLostPointerCaptureCapture',
// UI Events
'onScroll', 'onScrollCapture',
// Wheel Events
'onWheel', 'onWheelCapture',
// Animation Events
'onAnimationStart', 'onAnimationStartCapture', 'onAnimationEnd', 'onAnimationEndCapture', 'onAnimationIteration', 'onAnimationIterationCapture',
// Transition Events
'onTransitionEnd', 'onTransitionEndCapture'];
const validHTMLAttribute = /^(aria-|data-)/;
const getHTMLProps = props => {

@@ -37,3 +60,2 @@ // Gets all the React props

};
export default getHTMLProps;

@@ -7,2 +7,3 @@ import { createElement as h, Component } from 'react';

import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js';
/**

@@ -16,3 +17,2 @@ * React component that renders a progress bar at the top of the page.

}
componentDidUpdate(prevProps) {

@@ -24,3 +24,4 @@ // eslint-disable-next-line react/destructuring-assignment

} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const options = { ...this.props,
const options = {
...this.props,
target: this.container

@@ -32,7 +33,5 @@ };

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -54,3 +53,2 @@ const {

}
uninstallPlugin(props) {

@@ -60,3 +58,2 @@ if (props === void 0) {

}
const {

@@ -67,3 +64,2 @@ uppy

}
render() {

@@ -78,5 +74,3 @@ return h('div', {

}
}
ProgressBar.propTypes = {

@@ -86,4 +80,4 @@ uppy: uppyPropType.isRequired,

hideAfterFinish: PropTypes.bool
}; // Must be kept in sync with @uppy/progress-bar/src/ProgressBar.jsx
};
// Must be kept in sync with @uppy/progress-bar/src/ProgressBar.jsx
ProgressBar.defaultProps = {

@@ -90,0 +84,0 @@ fixed: false,

import PropTypes from 'prop-types';
import { Uppy as UppyCore } from '@uppy/core'; // The `uppy` prop receives the Uppy core instance.
import { Uppy as UppyCore } from '@uppy/core';
const uppy = PropTypes.instanceOf(UppyCore); // A list of plugins to mount inside this component.
// The `uppy` prop receives the Uppy core instance.
const uppy = PropTypes.instanceOf(UppyCore);
const plugins = PropTypes.arrayOf(PropTypes.string); // Language strings for this component.
// A list of plugins to mount inside this component.
const plugins = PropTypes.arrayOf(PropTypes.string);
// Language strings for this component.
const locale = PropTypes.shape({

@@ -12,4 +15,5 @@ strings: PropTypes.object,

pluralize: PropTypes.func
}); // List of meta fields for the editor in the Dashboard.
});
// List of meta fields for the editor in the Dashboard.
const metaField = PropTypes.shape({

@@ -20,6 +24,8 @@ id: PropTypes.string.isRequired,

});
const metaFields = PropTypes.oneOfType([PropTypes.arrayOf(metaField), PropTypes.func]); // A size in pixels (number) or with some other unit (string).
const metaFields = PropTypes.oneOfType([PropTypes.arrayOf(metaField), PropTypes.func]);
const cssSize = PropTypes.oneOfType([PropTypes.string, PropTypes.number]); // Common props for dashboardy components (Dashboard and DashboardModal).
// A size in pixels (number) or with some other unit (string).
const cssSize = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
// Common props for dashboardy components (Dashboard and DashboardModal).
const dashboard = {

@@ -26,0 +32,0 @@ uppy,

@@ -7,2 +7,3 @@ import { createElement as h, Component } from 'react';

import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js';
/**

@@ -17,3 +18,2 @@ * React component that renders a status bar containing upload progress and speed,

}
componentDidUpdate(prevProps) {

@@ -25,3 +25,4 @@ // eslint-disable-next-line react/destructuring-assignment

} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const options = { ...this.props,
const options = {
...this.props,
target: this.container

@@ -33,7 +34,5 @@ };

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -65,3 +64,2 @@ const {

}
uninstallPlugin(props) {

@@ -71,3 +69,2 @@ if (props === void 0) {

}
const {

@@ -78,3 +75,2 @@ uppy

}
render() {

@@ -89,5 +85,3 @@ return h('div', {

}
}
StatusBar.propTypes = {

@@ -102,4 +96,4 @@ uppy: uppyPropType.isRequired,

doneButtonHandler: PropTypes.func
}; // Must be kept in sync with @uppy/status-bar/src/StatusBar.jsx.
};
// Must be kept in sync with @uppy/status-bar/src/StatusBar.jsx.
StatusBar.defaultProps = {

@@ -106,0 +100,0 @@ hideUploadButton: false,

import { useEffect, useRef } from 'react';
import { Uppy as UppyCore } from '@uppy/core';
/**
* @deprecated Initialize Uppy outside of the component.
*/
export default function useUppy(factory) {

@@ -11,8 +11,5 @@ if (typeof factory !== 'function') {

}
const uppy = useRef(undefined);
if (uppy.current === undefined) {
uppy.current = factory();
if (!(uppy.current instanceof UppyCore)) {

@@ -22,7 +19,5 @@ throw new TypeError(`useUppy: factory function must return an Uppy instance, got ${typeof uppy.current}`);

}
useEffect(() => {
return () => {
var _uppy$current;
(_uppy$current = uppy.current) == null ? void 0 : _uppy$current.close({

@@ -29,0 +24,0 @@ reason: 'unmount'

import { createElement as h, Component } from 'react';
import PropTypes from 'prop-types';
import { uppy as uppyPropType } from './propTypes.js';
class UppyWrapper extends Component {

@@ -10,7 +9,5 @@ constructor(props) {

}
componentDidMount() {
this.installPlugin();
}
componentDidUpdate(prevProps) {

@@ -20,3 +17,2 @@ const {

} = this.props;
if (prevProps.uppy !== uppy) {

@@ -27,7 +23,5 @@ this.uninstallPlugin(prevProps);

}
componentWillUnmount() {
this.uninstallPlugin();
}
installPlugin() {

@@ -41,3 +35,2 @@ const {

}
uninstallPlugin(_temp) {

@@ -52,7 +45,5 @@ let {

}
refContainer(container) {
this.container = container;
}
render() {

@@ -64,5 +55,3 @@ return h('div', {

}
}
UppyWrapper.propTypes = {

@@ -69,0 +58,0 @@ uppy: uppyPropType.isRequired,

{
"name": "@uppy/react",
"description": "React component wrappers around Uppy's official UI plugins.",
"version": "3.1.2",
"version": "3.1.3",
"license": "MIT",

@@ -25,3 +25,3 @@ "main": "lib/index.js",

"dependencies": {
"@uppy/utils": "^5.3.0",
"@uppy/utils": "^5.4.1",
"prop-types": "^15.6.1"

@@ -34,8 +34,8 @@ },

"peerDependencies": {
"@uppy/core": "^3.2.0",
"@uppy/dashboard": "^3.4.0",
"@uppy/core": "^3.3.1",
"@uppy/dashboard": "^3.4.2",
"@uppy/drag-drop": "^3.0.2",
"@uppy/file-input": "^3.0.2",
"@uppy/progress-bar": "^3.0.2",
"@uppy/status-bar": "^3.1.1",
"@uppy/status-bar": "^3.2.2",
"react": "^16.0.0 || ^17.0.0 || ^18.0.0"

@@ -42,0 +42,0 @@ },

@@ -41,2 +41,3 @@ import { createElement as h, Component } from 'react'

const {
id = 'react:DashboardModal',
uppy,

@@ -81,3 +82,3 @@ target,

const options = {
id: 'react:DashboardModal',
id,
target,

@@ -84,0 +85,0 @@ closeModalOnClickOutside,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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