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

data-transfer-object

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

data-transfer-object - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

changelog.md

26

lib/cjs/data-transfer-object.d.ts
import { ValidationError, ValidatorOptions } from 'class-validator';
export * from 'class-validator';
declare type NonFunctionPropertyNames<T> = {

@@ -33,13 +32,29 @@ [K in keyof T]: T[K] extends Function ? never : K;

* Runs all synchronous validators on this object.
* To run asynchronous validators as well, use `.validateAsync()`.
* To run asynchronous validators as well, use `.getValidationErrorsAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): ValidationError[];
getValidationErrors(opts?: ValidatorOptions): ValidationError[];
/**
* Runs all synchronous and asynchronous validators on this object.
* Always returns a promise. To validate synchronously, use `.validate()`.
* Always returns a promise. To validate synchronously, use `.getValidationErrors()`.
* @param opts Options to pass to the validator system.
*/
validateAsync(opts?: ValidatorOptions): Promise<ValidationError[]>;
getValidationErrorsAsync(opts?: ValidatorOptions): Promise<ValidationError[]>;
/**
* Validates this object (sync validators only), and returns its plain data if validations pass.
* Otherwise, throws an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To run both sync and async validators, use `.validateAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): Data<this>;
/**
* Validates this object asynchronously, and resolves to its plain data if validations pass.
* Otherwise, rejects with an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To validate synchronously, use `.validate()`.
* @param opts Options to pass to the validator system.
*/
validateAsync(opts?: ValidatorOptions): Promise<Data<this>>;
/**
* Returns a JSON friendly object containing only data properties of this object (ie, no validation functions).

@@ -50,1 +65,2 @@ * Automatically used by `JSON.stringify()`.

}
export {};

60

lib/cjs/data-transfer-object.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var _a, _b;

@@ -16,5 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });

const class_validator_1 = require("class-validator");
__exportStar(require("class-validator"), exports);
const validation_exception_1 = require("./validation-exception");
const validation_error_handler_1 = require("./validation-error-handler");
// Strict options by default
const defaultOpts = {
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
};

@@ -29,2 +23,14 @@ // Must use symbols for private properties so that they are not included in validation

/**
* Checks the input error list, and if non-empty, throws an error.
* @param errors The error list to check against.
*/
function assertEmptyErrorList(errors) {
if (errors.length) {
if (!validation_error_handler_1.onValidationError)
throw new validation_exception_1.ValidationException(errors);
validation_error_handler_1.onValidationError(errors);
throw new validation_exception_1.ValidationException(errors);
}
}
/**
* Creates a new data transfer object which will validate and reshape its input

@@ -48,6 +54,6 @@ * data based on the validators of its own properties. Must be extended, should

* Runs all synchronous validators on this object.
* To run asynchronous validators as well, use `.validateAsync()`.
* To run asynchronous validators as well, use `.getValidationErrorsAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts) {
getValidationErrors(opts) {
if (this[validated])

@@ -61,6 +67,6 @@ return this[validationErrors];

* Runs all synchronous and asynchronous validators on this object.
* Always returns a promise. To validate synchronously, use `.validate()`.
* Always returns a promise. To validate synchronously, use `.getValidationErrors()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts) {
async getValidationErrorsAsync(opts) {
if (this[validated])

@@ -81,2 +87,26 @@ return this[validationErrors];

/**
* Validates this object (sync validators only), and returns its plain data if validations pass.
* Otherwise, throws an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To run both sync and async validators, use `.validateAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts) {
const errors = this.getValidationErrors(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Validates this object asynchronously, and resolves to its plain data if validations pass.
* Otherwise, rejects with an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To validate synchronously, use `.validate()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts) {
const errors = await this.getValidationErrorsAsync(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Returns a JSON friendly object containing only data properties of this object (ie, no validation functions).

@@ -83,0 +113,0 @@ * Automatically used by `JSON.stringify()`.

export * from './data-transfer-object';
export * from './validation-error-handler';
export * from './validation-error-map';
export * from './validation-exception';
export * from 'class-validator';

@@ -14,1 +14,5 @@ "use strict";

__exportStar(require("./data-transfer-object"), exports);
__exportStar(require("./validation-error-handler"), exports);
__exportStar(require("./validation-error-map"), exports);
__exportStar(require("./validation-exception"), exports);
__exportStar(require("class-validator"), exports);
import { ValidationError, ValidatorOptions } from 'class-validator';
export * from 'class-validator';
declare type NonFunctionPropertyNames<T> = {

@@ -33,13 +32,29 @@ [K in keyof T]: T[K] extends Function ? never : K;

* Runs all synchronous validators on this object.
* To run asynchronous validators as well, use `.validateAsync()`.
* To run asynchronous validators as well, use `.getValidationErrorsAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): ValidationError[];
getValidationErrors(opts?: ValidatorOptions): ValidationError[];
/**
* Runs all synchronous and asynchronous validators on this object.
* Always returns a promise. To validate synchronously, use `.validate()`.
* Always returns a promise. To validate synchronously, use `.getValidationErrors()`.
* @param opts Options to pass to the validator system.
*/
validateAsync(opts?: ValidatorOptions): Promise<ValidationError[]>;
getValidationErrorsAsync(opts?: ValidatorOptions): Promise<ValidationError[]>;
/**
* Validates this object (sync validators only), and returns its plain data if validations pass.
* Otherwise, throws an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To run both sync and async validators, use `.validateAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): Data<this>;
/**
* Validates this object asynchronously, and resolves to its plain data if validations pass.
* Otherwise, rejects with an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To validate synchronously, use `.validate()`.
* @param opts Options to pass to the validator system.
*/
validateAsync(opts?: ValidatorOptions): Promise<Data<this>>;
/**
* Returns a JSON friendly object containing only data properties of this object (ie, no validation functions).

@@ -50,1 +65,2 @@ * Automatically used by `JSON.stringify()`.

}
export {};
var _a, _b;
import { validate, validateSync } from 'class-validator';
export * from 'class-validator';
import { ValidationException } from './validation-exception';
import { onValidationError } from './validation-error-handler';
// Strict options by default
const defaultOpts = {
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
};

@@ -15,2 +19,14 @@ // Must use symbols for private properties so that they are not included in validation

/**
* Checks the input error list, and if non-empty, throws an error.
* @param errors The error list to check against.
*/
function assertEmptyErrorList(errors) {
if (errors.length) {
if (!onValidationError)
throw new ValidationException(errors);
onValidationError(errors);
throw new ValidationException(errors);
}
}
/**
* Creates a new data transfer object which will validate and reshape its input

@@ -34,6 +50,6 @@ * data based on the validators of its own properties. Must be extended, should

* Runs all synchronous validators on this object.
* To run asynchronous validators as well, use `.validateAsync()`.
* To run asynchronous validators as well, use `.getValidationErrorsAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts) {
getValidationErrors(opts) {
if (this[validated])

@@ -47,6 +63,6 @@ return this[validationErrors];

* Runs all synchronous and asynchronous validators on this object.
* Always returns a promise. To validate synchronously, use `.validate()`.
* Always returns a promise. To validate synchronously, use `.getValidationErrors()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts) {
async getValidationErrorsAsync(opts) {
if (this[validated])

@@ -67,2 +83,26 @@ return this[validationErrors];

/**
* Validates this object (sync validators only), and returns its plain data if validations pass.
* Otherwise, throws an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To run both sync and async validators, use `.validateAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts) {
const errors = this.getValidationErrors(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Validates this object asynchronously, and resolves to its plain data if validations pass.
* Otherwise, rejects with an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To validate synchronously, use `.validate()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts) {
const errors = await this.getValidationErrorsAsync(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Returns a JSON friendly object containing only data properties of this object (ie, no validation functions).

@@ -69,0 +109,0 @@ * Automatically used by `JSON.stringify()`.

export * from './data-transfer-object';
export * from './validation-error-handler';
export * from './validation-error-map';
export * from './validation-exception';
export * from 'class-validator';
export * from './data-transfer-object';
export * from './validation-error-handler';
export * from './validation-error-map';
export * from './validation-exception';
export * from 'class-validator';
{
"name": "data-transfer-object",
"version": "0.3.0",
"version": "0.4.0",
"description": "Data Transfer Object class built on `class-validator`.",

@@ -39,3 +39,4 @@ "keywords": [

"docs:readme": "doctoc --title \"**Table of contents**\" readme.md",
"docs:api": "typedoc src/index.ts"
"docs:api": "typedoc src/index.ts",
"changelog": "standard-changelog"
},

@@ -56,2 +57,3 @@ "dependencies": {

"rimraf": "^3.0.2",
"standard-changelog": "^2.0.27",
"ts-jest": "^26.4.4",

@@ -58,0 +60,0 @@ "ts-node": "^9.1.1",

# data-transfer-object
Data Transfer Object class built on [TypeStacks's `class-validator`](https://github.com/typestack/class-validator). Allows you to build a DTO class that automatically validates input from outside sources and ensures its shape is correct.
Data Transfer Object class built on [TypeStacks's `class-validator`](https://github.com/typestack/class-validator). Allows you to build a class that validates input from outside sources and ensures its shape is correct. Full TypeScript support with strict, strong typing.

@@ -12,7 +12,11 @@ <!-- START doctoc generated TOC please keep comment here to allow auto update -->

- [For browsers (script tag)](#for-browsers-script-tag)
- [Release notes](#release-notes)
- [Usage](#usage)
- [TypeScript notes](#typescript-notes)
- [Documentation](#documentation)
- [Example](#example)
- [Development](#development)
- [Throwing a custom error on validation failure](#throwing-a-custom-error-on-validation-failure)
- [Accessing raw error data in custom error handler](#accessing-raw-error-data-in-custom-error-handler)
- [Get validation errors without throwing an error](#get-validation-errors-without-throwing-an-error)
- [Run async validators](#run-async-validators)
- [Full API Documentation](#full-api-documentation)
- [Comprehensive example](#comprehensive-example)
- [Development and contributions](#development-and-contributions)
- [License](#license)

@@ -34,7 +38,11 @@

UMD builds aren't available yet. Rollup builds are planned for the future.
Browser builds aren't available yet, but they are planned for the future.
## Release notes
See information about breaking changes and release notes [here](changelog.md).
## Usage
Create a DTO class by importing `DataTransferObject`, extending it with your custom properties, and using the appropriate decorators. This package re-exports all decorators and functions from [TypeStack's `class-validator`](https://github.com/typestack/class-validator).
Create your own classes by importing and extending `DataTransferObject` with your own properties, and using the appropriate validator decorators. This package re-exports all decorators and functions from [TypeStack's `class-validator`](https://github.com/typestack/class-validator).

@@ -51,23 +59,94 @@ ```typescript

Once your class is defined, you can instantiate it, pass your input into it, and validate it:
**TypeScript note:** when using TypeScript with `"strict": true`, you must use non-null assertions (`!:`) when declaring class properties. Also, `experimentalDecorators` and `emitDecoratorMetadata` must be set to `true` in your `tsconfig.json`.
Once your class is defined, you can construct a new instance of it, pass your input into it, and run `.validate()` on it. If your input is valid, it will return a plain object with the validated data. Otherwise, by default, a `ValidationException` will be thrown.
```typescript
const input = new MyDto({ myString: 12 });
const errors = input.validate();
// `errors` will be an array of `ValidationError` objects.
console.log(errors);
try {
const validated = new MyDto(input).validate();
console.log(validated);
// validated === input
} catch (err) {
if (err instanceof ValidationException) {
console.error(err.validationErrors);
// e.g. if `input` was `{ myString: 1234 }`, this would output:
{ "myString": ["property myString should be a string"] }
}
}
```
// outputs:
[
{
target: { myString: 12 },
value: 12,
property: 'myString',
children: [],
constraints: { isString: 'myString must be a string' },
### Throwing a custom error on validation failure
You can use `setValidationErrorHandler()` to register a callback to run whenever a `.validate()` call fails on any object across your project. For instance:
```typescript
import { setValidationErrorHandler, ValidationErrorMap } from 'data-transfer-object';
class CustomError extends Error {
statusCode = 400;
errors: ValidationErrorMap;
constructor(errors: ValidationErrorMap) {
super('Failed to validate');
this.errors = errors;
}
}
setValidationErrorHandler(errors => {
throw new CustomError(errors);
});
try {
new MyExampleDto({ invalidData: 42 }).validate();
} catch (err) {
if (err instanceof CustomError) {
console.error(`Request failed with error code ${err.statusCode}`);
console.error(err.errors);
}
}
```
#### Accessing raw error data in custom error handler
Under the hood, `data-transfer-object` formats the raw array of `ValidationError` returned by `class-validator` into an object mapping keys to properties and values to validation messages (aka a `ValidationErrorMap`).
If you wish to get direct access to the array of `ValidationError` in your error handler, you may pass in `{ rawErrors: true }` as a second parameter to `.setValidationErrorHandler()`:
```typescript
import { setValidationErrorHandler } from 'data-transfer-object';
setValidationErrorHandler(
errors => {
// `errors` here is now of type `ValidationError[]`.
console.error(errors);
// example output:
[
{
target: { myString: 12 },
value: 12,
property: 'myString',
children: [],
constraints: { isString: 'myString must be a string' },
},
];
},
];
{ rawErrors: true },
);
```
### Get validation errors without throwing an error
You may use `.getValidationErrors()` to get an array of `ValidationError` without having to thrown an actual error. To get the plain data later, use `.toJSON()`.
```typescript
const dto = new MyDto({ someData: 'data' });
const errors = dto.getValidationErrors();
if (errors.length) {
console.error(errors);
return;
}
const data = dto.toJSON();
```
Validating it will also silently drop all unknown properties from the input:

@@ -85,16 +164,24 @@

### TypeScript notes
### Run async validators
Note that when using TypeScript with `"strict": true`, you must use non-null assertions (`!:`) when declaring class properties. Also, `experimentalDecorators` and `emitDecoratorMetadata` must be set to `true` in your `tsconfig.json`.
`.validate()` and `.getValidationErrors()` will only run synchronous validators, which covers most use cases in a web application. If you would like to run asynchronous validators as well, use `.validateAsync()` and `.getValidationErrorsAsync()` respectively. These counterparts will always return a promise, even if there are no async validators on the validated object.
## Documentation
## Full API Documentation
The most up-to-date documentation for all exported items from this package is automatically generated from code and available at https://danielegarciav.github.io/data-transfer-object/.
## Example
You may wish to uncheck the "Externals" checkbox option (top-right on desktop, cog icon on mobile) in order to hide documentation from `class-validator` and focus only on what this package exports.
In the following example, we have an Express application that lets us sign up users. In order to validate input from the web app client, we create a data transfer object representing the input data, and attach our desired validators:
## Comprehensive example
In the following example, we have an Express application that lets us sign up users.
- We define an `UserSignupInput` data transfer object class.
- We define our own custom errors `ApiError` and `ApiValidationError`, which allow us to define a status code, among other things.
- We define an [Express error handler](https://expressjs.com/en/guide/error-handling.html) to catch any errors and format the result that will be sent back to our client.
- We wire everything up as an Express app, and make it so validation errors throw an `ApiValidationError`, which will be then appropriately handled by our Express error handler.
- We can then write our signup controller.
```typescript
// input-dtos.ts
// input-classes.ts

@@ -118,46 +205,96 @@ import { DataTransferObject, IsString, Length, MinLength } from 'data-transfer-object';

The Express request handler in our example:
```typescript
// custom-errors.ts
import { ValidationErrorMap } from 'data-transfer-object';
export class ApiError extends Error {
type: string;
statusCode: number;
constructor(type: ApiErrorType, statusCode?: number, message?: string) {
super(message);
this.name = 'ApiError';
this.type = type;
this.message = message ?? 'Unspecified error';
this.statusCode = statusCode ?? 500;
}
}
export class ApiValidationError extends ApiError {
validationMessages: ValidationErrorMap;
constructor(errors: ValidationErrorMap) {
super('InvalidRequest', 400, 'Request is invalid');
this.validationMessages = errors;
}
}
```
```typescript
// signup-controller.ts
// error-handler.ts
import { Request, Response } from 'express';
import { User } from './models';
import { UserSignupInput } from './input-dtos';
import { Request, Response, NextFunction } from 'express';
import { ApiError } from './custom-errors';
export async function signup(req: Request, res: Response): {
// Construct a new DTO instance passing starting state as argument.
const input = new UserSignupInput(req.body);
export function expressErrorHandler(
error: Error | ApiError,
req: Request,
res: Response,
next: NextFunction,
) {
const statusCode = error instanceof ApiError ? error.statusCode : 500;
const jsonResponse = { error: { ...error, statusCode } };
// Run validation. Only synchronous validators are run by default, which covers most use cases.
const errors = input.validate();
// Log non-ApiErrors to console
if (!(error instanceof ApiError)) console.error(error);
// You may also use `.validateAsync()` to run both sync + async validators.
const asyncErrors = await input.validateAsync();
res.status(statusCode).json(jsonResponse);
}
```
// Result will be an array of `ValidationError[]`
if (errors.length) {
// Handle validation errors here, for example:
return res.status(400).json(errors);
}
```typescript
// express-server.ts
// Your input is guaranteed to be validated at this point.
await User.register(input);
import Express from 'express';
import { setValidationErrorHandler } from 'data-transfer-object';
import { expressErrorHandler } from './error-handler.ts';
import { ApiValidationError } from './custom-errors.ts';
import { signup } from './signup-controller.ts';
// Use `.toJSON()` to get a plain object with just your data.
// `.toJSON()` is automatically called when a DTO instance is stringified.
const data = input.toJSON();
typeof input.validate === 'function';
typeof data.validate === 'undefined';
setValidationErrorHandler(errors => {
throw new ApiValidationError(errors);
});
return res.status(200).json({ success: true });
export const app = Express();
app.use(Express.json());
app.use('/users/signup', signup);
app.use(expressErrorHandler);
```
```typescript
// signup-controller.ts
import { Request, Response, NextFunction } from 'express';
import { User } from './models';
import { UserSignupInput } from './input-classes';
export async function signup(req: Request, res: Response, next: NextFunction) {
try {
const { username, password } = new UserSignupInput(req.body).validate();
await User.register(username, password);
return res.status(200).json({ success: true });
} catch (err) {
return next(err);
}
}
```
## Development
We may also use something like [`express-async-errors`](https://github.com/davidbanham/express-async-errors) in order to avoid having to wrap our async code in try/catch statements and manually calling `next()`. This is something that will be automatically addressed by Express 5 once it is released.
Check package.json to find scripts related to installing dependencies, building, testing, linting and generating documentation.
## Development and contributions
Check package.json to find scripts related to installing dependencies, building, testing, linting and generating documentation. I am open to new issues and pull requests!
## License
MIT
import { validate, validateSync, ValidationError, ValidatorOptions } from 'class-validator';
export * from 'class-validator';
import { ValidationException } from './validation-exception';
import { onValidationError } from './validation-error-handler';

@@ -16,4 +17,7 @@ // Simple conditional mapping turns function types into `never` types

// Strict options by default
const defaultOpts: ValidatorOptions = {
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true,
};

@@ -31,2 +35,14 @@

/**
* Checks the input error list, and if non-empty, throws an error.
* @param errors The error list to check against.
*/
function assertEmptyErrorList(errors: ValidationError[]) {
if (errors.length) {
if (!onValidationError) throw new ValidationException(errors);
onValidationError(errors);
throw new ValidationException(errors);
}
}
/**
* Creates a new data transfer object which will validate and reshape its input

@@ -54,6 +70,6 @@ * data based on the validators of its own properties. Must be extended, should

* Runs all synchronous validators on this object.
* To run asynchronous validators as well, use `.validateAsync()`.
* To run asynchronous validators as well, use `.getValidationErrorsAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): ValidationError[] {
getValidationErrors(opts?: ValidatorOptions): ValidationError[] {
if (this[validated]) return this[validationErrors];

@@ -67,6 +83,6 @@ this[validationErrors] = validateSync(this, { ...defaultOpts, ...opts });

* Runs all synchronous and asynchronous validators on this object.
* Always returns a promise. To validate synchronously, use `.validate()`.
* Always returns a promise. To validate synchronously, use `.getValidationErrors()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts?: ValidatorOptions): Promise<ValidationError[]> {
async getValidationErrorsAsync(opts?: ValidatorOptions): Promise<ValidationError[]> {
if (this[validated]) return this[validationErrors];

@@ -89,2 +105,28 @@

/**
* Validates this object (sync validators only), and returns its plain data if validations pass.
* Otherwise, throws an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To run both sync and async validators, use `.validateAsync()`.
* @param opts Options to pass to the validator system.
*/
validate(opts?: ValidatorOptions): Data<this> {
const errors = this.getValidationErrors(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Validates this object asynchronously, and resolves to its plain data if validations pass.
* Otherwise, rejects with an error or runs the appropriate handler set with `setValidationErrorHandler()`.
*
* To validate synchronously, use `.validate()`.
* @param opts Options to pass to the validator system.
*/
async validateAsync(opts?: ValidatorOptions): Promise<Data<this>> {
const errors = await this.getValidationErrorsAsync(opts);
assertEmptyErrorList(errors);
return this.toJSON();
}
/**
* Returns a JSON friendly object containing only data properties of this object (ie, no validation functions).

@@ -91,0 +133,0 @@ * Automatically used by `JSON.stringify()`.

export * from './data-transfer-object';
export * from './validation-error-handler';
export * from './validation-error-map';
export * from './validation-exception';
export * from 'class-validator';
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