Socket
Socket
Sign inDemoInstall

azurite

Package Overview
Dependencies
250
Maintainers
4
Versions
153
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.13.1 to 3.14.0

24

ChangeLog.md

@@ -7,2 +7,24 @@ # Changelog

## 2021.7 Version 3.14.0
General:
- Bump up service API version to 2020-10-02
- Added an example for run Azurite with https in docker in Readme
Blob:
- Fixed SAS-token validation for requests with Content-Encoding/Content-Language headers.
- Return `x-ms-copy-status` header from syncCopyFromURL.
- Fixed continuation token not work correctly when blob names are only number
Table:
- Added test for URI path parser and updated regex to allow for non standard dev store account names.
- Corrected serialization of errors during Entity Group Transactions.
- Corrected entity tests using invalid eTag formats.
- Added support for PATCH Verb in Table Batch Operations / Entity Group Transactions.
- Added /@Element to the odata.metadata response.
- Allowed use of empty string for partitionKey and rowKey on InsertEntity.
## 2021.6 Version 3.13.1

@@ -35,2 +57,3 @@

- Added check for invalid table name.
- Improved handling of empty strings and strings with multiple spaces for query filters.

@@ -59,2 +82,3 @@ ## 2021.4 Version 3.12.0

- Skip Content-Length check for Append Block if the `--loose` flag is set.
- BlockBlob_StageBlock now checks for Content-MD5 integrity, and will fail if this check does not pass.

@@ -61,0 +85,0 @@ ## 2020.12 Version 3.10.0

6

dist/src/blob/authentication/BlobSharedKeyAuthenticator.js

@@ -32,4 +32,4 @@ "use strict";

req.getMethod().toUpperCase(),
this.getHeaderValueToSign(req, constants_1.HeaderConstants.CONTENT_ENCODING),
this.getHeaderValueToSign(req, constants_1.HeaderConstants.CONTENT_LANGUAGE),
this.getHeaderValueToSign(req, constants_1.HeaderConstants.CONTENT_ENCODING),
this.getHeaderValueToSign(req, constants_1.HeaderConstants.CONTENT_LENGTH),

@@ -127,3 +127,3 @@ this.getHeaderValueToSign(req, constants_1.HeaderConstants.CONTENT_MD5),

}
const headersArray = headers.filter(value => {
const headersArray = headers.filter((value) => {
return value.name

@@ -137,3 +137,3 @@ .toLowerCase()

let canonicalizedHeadersStringToSign = "";
headersArray.forEach(header => {
headersArray.forEach((header) => {
canonicalizedHeadersStringToSign += `${header.name

@@ -140,0 +140,0 @@ .toLowerCase()

@@ -233,4 +233,7 @@ "use strict";

}
static getUnexpectedSyncCopyStatus(contextID, copyStatus) {
return new StorageError_1.default(409, "UnexpectedSyncCopyStatus", 'Expected copyStatus to be "success" but got different status.', contextID, { ReceivedCopyStatus: copyStatus });
}
}
exports.default = StorageErrorFactory;
//# sourceMappingURL=StorageErrorFactory.js.map

@@ -514,2 +514,11 @@ "use strict";

}, { account, container, blob }, copySource, metadata, options.tier, options);
let copyStatus;
if (res.copyStatus !== undefined) {
if (res.copyStatus === Models.CopyStatusType.Success) {
copyStatus = Models.SyncCopyStatusType.Success;
}
else {
throw StorageErrorFactory_1.default.getUnexpectedSyncCopyStatus(context.contextId, res.copyStatus);
}
}
const response = {

@@ -523,2 +532,3 @@ statusCode: 202,

copyId: res.copyId,
copyStatus,
clientRequestId: options.requestId

@@ -525,0 +535,0 @@ };

@@ -120,2 +120,7 @@ "use strict";

const date = blobCtx.startTime;
options.blobHTTPHeaders = options.blobHTTPHeaders || {};
const contentMD5 = context.request.getHeader("content-md5")
? options.blobHTTPHeaders.blobContentMD5 ||
context.request.getHeader("content-md5")
: undefined;
this.validateBlockId(blockId, blobCtx);

@@ -128,2 +133,18 @@ await this.metadataStore.checkContainerExist(context, accountName, containerName);

}
// Calculate MD5 for validation
const stream = await this.extentStore.readExtent(persistency, context.contextId);
const calculatedContentMD5 = await utils_2.getMD5FromStream(stream);
if (contentMD5 !== undefined) {
if (typeof contentMD5 === "string") {
const calculatedContentMD5String = Buffer.from(calculatedContentMD5).toString("base64");
if (contentMD5 !== calculatedContentMD5String) {
throw StorageErrorFactory_1.default.getInvalidOperation(context.contextId, "Provided contentMD5 doesn't match.");
}
}
else {
if (!Buffer.from(contentMD5).equals(calculatedContentMD5)) {
throw StorageErrorFactory_1.default.getInvalidOperation(context.contextId, "Provided contentMD5 doesn't match.");
}
}
}
const block = {

@@ -130,0 +151,0 @@ accountName,

@@ -6,4 +6,4 @@ "use strict";

const Models = tslib_1.__importStar(require("../generated/artifacts/models"));
exports.VERSION = "3.13.1";
exports.BLOB_API_VERSION = "2020-08-04";
exports.VERSION = "3.14.0";
exports.BLOB_API_VERSION = "2020-10-02";
exports.DEFAULT_BLOB_SERVER_HOST_NAME = "127.0.0.1"; // Change to 0.0.0.0 when needs external access

@@ -91,2 +91,3 @@ exports.DEFAULT_LIST_BLOBS_MAX_RESULTS = 5000;

exports.ValidAPIVersions = [
"2020-10-02",
"2020-08-04",

@@ -93,0 +94,0 @@ "2020-06-12",

@@ -65,4 +65,12 @@ "use strict";

}
/**
* Extracts the path from a URI
* @param uriString
* @returns just the path
*/
extractPath(uriString) {
return uriString.match(/\/\w+\/(\w+)/);
}
}
exports.BatchSerialization = BatchSerialization;
//# sourceMappingURL=BatchSerialization.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VALID_QUEUE_AUDIENCES = exports.ValidAPIVersions = exports.DEFAULT_QUEUE_PERSISTENCE_ARRAY = exports.QUEUE_STATUSCODE = exports.SECONDARY_SUFFIX = exports.HeaderConstants = exports.MethodConstants = exports.EMPTY_EXTENT_CHUNK = exports.UPDATE_VISIBILITYTIMEOUT_MAX = exports.UPDATE_VISIBILITYTIMEOUT_MIN = exports.DEFUALT_UPDATE_VISIBILITYTIMEOUT = exports.MESSAGETTL_MIN = exports.ENQUEUE_VISIBILITYTIMEOUT_MAX = exports.ENQUEUE_VISIBILITYTIMEOUT_MIN = exports.DEFUALT_MESSAGETTL = exports.MESSAGETEXT_LENGTH_MAX = exports.DEQUEUE_NUMOFMESSAGES_MAX = exports.DEQUEUE_NUMOFMESSAGES_MIN = exports.DEQUEUE_VISIBILITYTIMEOUT_MAX = exports.DEQUEUE_VISIBILITYTIMEOUT_MIN = exports.DEFUALT_DEQUEUE_VISIBILITYTIMEOUT = exports.LIST_QUEUE_MAXRESSULTS_MAX = exports.LIST_QUEUE_MAXRESSULTS_MIN = exports.QUEUE_SERVICE_PERMISSION = exports.NEVER_EXPIRE_DATE = exports.DEFAULT_GC_INTERVAL_MS = exports.LOGGER_CONFIGS = exports.DEFAULT_QUEUE_CONTEXT_PATH = exports.DEFAULT_ENABLE_ACCESS_LOG = exports.DEFAULT_ACCESS_LOG_PATH = exports.DEFAULT_ENABLE_DEBUG_LOG = exports.DEFAULT_DEBUG_LOG_PATH = exports.DEFAULT_QUEUE_PERSISTENCE_PATH = exports.DEFAULT_QUEUE_EXTENT_LOKI_DB_PATH = exports.DEFAULT_QUEUE_LOKI_DB_PATH = exports.IS_PRODUCTION = exports.DEFAULT_QUEUE_LISTENING_PORT = exports.DEFAULT_QUEUE_SERVER_HOST_NAME = exports.QUEUE_API_VERSION = exports.VERSION = void 0;
exports.VERSION = "3.13.1";
exports.QUEUE_API_VERSION = "2020-08-04";
exports.VERSION = "3.14.0";
exports.QUEUE_API_VERSION = "2020-10-02";
exports.DEFAULT_QUEUE_SERVER_HOST_NAME = "127.0.0.1"; // Change to 0.0.0.0 when needs external access

@@ -87,2 +87,3 @@ exports.DEFAULT_QUEUE_LISTENING_PORT = 10001;

exports.ValidAPIVersions = [
"2020-10-02",
"2020-08-04",

@@ -89,0 +90,0 @@ "2020-06-12",

@@ -113,5 +113,7 @@ "use strict";

// serialize the error
responseString += changesetBoundary;
responseString += changesetBoundary + "\r\n";
// then headers
// content type etc
responseString += "Content-Type: application/http\r\n";
responseString += "Content-Transfer-Encoding: binary\r\n";
responseString += "\r\n";
// then HTTP/1.1 404 etc

@@ -182,3 +184,4 @@ responseString += this.errorResponse;

case "PATCH":
throw new Error("Patch Method unsupported in batch.");
// this is using the PATCH verb to merge
({ __return, response } = await this.handleBatchMerge(request, response, batchContextClone, contentID));
break;

@@ -185,0 +188,0 @@ default:

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

let requestType = [];
requestType = subRequest.match("(GET|POST|PUT|MERGE|INSERT|DELETE)");
requestType = subRequest.match("(GET|PATCH|POST|PUT|MERGE|INSERT|DELETE)");
if (requestType === null || requestType.length < 2) {

@@ -69,4 +69,3 @@ throw new Error(`Couldn't extract verb from sub-Request:\n ${subRequest}`);

// extract the request path
const pathString = fullRequestURI[1];
const path = pathString.match(/\S+devstoreaccount1\/(\w+)/);
const path = this.extractPath(fullRequestURI[1]);
if (path === null || path.length < 2) {

@@ -459,6 +458,4 @@ throw new Error(`Couldn't extract path from URL in sub-Request:\n ${subRequest}`);

serializeError(err, contentID, request) {
const changesetBoundary = this.changesetBoundary.replace("changeset", "changesetresponse");
let errorReponse = "";
const odataError = err;
errorReponse += changesetBoundary + "\r\n";
// Errors in batch processing generate Bad Request error

@@ -465,0 +462,0 @@ errorReponse = this.serializeHttpStatusCode(errorReponse, 400);

@@ -99,5 +99,9 @@ "use strict";

const prefer = this.getAndCheckPreferHeader(tableContext);
// curently unable to use checking functions as the partitionKey
// and rowKey are not coming through the context.
// const partitionKey = this.getAndCheckPartitionKey(tableContext);
// const rowKey = this.getAndCheckRowKey(tableContext);
if (!options.tableEntityProperties ||
!options.tableEntityProperties.PartitionKey ||
// rowKey may be empty string
// rowKey and partitionKey may be empty string
options.tableEntityProperties.PartitionKey === null ||
options.tableEntityProperties.RowKey === null) {

@@ -104,0 +108,0 @@ throw StorageErrorFactory_1.default.getPropertiesNeedValue(context);

@@ -48,3 +48,3 @@ #!/usr/bin/env node

process
.once("message", msg => {
.once("message", (msg) => {
if (msg === "shutdown") {

@@ -64,6 +64,6 @@ console.log(beforeCloseMessage);

}
main().catch(err => {
console.error(`Exit die to unhandled error: ${err.message}`);
main().catch((err) => {
console.error(`Exiting due to an unhandled error: ${err.message}`);
process.exit(1);
});
//# sourceMappingURL=main.js.map

@@ -491,38 +491,96 @@ "use strict";

}
static tokenizeQuery(originalQuery) {
// Escape a single backtick to prevent interpreting the start of a template literal.
const query = originalQuery.replace(/`/g, "\\`");
let tokenStart = 0;
const tokens = [];
let inString = false;
let i;
function appendToken() {
if (i - tokenStart > 0) {
let token;
if (inString) {
// Extract the token and unescape quotes
token = query.substring(tokenStart, i).replace(/''/g, "'");
// Extract the leading type prefix, if any.
const stringStart = token.indexOf("'");
const typePrefix = token.substring(0, stringStart);
const backtickString = "`" + token.substring(typePrefix.length + 1) + "`";
// Remove the GUID type prefix since we compare these as strings
if (typePrefix === "guid") {
token = backtickString;
}
else {
token = typePrefix + backtickString;
}
}
else {
token = convertToken(query.substring(tokenStart, i));
}
if (token) {
tokens.push(token);
}
}
tokenStart = i + 1;
}
function convertToken(token) {
switch (token) {
case "TableName":
return "name";
case "eq":
return "===";
case "gt":
return ">";
case "ge":
return ">=";
case "lt":
return "<";
case "le":
return "<=";
case "ne":
return "!==";
case "and":
return "&&";
case "or":
return "||";
case "not":
return "!";
default:
return token;
}
}
for (i = 0; i < query.length; i++) {
if (inString) {
// Look for a double quote, inside of a string.
if (i < query.length - 1 && query[i] === "'" && query[i + 1] === "'") {
i++;
continue;
}
else if (query[i] === "'") {
appendToken();
inString = false;
}
}
else if (query[i] === "(" || query[i] === ")") {
i--;
appendToken();
i++;
tokens.push(query[i]);
tokenStart++;
}
else if (/\s/.test(query[i])) {
appendToken();
}
else if (query[i] === "'") {
inString = true;
}
}
appendToken();
return tokens;
}
/**
* Azurite V2 query entities implementation as temporary workaround before new refactored implementation of querying.
* TODO: Handle query types
*
* @param query Query Enties $query string.
*/
generateQueryEntityWhereFunction(query) {
if (query === undefined) {
return () => true;
}
const filter = query
// ignoring these query keywords since we compare simply on a string-level
// .replace(/\bbinary\b/g, "")
.replace(/\bguid\b/g, "")
// Escape a single backtick to prevent interpreting the start of a template literal.
.replace(/`/g, "\\`")
// A simple quotation mark is escaped with another one (i.e. '').
// Since we will evaluate this string we replace simple quotation marks
// indictaing strings with template quotation marks
.replace(/''/g, "@ESCAPEDQUOTE@")
.replace(/'/g, "`")
.replace(/@ESCAPEDQUOTE@/g, `'`)
// Mapping 'TableName' to 'name' which is used internally as attribute name
.replace(/\bTableName\b/g, "name")
// Mapping operators
.replace(/\beq\b/g, "===")
.replace(/\bgt\b/g, ">")
.replace(/\bge\b/g, ">=")
.replace(/\blt\b/g, "<")
.replace(/\ble\b/g, "<=")
.replace(/\bne\b/g, "!==")
.replace(/\band\b/g, "&&")
.replace(/\bor\b/g, "||")
.replace(/\(/g, " ( ")
.replace(/\)/g, " ) ")
.replace(/\bnot\b/g, " ! ");
static transformQuery(query) {
// If a token is neither a number, nor a boolean, nor a string enclosed with quotation marks it is an operand.

@@ -534,3 +592,3 @@ // Operands are attributes of the object used within the where clause of LokiJS, thus we need to prepend each

let previousIsOp = false;
const tokens = filter.split(" ");
const tokens = LokiTableMetadataStore.tokenizeQuery(query);
let counter = -1;

@@ -598,2 +656,12 @@ for (let token of tokens) {

transformedQuery += ")";
return transformedQuery;
}
/**
* @param query Query Enties $query string.
*/
generateQueryEntityWhereFunction(query) {
if (query === undefined) {
return () => true;
}
const transformedQuery = LokiTableMetadataStore.transformQuery(query);
// tslint:disable-next-line: no-console

@@ -600,0 +668,0 @@ // console.log(query);

@@ -16,4 +16,4 @@ "use strict";

exports.DEFAULT_TABLE_CONTEXT_PATH = "azurite_table_context";
exports.TABLE_API_VERSION = "2020-08-04";
exports.VERSION = "3.13.1";
exports.TABLE_API_VERSION = "2020-10-02";
exports.VERSION = "3.14.0";
exports.HeaderConstants = {

@@ -42,2 +42,3 @@ SERVER: "Server",

exports.ValidAPIVersions = [
"2020-10-02",
"2020-08-04",

@@ -44,0 +45,0 @@ "2020-06-12",

@@ -89,2 +89,6 @@ "use strict";

exports.updateEntityOdataAnnotationsForResponse = updateEntityOdataAnnotationsForResponse;
// table service APIs are in layers
// we need to ensure that table, entity, and service
// API layers are not affected when we change this odata response.
// check that change does not impact query entities & query tables
function getOdataAnnotations(account, urlPrefix, table, partitionKey, rowKey) {

@@ -99,3 +103,3 @@ const urlPrefixEndWithSlash = urlPrefix.endsWith("/")

return {
odatametadata: `${urlPrefixEndWithSlash}$metadata#${table}`,
odatametadata: `${urlPrefixEndWithSlash}$metadata#${table}/@Element`,
odatatype: `${account}.${table}`,

@@ -102,0 +106,0 @@ odataid: `${urlPrefixEndWithSlash}${table}(PartitionKey='${partitionKey}',RowKey='${rowKey}')`,

@@ -6,3 +6,3 @@ {

"icon": "icon.png",
"version": "3.13.1",
"version": "3.14.0",
"publisher": "Azurite",

@@ -34,7 +34,7 @@ "categories": [

"mysql2": "^2.1.0",
"rimraf": "^2.6.3",
"rimraf": "^3.0.2",
"sequelize": "^6.3.0",
"tedious": "^9.2.1",
"tedious": "^11.0.9",
"to-readable-stream": "^2.1.0",
"tslib": "^1.9.3",
"tslib": "^2.3.0",
"uri-templates": "^0.2.0",

@@ -56,10 +56,10 @@ "uuid": "^3.3.2",

"@types/lokijs": "^1.5.2",
"@types/mocha": "^5.2.6",
"@types/mocha": "^9.0.0",
"@types/morgan": "^1.7.35",
"@types/multistream": "^2.1.1",
"@types/node": "^14.14.24",
"@types/rimraf": "^2.0.2",
"@types/rimraf": "^3.0.0",
"@types/uri-templates": "^0.1.29",
"@types/uuid": "^3.4.4",
"@types/validator": "^10.11.3",
"@types/validator": "^13.1.4",
"@types/vscode": "^1.39.0",

@@ -71,4 +71,4 @@ "@types/xml2js": "^0.4.3",

"cross-var": "^1.1.0",
"husky": "^4.3.5",
"lint-staged": "^8.2.1",
"husky": "^7.0.0",
"lint-staged": "^11.0.0",
"mocha": "^5.2.0",

@@ -78,3 +78,3 @@ "prettier": "^2.2.1",

"ts-mockito": "^2.6.1",
"ts-node": "^9.0.0",
"ts-node": "^10.0.0",
"tslint": "^6.1.3",

@@ -81,0 +81,0 @@ "typescript": "^4.2.4",

@@ -12,3 +12,3 @@ # Azurite V3

| ------------------------------------------------------------------ | ------------------------- | ------------------------------ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 3.13.1 | 2020-08-04 | Blob, Queue and Table(preview) | Azurite V3 based on TypeScript & New Architecture | [NPM](https://www.npmjs.com/package/azurite) - [Docker](https://hub.docker.com/_/microsoft-azure-storage-azurite) - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite) |
| 3.14.0 | 2020-10-02 | Blob, Queue and Table(preview) | Azurite V3 based on TypeScript & New Architecture | [NPM](https://www.npmjs.com/package/azurite) - [Docker](https://hub.docker.com/_/microsoft-azure-storage-azurite) - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite) |
| [Legacy (v2)](https://github.com/Azure/Azurite/tree/legacy-master) | 2016-05-31 | Blob, Queue and Table | Legacy Azurite V2 | [NPM](https://www.npmjs.com/package/azurite) |

@@ -28,3 +28,3 @@

- Blob storage features align with Azure Storage API version 2020-08-04 (Refer to support matrix section below)
- Blob storage features align with Azure Storage API version 2020-10-02 (Refer to support matrix section below)
- SharedKey/Account SAS/Service SAS/Public Access Authentications

@@ -35,3 +35,3 @@ - Get/Set Blob Service Properties

- Create/Read/List/Update/Delete Page Blobs
- Queue storage features align with Azure Storage API version 2020-08-04 (Refer to support matrix section below)
- Queue storage features align with Azure Storage API version 2020-10-02 (Refer to support matrix section below)
- SharedKey/Account SAS/Service SAS

@@ -42,3 +42,3 @@ - Get/Set Queue Service Properties

- Put/Get/Peek/Updata/Deleta/Clear Messages
- Table storage features align with Azure Storage API version 2020-08-04 (Refer to support matrix section below)
- Table storage features align with Azure Storage API version 2020-10-02 (Refer to support matrix section below)
- SharedKey/Account SAS/Service SAS

@@ -247,6 +247,7 @@ - Create/List/Delete Tables

Optional. By default, Azurite V3 will listen to 10000 as blob service port, and 10001 as queue service port.
Optional. By default, Azurite V3 will listen to 10000 as blob service port, and 10001 as queue service port, and 10002 as the table service port.
You can customize the listening port per your requirements.
> Warning: After using a customized port, you need to update connection string or configurations correspondingly in your Storage Tools or SDKs.
> If starting Azurite you see error `Error: listen EACCES 0.0.0.0:10000` the TCP port is most likely already occupied by another process.

@@ -444,4 +445,9 @@ #### Customize Blob/Queue Service Listening Port

NOTE: If you are using the Azure SDKs, then you will also need to pass the `--oauth basic` option.
If you start Azurite with docker, you need to map the folder contains the cert and key files to docker.
In following example, the local folder c:/azurite contains the cert and key files, and map it to /workspace on docker.
```bash
docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 -v c:/azurite:/workspace mcr.microsoft.com/azure-storage/azurite azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --cert /workspace/127.0.0.1.pem --key /workspace/127.0.0.1-key.pem
```
##### OpenSSL

@@ -590,3 +596,3 @@

To use Azurite with the [Azure SDKs](https://aka.ms/azsdk), you must use OAuth and HTTPS options:
To use Azurite with the [Azure SDKs](https://aka.ms/azsdk), you can use OAuth with HTTPS options:

@@ -792,3 +798,3 @@ `azurite --oauth basic --cert certname.pem --key certname-key.pem`

Azurite V3 supports features from Azure Storage API version 2020-08-04, and will maintain parity with the latest API versions, in a more frequent update frequency than legacy Azurite V2.
Azurite V3 supports features from Azure Storage API version 2020-10-02, and will maintain parity with the latest API versions, in a more frequent update frequency than legacy Azurite V2.

@@ -804,3 +810,3 @@ ## TypeScript Server Code Generator

Latest release targets **2020-08-04** API version **blob** service.
Latest release targets **2020-10-02** API version **blob** service.

@@ -860,4 +866,5 @@ Detailed support matrix:

- Version Level Worm
- Sync copy blob by access source with oauth
Latest version supports for **2020-08-04** API version **queue** service.
Latest version supports for **2020-10-02** API version **queue** service.
Detailed support matrix:

@@ -892,3 +899,3 @@

Latest version supports for **2020-08-04** API version **table** service (preview).
Latest version supports for **2020-10-02** API version **table** service (preview).
Detailed support matrix:

@@ -895,0 +902,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 too big to display

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc