New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@slack/oauth

Package Overview
Dependencies
Maintainers
11
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@slack/oauth - npm Package Compare versions

Comparing version 2.2.0 to 2.3.0

4

dist/errors.d.ts

@@ -12,2 +12,3 @@ export interface CodedError extends Error {

MissingStateError = "slack_oauth_missing_state",
MissingCodeError = "slack_oauth_missing_code",
UnknownError = "slack_oauth_unknown_error"

@@ -24,2 +25,5 @@ }

}
export declare class MissingCodeError extends Error implements CodedError {
code: ErrorCode;
}
export declare class UnknownError extends Error implements CodedError {

@@ -26,0 +30,0 @@ code: ErrorCode;

@@ -18,3 +18,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthorizationError = exports.UnknownError = exports.MissingStateError = exports.GenerateInstallUrlError = exports.InstallerInitializationError = exports.ErrorCode = void 0;
exports.AuthorizationError = exports.UnknownError = exports.MissingCodeError = exports.MissingStateError = exports.GenerateInstallUrlError = exports.InstallerInitializationError = exports.ErrorCode = void 0;
/**

@@ -29,2 +29,3 @@ * A dictionary of codes for errors produced by this package.

ErrorCode["MissingStateError"] = "slack_oauth_missing_state";
ErrorCode["MissingCodeError"] = "slack_oauth_missing_code";
ErrorCode["UnknownError"] = "slack_oauth_unknown_error";

@@ -62,2 +63,12 @@ })(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {}));

exports.MissingStateError = MissingStateError;
var MissingCodeError = /** @class */ (function (_super) {
__extends(MissingCodeError, _super);
function MissingCodeError() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.code = ErrorCode.MissingCodeError;
return _this;
}
return MissingCodeError;
}(Error));
exports.MissingCodeError = MissingCodeError;
var UnknownError = /** @class */ (function (_super) {

@@ -64,0 +75,0 @@ __extends(UnknownError, _super);

17

dist/index.d.ts

@@ -12,2 +12,3 @@ /// <reference types="node" />

* @param stateStore - Replacement function for the built-in `stateStore`
* @param stateVerification - Pass in false to disable state parameter verification
* @param installationStore - Interface to store and retrieve installation data from the database

@@ -19,3 +20,3 @@ * @param authVersion - Can be either `v1` or `v2`. Determines which slack Oauth URL and method to use

export declare class InstallProvider {
stateStore: StateStore;
stateStore?: StateStore;
installationStore: InstallationStore;

@@ -28,3 +29,4 @@ private clientId;

private authorizationUrl;
constructor({ clientId, clientSecret, stateSecret, stateStore, installationStore, authVersion, logger, logLevel, clientOptions, authorizationUrl, }: InstallProviderOptions);
private stateVerification;
constructor({ clientId, clientSecret, stateSecret, stateStore, stateVerification, installationStore, authVersion, logger, logLevel, clientOptions, authorizationUrl, }: InstallProviderOptions);
/**

@@ -41,6 +43,11 @@ * Fetches data from the installationStore

/**
* Returns search params from a URL and ignores protocol / hostname as those
* aren't guaranteed to be accurate e.g. in x-forwarded- scenarios
*/
private static extractSearchParams;
/**
* Returns a URL that is suitable for including in an Add to Slack button
* Uses stateStore to generate a value for the state query param.
*/
generateInstallUrl(options: InstallURLOptions): Promise<string>;
generateInstallUrl(options: InstallURLOptions, stateVerification?: boolean): Promise<string>;
/**

@@ -55,3 +62,3 @@ * This method handles the incoming request to the callback URL.

*/
handleCallback(req: IncomingMessage, res: ServerResponse, options?: CallbackOptions): Promise<void>;
handleCallback(req: IncomingMessage, res: ServerResponse, options?: CallbackOptions, installOptions?: InstallURLOptions): Promise<void>;
}

@@ -63,2 +70,3 @@ export interface InstallProviderOptions {

stateSecret?: string;
stateVerification?: boolean;
installationStore?: InstallationStore;

@@ -253,3 +261,2 @@ authVersion?: 'v1' | 'v2';

is_enterprise_install: boolean;
response_metadata: {};
}

@@ -256,0 +263,0 @@ export { Logger, LogLevel } from './logger';

@@ -61,8 +61,32 @@ "use strict";

exports.LogLevel = exports.InstallProvider = void 0;
var url_1 = require("url");
var jsonwebtoken_1 = require("jsonwebtoken");
var web_api_1 = require("@slack/web-api");
var errors_1 = require("./errors");
var url_1 = require("url");
var logger_1 = require("./logger");
var stores_1 = require("./stores");
// default implementation of StateStore
var ClearStateStore = /** @class */ (function () {
function ClearStateStore(stateSecret) {
this.stateSecret = stateSecret;
}
ClearStateStore.prototype.generateStateParam = function (installOptions, now) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, (0, jsonwebtoken_1.sign)({ installOptions: installOptions, now: now.toJSON() }, this.stateSecret)];
});
});
};
ClearStateStore.prototype.verifyStateParam = function (_now, state) {
return __awaiter(this, void 0, void 0, function () {
var decoded;
return __generator(this, function (_a) {
decoded = (0, jsonwebtoken_1.verify)(state, this.stateSecret);
// return installOptions
return [2 /*return*/, decoded.installOptions];
});
});
};
return ClearStateStore;
}());
/**

@@ -74,2 +98,3 @@ * InstallProvider Class.

* @param stateStore - Replacement function for the built-in `stateStore`
* @param stateVerification - Pass in false to disable state parameter verification
* @param installationStore - Interface to store and retrieve installation data from the database

@@ -82,3 +107,3 @@ * @param authVersion - Can be either `v1` or `v2`. Determines which slack Oauth URL and method to use

function InstallProvider(_a) {
var clientId = _a.clientId, clientSecret = _a.clientSecret, _b = _a.stateSecret, stateSecret = _b === void 0 ? undefined : _b, _c = _a.stateStore, stateStore = _c === void 0 ? undefined : _c, _d = _a.installationStore, installationStore = _d === void 0 ? new stores_1.MemoryInstallationStore() : _d, _e = _a.authVersion, authVersion = _e === void 0 ? 'v2' : _e, _f = _a.logger, logger = _f === void 0 ? undefined : _f, _g = _a.logLevel, logLevel = _g === void 0 ? undefined : _g, _h = _a.clientOptions, clientOptions = _h === void 0 ? {} : _h, _j = _a.authorizationUrl, authorizationUrl = _j === void 0 ? 'https://slack.com/oauth/v2/authorize' : _j;
var clientId = _a.clientId, clientSecret = _a.clientSecret, _b = _a.stateSecret, stateSecret = _b === void 0 ? undefined : _b, _c = _a.stateStore, stateStore = _c === void 0 ? undefined : _c, _d = _a.stateVerification, stateVerification = _d === void 0 ? true : _d, _e = _a.installationStore, installationStore = _e === void 0 ? new stores_1.MemoryInstallationStore() : _e, _f = _a.authVersion, authVersion = _f === void 0 ? 'v2' : _f, _g = _a.logger, logger = _g === void 0 ? undefined : _g, _h = _a.logLevel, logLevel = _h === void 0 ? undefined : _h, _j = _a.clientOptions, clientOptions = _j === void 0 ? {} : _j, _k = _a.authorizationUrl, authorizationUrl = _k === void 0 ? 'https://slack.com/oauth/v2/authorize' : _k;
if (clientId === undefined || clientSecret === undefined) {

@@ -95,4 +120,8 @@ throw new errors_1.InstallerInitializationError('You must provide a valid clientId and clientSecret');

else {
this.logger = logger_1.getLogger('OAuth:InstallProvider', logLevel !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.INFO, logger);
this.logger = (0, logger_1.getLogger)('OAuth:InstallProvider', logLevel !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.INFO, logger);
}
this.stateVerification = stateVerification;
if (!stateVerification) {
this.logger.warn("You've set InstallProvider#stateVerification to false. This flag is intended to enable org-wide app installations from admin pages. If this isn't your scenario, we recommend setting stateVerification to true and starting your OAuth flow from the provided `/slack/install` or your own starting endpoint.");
}
// Setup stateStore

@@ -102,8 +131,11 @@ if (stateStore !== undefined) {

}
else if (stateSecret === undefined) {
throw new errors_1.InstallerInitializationError('You must provide a State Secret to use the built-in state store');
else if (this.stateVerification) {
// if state verification is disabled, state store is not necessary
if (stateSecret !== undefined) {
this.stateStore = new ClearStateStore(stateSecret);
}
else {
throw new errors_1.InstallerInitializationError('To use the built-in state store you must provide a State Secret');
}
}
else {
this.stateStore = new ClearStateStore(stateSecret);
}
this.installationStore = installationStore;

@@ -212,4 +244,8 @@ this.clientId = clientId;

updatedInstallation = __assign(__assign({}, installationUpdates), (_a = {}, _a[tokenType] = __assign(__assign({}, queryResult[tokenType]), installationUpdates[tokenType]), _a));
// TODO: related to the above TODO comment as well
// eslint-disable-next-line no-await-in-loop
return [4 /*yield*/, this.installationStore.storeInstallation(updatedInstallation)];
case 7:
// TODO: related to the above TODO comment as well
// eslint-disable-next-line no-await-in-loop
_b.sent();

@@ -258,6 +294,15 @@ _b.label = 8;

/**
* Returns search params from a URL and ignores protocol / hostname as those
* aren't guaranteed to be accurate e.g. in x-forwarded- scenarios
*/
InstallProvider.extractSearchParams = function (req) {
var searchParams = new url_1.URL(req.url, "https://" + req.headers.host).searchParams;
return searchParams;
};
/**
* Returns a URL that is suitable for including in an Add to Slack button
* Uses stateStore to generate a value for the state query param.
*/
InstallProvider.prototype.generateInstallUrl = function (options) {
InstallProvider.prototype.generateInstallUrl = function (options, stateVerification) {
if (stateVerification === void 0) { stateVerification = true; }
return __awaiter(this, void 0, void 0, function () {

@@ -279,2 +324,3 @@ var slackURL, scopes, params, state, userScopes;

params = new url_1.URLSearchParams("scope=" + scopes);
if (!(stateVerification && this.stateStore)) return [3 /*break*/, 2];
return [4 /*yield*/, this.stateStore.generateStateParam(options, new Date())];

@@ -284,2 +330,4 @@ case 1:

params.append('state', state);
_a.label = 2;
case 2:
// client id

@@ -321,17 +369,24 @@ params.append('client_id', this.clientId);

*/
InstallProvider.prototype.handleCallback = function (req, res, options) {
InstallProvider.prototype.handleCallback = function (req, res, options, installOptions) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var parsedUrl, code, state, installOptions, client, installation, resp, v1Resp, v1Installation, authResult, botId, v2Resp, v2Installation, currentUTC, authResult, authResult, error_2;
var code, flowError, state, searchParams, emptyInstallOptions, client, installation, resp, v1Resp, v1Installation, authResult, botId, v2Resp, v2Installation, currentUTC, authResult, authResult, error_2;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 16, , 17]);
_b.trys.push([0, 17, , 18]);
if (req.url !== undefined) {
parsedUrl = url_1.parse(req.url, true);
code = parsedUrl.query.code;
state = parsedUrl.query.state;
if (state === undefined || state === '' || code === undefined) {
throw new errors_1.MissingStateError('redirect url is missing state or code query parameters');
searchParams = InstallProvider.extractSearchParams(req);
flowError = searchParams.get('error');
if (flowError === 'access_denied') {
throw new errors_1.AuthorizationError('User cancelled the OAuth installation flow!');
}
code = searchParams.get('code');
state = searchParams.get('state');
if (!code) {
throw new errors_1.MissingCodeError('Redirect url is missing the required code query parameter');
}
if (this.stateVerification && !state) {
throw new errors_1.MissingStateError('Redirect url is missing the state query parameter. If this is intentional, see options for disabling default state verification.');
}
}

@@ -341,9 +396,18 @@ else {

}
if (!(this.stateVerification && this.stateStore)) return [3 /*break*/, 2];
return [4 /*yield*/, this.stateStore.verifyStateParam(new Date(), state)];
case 1:
// eslint-disable-next-line no-param-reassign
installOptions = _b.sent();
_b.label = 2;
case 2:
if (!installOptions) {
emptyInstallOptions = { scopes: [] };
// eslint-disable-next-line no-param-reassign
installOptions = emptyInstallOptions;
}
client = new web_api_1.WebClient(undefined, this.clientOptions);
installation = void 0;
resp = void 0;
if (!(this.authVersion === 'v1')) return [3 /*break*/, 5];
if (!(this.authVersion === 'v1')) return [3 /*break*/, 6];
return [4 /*yield*/, client.oauth.access({

@@ -355,3 +419,3 @@ code: code,

})];
case 2:
case 3:
v1Resp = _b.sent();

@@ -370,5 +434,5 @@ v1Installation = {

};
if (!(v1Resp.bot !== undefined)) return [3 /*break*/, 4];
if (!(v1Resp.bot !== undefined)) return [3 /*break*/, 5];
return [4 /*yield*/, runAuthTest(v1Resp.bot.bot_access_token, this.clientOptions)];
case 3:
case 4:
authResult = _b.sent();

@@ -382,8 +446,8 @@ botId = authResult.bot_id;

};
_b.label = 4;
case 4:
_b.label = 5;
case 5:
resp = v1Resp;
installation = v1Installation;
return [3 /*break*/, 11];
case 5: return [4 /*yield*/, client.oauth.v2.access({
return [3 /*break*/, 12];
case 6: return [4 /*yield*/, client.oauth.v2.access({
code: code,

@@ -394,3 +458,3 @@ client_id: this.clientId,

})];
case 6:
case 7:
v2Resp = _b.sent();

@@ -412,5 +476,5 @@ v2Installation = {

currentUTC = Math.floor(Date.now() / 1000);
if (!(v2Resp.access_token !== undefined && v2Resp.scope !== undefined && v2Resp.bot_user_id !== undefined)) return [3 /*break*/, 8];
if (!(v2Resp.access_token !== undefined && v2Resp.scope !== undefined && v2Resp.bot_user_id !== undefined)) return [3 /*break*/, 9];
return [4 /*yield*/, runAuthTest(v2Resp.access_token, this.clientOptions)];
case 7:
case 8:
authResult = _b.sent();

@@ -431,7 +495,7 @@ v2Installation.bot = {

}
_b.label = 8;
case 8:
if (!(v2Resp.authed_user !== undefined && v2Resp.authed_user.access_token !== undefined)) return [3 /*break*/, 10];
_b.label = 9;
case 9:
if (!(v2Resp.authed_user !== undefined && v2Resp.authed_user.access_token !== undefined)) return [3 /*break*/, 11];
return [4 /*yield*/, runAuthTest(v2Resp.authed_user.access_token, this.clientOptions)];
case 9:
case 10:
authResult = _b.sent();

@@ -446,8 +510,8 @@ if (v2Resp.is_enterprise_install && v2Installation.enterpriseUrl === undefined) {

}
_b.label = 10;
case 10:
_b.label = 11;
case 11:
resp = v2Resp;
installation = v2Installation;
_b.label = 11;
case 11:
_b.label = 12;
case 12:
if (resp.incoming_webhook !== undefined) {

@@ -461,3 +525,3 @@ installation.incomingWebhook = {

}
if (installOptions !== undefined && installOptions.metadata !== undefined) {
if (installOptions && installOptions.metadata !== undefined) {
// Pass the metadata in state parameter if exists.

@@ -467,12 +531,12 @@ // Developers can use the value for additional/custom data associated with the installation.

}
if (!installation.isEnterpriseInstall) return [3 /*break*/, 13];
if (!installation.isEnterpriseInstall) return [3 /*break*/, 14];
return [4 /*yield*/, this.installationStore.storeInstallation(installation, this.logger)];
case 12:
case 13:
_b.sent();
return [3 /*break*/, 15];
case 13: return [4 /*yield*/, this.installationStore.storeInstallation(installation, this.logger)];
case 14:
return [3 /*break*/, 16];
case 14: return [4 /*yield*/, this.installationStore.storeInstallation(installation, this.logger)];
case 15:
_b.sent();
_b.label = 15;
case 15:
_b.label = 16;
case 16:
// Call the success callback

@@ -487,4 +551,4 @@ if (options !== undefined && options.success !== undefined) {

}
return [3 /*break*/, 17];
case 16:
return [3 /*break*/, 18];
case 17:
error_2 = _b.sent();

@@ -501,4 +565,4 @@ this.logger.error(error_2);

}
return [3 /*break*/, 17];
case 17: return [2 /*return*/];
return [3 /*break*/, 18];
case 18: return [2 /*return*/];
}

@@ -511,28 +575,2 @@ });

exports.InstallProvider = InstallProvider;
// default implementation of StateStore
var ClearStateStore = /** @class */ (function () {
function ClearStateStore(stateSecret) {
this.stateSecret = stateSecret;
}
ClearStateStore.prototype.generateStateParam = function (installOptions, now) {
return __awaiter(this, void 0, void 0, function () {
var state;
return __generator(this, function (_a) {
state = jsonwebtoken_1.sign({ installOptions: installOptions, now: now.toJSON() }, this.stateSecret);
return [2 /*return*/, state];
});
});
};
ClearStateStore.prototype.verifyStateParam = function (_now, state) {
return __awaiter(this, void 0, void 0, function () {
var decoded;
return __generator(this, function (_a) {
decoded = jsonwebtoken_1.verify(state, this.stateSecret);
// return installOptions
return [2 /*return*/, decoded.installOptions];
});
});
};
return ClearStateStore;
}());
// Default function to call when OAuth flow is successful

@@ -539,0 +577,0 @@ function callbackSuccess(installation, _options, _req, res) {

@@ -8,3 +8,3 @@ import { Installation, InstallationStore, InstallationQuery } from '../index';

}
export declare class FileInstallationStore implements InstallationStore {
export default class FileInstallationStore implements InstallationStore {
private baseDir;

@@ -11,0 +11,0 @@ private historicalDataEnabled;

@@ -42,3 +42,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.FileInstallationStore = void 0;
var fs_1 = __importDefault(require("fs"));

@@ -49,3 +48,3 @@ var path_1 = __importDefault(require("path"));

function FileInstallationStore(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.baseDir, baseDir = _c === void 0 ? os_1.homedir() + "/.bolt-js-app-installation" : _c, clientId = _b.clientId, _d = _b.historicalDataEnabled, historicalDataEnabled = _d === void 0 ? true : _d;
var _b = _a === void 0 ? {} : _a, _c = _b.baseDir, baseDir = _c === void 0 ? (0, os_1.homedir)() + "/.bolt-js-app-installation" : _c, clientId = _b.clientId, _d = _b.historicalDataEnabled, historicalDataEnabled = _d === void 0 ? true : _d;
this.baseDir = clientId !== undefined ? baseDir + "/" + clientId : baseDir;

@@ -127,3 +126,2 @@ this.historicalDataEnabled = historicalDataEnabled;

try {
// tslint:disable-next-line:ter-arrow-parens
filesToDelete.map(function (filePath) { return deleteFile(path_1.default.resolve(installationDir + "/" + filePath)); });

@@ -150,3 +148,3 @@ }

}());
exports.FileInstallationStore = FileInstallationStore;
exports.default = FileInstallationStore;
function writeToFile(filePath, data) {

@@ -153,0 +151,0 @@ fs_1.default.writeFile(filePath, data, function (err) {

@@ -1,3 +0,3 @@

export { MemoryInstallationStore } from './memory-store';
export { FileInstallationStore } from './file-store';
export { default as MemoryInstallationStore } from './memory-store';
export { default as FileInstallationStore } from './file-store';
//# sourceMappingURL=index.d.ts.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileInstallationStore = exports.MemoryInstallationStore = void 0;
var memory_store_1 = require("./memory-store");
Object.defineProperty(exports, "MemoryInstallationStore", { enumerable: true, get: function () { return memory_store_1.MemoryInstallationStore; } });
Object.defineProperty(exports, "MemoryInstallationStore", { enumerable: true, get: function () { return __importDefault(memory_store_1).default; } });
var file_store_1 = require("./file-store");
Object.defineProperty(exports, "FileInstallationStore", { enumerable: true, get: function () { return file_store_1.FileInstallationStore; } });
Object.defineProperty(exports, "FileInstallationStore", { enumerable: true, get: function () { return __importDefault(file_store_1).default; } });
//# sourceMappingURL=index.js.map

@@ -6,3 +6,3 @@ import { Installation, InstallationStore, InstallationQuery } from '../index';

}
export declare class MemoryInstallationStore implements InstallationStore {
export default class MemoryInstallationStore implements InstallationStore {
devDB: DevDatabase;

@@ -9,0 +9,0 @@ storeInstallation(installation: Installation, logger?: Logger): Promise<void>;

@@ -50,3 +50,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryInstallationStore = void 0;
// Default Install Store. Should only be used for development

@@ -140,3 +139,3 @@ var MemoryInstallationStore = /** @class */ (function () {

}());
exports.MemoryInstallationStore = MemoryInstallationStore;
exports.default = MemoryInstallationStore;
//# sourceMappingURL=memory-store.js.map
{
"name": "@slack/oauth",
"version": "2.2.0",
"version": "2.3.0",
"description": "Official library for interacting with Slack's Oauth endpoints",
"author": "Slack Technologies, Inc.",
"author": "Slack Technologies, LLC",
"license": "MIT",

@@ -34,4 +34,5 @@ "keywords": [

"build:clean": "shx rm -rf ./dist ./coverage ./.nyc_output",
"lint": "tslint --project .",
"test": "nyc mocha --config .mocharc.json src/*.spec.js",
"lint": "eslint --ext .ts src",
"test": "npm run lint && npm run test:mocha",
"test:mocha": "nyc mocha --config .mocharc.json src/*.spec.js",
"coverage": "codecov -F oauthhelper --root=$PWD",

@@ -43,3 +44,3 @@ "ref-docs:model": "api-extractor run",

"@slack/logger": "^3.0.0",
"@slack/web-api": "^6.0.0",
"@slack/web-api": "^6.3.0",
"@types/jsonwebtoken": "^8.3.7",

@@ -53,5 +54,13 @@ "@types/node": ">=12",

"@microsoft/api-extractor": "^7.3.4",
"@typescript-eslint/eslint-plugin": "^4.4.1",
"@typescript-eslint/parser": "^4.4.0",
"chai": "^4.2.0",
"codecov": "^3.0.4",
"mocha": "^6.1.4",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsdoc": "^30.6.1",
"eslint-plugin-node": "^11.1.0",
"mocha": "^9.1.0",
"nop": "^1.0.0",

@@ -65,7 +74,5 @@ "nyc": "^14.1.1",

"ts-node": "^8.2.0",
"tslint": "^5.17.0",
"tslint-config-airbnb": "^5.11.1",
"typescript": "^4.1",
"uncaughtException": "^1.0.0"
}
}
}

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