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

azure-iot-device-http

Package Overview
Dependencies
Maintainers
3
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

azure-iot-device-http - npm Package Compare versions

Comparing version 1.2.3 to 1.3.0

8

lib/http.d.ts
/// <reference types="node" />
import { EventEmitter } from 'events';
import { results, Message } from 'azure-iot-common';
import { results, Message, AuthenticationProvider } from 'azure-iot-common';
import { DeviceMethodResponse, Client } from 'azure-iot-device';

@@ -12,3 +12,3 @@ /**

export declare class Http extends EventEmitter implements Client.Transport {
private _config;
private _authenticationProvider;
private _http;

@@ -25,3 +25,3 @@ private _opts;

*/
constructor(config: Client.Config, http?: any);
constructor(authenticationProvider: AuthenticationProvider, http?: any);
/**

@@ -169,3 +169,3 @@ * @private

disableMethods(callback: (err?: Error) => void): void;
private _insertAuthHeaderIfNecessary(headers);
private _insertAuthHeaderIfNecessary(headers, credentials);
/**

@@ -172,0 +172,0 @@ * @private

@@ -75,5 +75,5 @@ // Copyright (c) Microsoft. All rights reserved.

*/
function Http(config, http) {
function Http(authenticationProvider, http) {
var _this = _super.call(this) || this;
_this._config = config;
_this._authenticationProvider = authenticationProvider;
_this._http = http || new azure_iot_http_base_1.Http();

@@ -134,3 +134,3 @@ _this._opts = defaultOptions;

Http.prototype.sendEvent = function (message, done) {
var config = this._config;
var _this = this;
/*Codes_SRS_NODE_DEVICE_HTTP_05_002: [The `sendEvent` method shall construct an HTTP request using information supplied by the caller, as follows:

@@ -145,41 +145,50 @@ ```

```]*/
var path = azure_iot_common_1.endpoint.eventPath(config.deviceId);
var httpHeaders = {
'iothub-to': path,
'User-Agent': 'azure-iot-device/' + packageJson.version,
};
this._insertAuthHeaderIfNecessary(httpHeaders);
for (var i = 0; i < message.properties.count(); i++) {
var propItem = message.properties.getItem(i);
/*Codes_SRS_NODE_DEVICE_HTTP_13_001: [ sendEvent shall add message properties as HTTP headers and prefix the key name with the string iothub-app. ]*/
httpHeaders[MESSAGE_PROP_HEADER_PREFIX + propItem.key] = propItem.value;
}
if (message.messageId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_014: [If the `message` object has a `messageId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-MessageId`.]*/
httpHeaders['IoTHub-MessageId'] = message.messageId;
}
if (message.correlationId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_015: [If the `message` object has a `correlationId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-CorrelationId`.]*/
httpHeaders['IoTHub-CorrelationId'] = message.correlationId;
}
if (message.userId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_016: [If the `message` object has a `userId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-UserId`.]*/
httpHeaders['IoTHub-UserId'] = message.userId;
}
if (message.to) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_017: [If the `message` object has a `to` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-To`.]*/
httpHeaders['IoTHub-To'] = message.to;
}
if (message.expiryTimeUtc) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_018: [If the `message` object has a `expiryTimeUtc` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-Expiry`.]*/
httpHeaders['IoTHub-Expiry'] = message.expiryTimeUtc;
}
if (message.ack) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_019: [If the `message` object has a `ack` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-Ack`.]*/
httpHeaders['IoTHub-Ack'] = message.ack;
}
/*Codes_SRS_NODE_DEVICE_HTTP_16_013: [If using x509 authentication the `Authorization` header shall not be set and the x509 parameters shall instead be passed to the underlying transpoort.]*/
var request = this._http.buildRequest('POST', path + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders, config.host, config.x509, handleResponse(done));
request.write(message.getBytes());
request.end();
/*Codes_SRS_NODE_DEVICE_HTTP_16_032: [All HTTP requests shall obtain the credentials necessary to execute the request by calling `getDeviceCredentials` on the `AuthenticationProvider` object passed to the `Http` constructor.]*/
this._authenticationProvider.getDeviceCredentials(function (err, config) {
if (err) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_033: [if the `getDeviceCredentials` fails with an error, the Http request shall call its callback with that error]*/
done(err);
}
else {
var path = azure_iot_common_1.endpoint.eventPath(config.deviceId);
var httpHeaders = {
'iothub-to': path,
'User-Agent': 'azure-iot-device/' + packageJson.version,
};
_this._insertAuthHeaderIfNecessary(httpHeaders, config);
for (var i = 0; i < message.properties.count(); i++) {
var propItem = message.properties.getItem(i);
/*Codes_SRS_NODE_DEVICE_HTTP_13_001: [ sendEvent shall add message properties as HTTP headers and prefix the key name with the string iothub-app. ]*/
httpHeaders[MESSAGE_PROP_HEADER_PREFIX + propItem.key] = propItem.value;
}
if (message.messageId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_014: [If the `message` object has a `messageId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-MessageId`.]*/
httpHeaders['IoTHub-MessageId'] = message.messageId;
}
if (message.correlationId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_015: [If the `message` object has a `correlationId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-CorrelationId`.]*/
httpHeaders['IoTHub-CorrelationId'] = message.correlationId;
}
if (message.userId) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_016: [If the `message` object has a `userId` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-UserId`.]*/
httpHeaders['IoTHub-UserId'] = message.userId;
}
if (message.to) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_017: [If the `message` object has a `to` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-To`.]*/
httpHeaders['IoTHub-To'] = message.to;
}
if (message.expiryTimeUtc) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_018: [If the `message` object has a `expiryTimeUtc` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-Expiry`.]*/
httpHeaders['IoTHub-Expiry'] = message.expiryTimeUtc;
}
if (message.ack) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_019: [If the `message` object has a `ack` property, the value of the property shall be inserted in the headers of the HTTP request with the key `IoTHub-Ack`.]*/
httpHeaders['IoTHub-Ack'] = message.ack;
}
/*Codes_SRS_NODE_DEVICE_HTTP_16_013: [If using x509 authentication the `Authorization` header shall not be set and the x509 parameters shall instead be passed to the underlying transpoort.]*/
var request = _this._http.buildRequest('POST', path + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders, config.host, config.x509, handleResponse(done));
request.write(message.getBytes());
request.end();
}
});
};

@@ -206,52 +215,61 @@ /**

Http.prototype.sendEventBatch = function (messages, done) {
var config = this._config;
function constructBatchBody(messages) {
var body = '[';
messages.forEach(function (message, index) {
var buffMsg = new Buffer(message.getData());
if (index > 0)
body += ',';
body += '{\"body\":\"' + buffMsg.toString('base64') + '\"';
// Get the properties
var propertyIdx = 0;
var property = ',\"properties\":{';
for (propertyIdx = 0; propertyIdx < message.properties.count(); propertyIdx++) {
if (propertyIdx > 0)
property += ',';
var propItem = message.properties.getItem(propertyIdx);
/*Codes_SRS_NODE_DEVICE_HTTP_13_002: [ sendEventBatch shall prefix the key name for all message properties with the string iothub-app. ]*/
property += '\"' + MESSAGE_PROP_HEADER_PREFIX + propItem.key + '\":\"' + propItem.value + '\"';
}
if (propertyIdx > 0) {
property += '}';
body += property;
}
body += '}';
});
body += ']';
return body;
}
/*Codes_SRS_NODE_DEVICE_HTTP_05_003: [The `sendEventBatch` method shall construct an HTTP request using information supplied by the caller, as follows:
```
POST <config.host>/devices/<config.deviceId>/messages/events?api-version=<version> HTTP/1.1
iothub-to: /devices/<config.deviceId>/messages/events
User-Agent: <version string>
Content-Type: application/vnd.microsoft.iothub.json
Host: <config.host>
{"body":"<Base64 Message1>","properties":{"<key>":"<value>"}},
{"body":"<Base64 Message1>"}...
```]*/
var path = azure_iot_common_1.endpoint.eventPath(config.deviceId);
var httpHeaders = {
'iothub-to': path,
'Content-Type': 'application/vnd.microsoft.iothub.json',
'User-Agent': 'azure-iot-device/' + packageJson.version
};
this._insertAuthHeaderIfNecessary(httpHeaders);
/*Codes_SRS_NODE_DEVICE_HTTP_16_013: [If using x509 authentication the `Authorization` header shall not be set and the x509 parameters shall instead be passed to the underlying transpoort.]*/
var request = this._http.buildRequest('POST', path + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders, config.host, config.x509, handleResponse(done));
var body = constructBatchBody(messages);
request.write(body);
request.end();
var _this = this;
/*Codes_SRS_NODE_DEVICE_HTTP_16_032: [All HTTP requests shall obtain the credentials necessary to execute the request by calling `getDeviceCredentials` on the `AuthenticationProvider` object passed to the `Http` constructor.]*/
this._authenticationProvider.getDeviceCredentials(function (err, config) {
if (err) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_033: [if the `getDeviceCredentials` fails with an error, the Http request shall call its callback with that error]*/
done(err);
}
else {
var constructBatchBody = function (messages) {
var body = '[';
messages.forEach(function (message, index) {
var buffMsg = new Buffer(message.getData());
if (index > 0)
body += ',';
body += '{\"body\":\"' + buffMsg.toString('base64') + '\"';
// Get the properties
var propertyIdx = 0;
var property = ',\"properties\":{';
for (propertyIdx = 0; propertyIdx < message.properties.count(); propertyIdx++) {
if (propertyIdx > 0)
property += ',';
var propItem = message.properties.getItem(propertyIdx);
/*Codes_SRS_NODE_DEVICE_HTTP_13_002: [ sendEventBatch shall prefix the key name for all message properties with the string iothub-app. ]*/
property += '\"' + MESSAGE_PROP_HEADER_PREFIX + propItem.key + '\":\"' + propItem.value + '\"';
}
if (propertyIdx > 0) {
property += '}';
body += property;
}
body += '}';
});
body += ']';
return body;
};
/*Codes_SRS_NODE_DEVICE_HTTP_05_003: [The `sendEventBatch` method shall construct an HTTP request using information supplied by the caller, as follows:
```
POST <config.host>/devices/<config.deviceId>/messages/events?api-version=<version> HTTP/1.1
iothub-to: /devices/<config.deviceId>/messages/events
User-Agent: <version string>
Content-Type: application/vnd.microsoft.iothub.json
Host: <config.host>
{"body":"<Base64 Message1>","properties":{"<key>":"<value>"}},
{"body":"<Base64 Message1>"}...
```]*/
var path = azure_iot_common_1.endpoint.eventPath(config.deviceId);
var httpHeaders = {
'iothub-to': path,
'Content-Type': 'application/vnd.microsoft.iothub.json',
'User-Agent': 'azure-iot-device/' + packageJson.version
};
_this._insertAuthHeaderIfNecessary(httpHeaders, config);
/*Codes_SRS_NODE_DEVICE_HTTP_16_013: [If using x509 authentication the `Authorization` header shall not be set and the x509 parameters shall instead be passed to the underlying transpoort.]*/
var request = _this._http.buildRequest('POST', path + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders, config.host, config.x509, handleResponse(done));
var body = constructBatchBody(messages);
request.write(body);
request.end();
}
});
};

@@ -268,7 +286,7 @@ /**

if (options.hasOwnProperty('cert')) {
this._config.x509 = {
this._authenticationProvider.setX509Options({
cert: options.cert,
key: options.key,
passphrase: options.passphrase
};
});
}

@@ -313,31 +331,41 @@ var calldoneifspecified = function (err) {

var _this = this;
var path = azure_iot_common_1.endpoint.messagePath(this._config.deviceId);
var httpHeaders = {
'iothub-to': path,
'User-Agent': 'azure-iot-device/' + packageJson.version
};
this._insertAuthHeaderIfNecessary(httpHeaders);
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_017: [If opts.drain is true all messages in the queue should be pulled at once.]*/
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_018: [If opts.drain is false, only one message shall be received at a time]*/
var drainRequester = new events_1.EventEmitter();
drainRequester.on('nextRequest', function () {
var request = _this._http.buildRequest('GET', path + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders, _this._config.host, _this._config.x509, function (err, body, res) {
if (!err) {
if (body) {
var msg = _this._http.toMessage(res, body);
if (_this._opts.drain) {
drainRequester.emit('nextRequest');
/*Codes_SRS_NODE_DEVICE_HTTP_16_032: [All HTTP requests shall obtain the credentials necessary to execute the request by calling `getDeviceCredentials` on the `AuthenticationProvider` object passed to the `Http` constructor.]*/
this._authenticationProvider.getDeviceCredentials(function (err, config) {
if (err) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_033: [if the `getDeviceCredentials` fails with an error, the Http request shall call its callback with that error]*/
debug('Error while receiving: ' + err.toString());
_this.emit('error', err);
}
else {
var path_1 = azure_iot_common_1.endpoint.messagePath(config.deviceId);
var httpHeaders_1 = {
'iothub-to': path_1,
'User-Agent': 'azure-iot-device/' + packageJson.version
};
_this._insertAuthHeaderIfNecessary(httpHeaders_1, config);
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_017: [If opts.drain is true all messages in the queue should be pulled at once.]*/
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_018: [If opts.drain is false, only one message shall be received at a time]*/
var drainRequester_1 = new events_1.EventEmitter();
drainRequester_1.on('nextRequest', function () {
var request = _this._http.buildRequest('GET', path_1 + azure_iot_common_1.endpoint.versionQueryString(), httpHeaders_1, config.host, config.x509, function (err, body, res) {
if (!err) {
if (body) {
var msg = _this._http.toMessage(res, body);
if (_this._opts.drain) {
drainRequester_1.emit('nextRequest');
}
_this.emit('message', msg);
}
}
_this.emit('message', msg);
}
}
else {
err.response = res;
err.responseBody = body;
_this.emit('error', err);
}
});
request.end();
else {
err.response = res;
err.responseBody = body;
_this.emit('error', err);
}
});
request.end();
});
drainRequester_1.emit('nextRequest');
}
});
drainRequester.emit('nextRequest');
};

@@ -393,3 +421,3 @@ /**

/*Codes_SRS_NODE_DEVICE_HTTP_16_006: [The updateSharedAccessSignature method shall save the new shared access signature given as a parameter to its configuration.] */
this._config.sharedAccessSignature = sharedAccessSignature;
this._authenticationProvider.updateSharedAccessSignature(sharedAccessSignature);
/*Codes_SRS_NODE_DEVICE_HTTP_16_007: [The updateSharedAccessSignature method shall call the `done` callback with a null error object and a SharedAccessSignatureUpdated object as a result, indicating that the client does not need to reestablish the transport connection.] */

@@ -507,4 +535,4 @@ done(null, new azure_iot_common_1.results.SharedAccessSignatureUpdated(false));

};
Http.prototype._insertAuthHeaderIfNecessary = function (headers) {
if (!this._config.x509) {
Http.prototype._insertAuthHeaderIfNecessary = function (headers, credentials) {
if (this._authenticationProvider.type === azure_iot_common_1.AuthenticationType.Token) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_012: [If using a shared access signature for authentication, the following additional header should be used in the HTTP request:

@@ -515,3 +543,3 @@ ```

/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_030: [If using x509 authentication the `Authorization` header shall not be set and the x509 parameters shall instead be passed to the underlying transpoort.]*/
headers.Authorization = this._config.sharedAccessSignature.toString();
headers.Authorization = credentials.sharedAccessSignature.toString();
}

@@ -537,57 +565,66 @@ };

Http.prototype._sendFeedback = function (action, message, done) {
var config = this._config;
var method;
var resultConstructor = null;
var path = azure_iot_common_1.endpoint.feedbackPath(config.deviceId, message.lockToken);
var httpHeaders = {
'If-Match': message.lockToken,
'User-Agent': 'azure-iot-device/' + packageJson.version
};
this._insertAuthHeaderIfNecessary(httpHeaders);
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_009: [abandon shall construct an HTTP request using information supplied by the caller, as follows:
POST <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>/abandon?api-version=<version> HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]
*/
if (action === 'abandon') {
path += '/abandon' + azure_iot_common_1.endpoint.versionQueryString();
method = 'POST';
resultConstructor = azure_iot_common_1.results.MessageAbandoned;
}
else if (action === 'reject') {
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_010: [reject shall construct an HTTP request using information supplied by the caller, as follows:
DELETE <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>?api-version=<version>&reject HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]*/
path += azure_iot_common_1.endpoint.versionQueryString() + '&reject';
method = 'DELETE';
resultConstructor = azure_iot_common_1.results.MessageRejected;
}
else {
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_011: [complete shall construct an HTTP request using information supplied by the caller, as follows:
DELETE <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>?api-version=<version> HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]*/
path += azure_iot_common_1.endpoint.versionQueryString();
method = 'DELETE';
resultConstructor = azure_iot_common_1.results.MessageCompleted;
}
/*Codes_SRS_NODE_DEVICE_HTTP_05_008: [If any Http method encounters an error before it can send the request, it shall invoke the done callback function and pass the standard JavaScript Error object with a text description of the error (err.message).]*/
var request = this._http.buildRequest(method, path, httpHeaders, config.host, this._config.x509, function (err, body, response) {
if (done) {
if (!err && response.statusCode === 204) {
var result = new resultConstructor(response);
done(null, result);
var _this = this;
/*Codes_SRS_NODE_DEVICE_HTTP_16_032: [All HTTP requests shall obtain the credentials necessary to execute the request by calling `getDeviceCredentials` on the `AuthenticationProvider` object passed to the `Http` constructor.]*/
this._authenticationProvider.getDeviceCredentials(function (err, config) {
if (err) {
/*Codes_SRS_NODE_DEVICE_HTTP_16_033: [if the `getDeviceCredentials` fails with an error, the Http request shall call its callback with that error]*/
done(err);
}
else {
var method = void 0;
var resultConstructor_1 = null;
var path = azure_iot_common_1.endpoint.feedbackPath(config.deviceId, message.lockToken);
var httpHeaders = {
'If-Match': message.lockToken,
'User-Agent': 'azure-iot-device/' + packageJson.version
};
_this._insertAuthHeaderIfNecessary(httpHeaders, config);
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_009: [abandon shall construct an HTTP request using information supplied by the caller, as follows:
POST <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>/abandon?api-version=<version> HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]
*/
if (action === 'abandon') {
path += '/abandon' + azure_iot_common_1.endpoint.versionQueryString();
method = 'POST';
resultConstructor_1 = azure_iot_common_1.results.MessageAbandoned;
}
else if (action === 'reject') {
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_010: [reject shall construct an HTTP request using information supplied by the caller, as follows:
DELETE <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>?api-version=<version>&reject HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]*/
path += azure_iot_common_1.endpoint.versionQueryString() + '&reject';
method = 'DELETE';
resultConstructor_1 = azure_iot_common_1.results.MessageRejected;
}
else {
err.response = response;
err.responseBody = body;
done(err);
/*Codes_SRS_NODE_DEVICE_HTTP_RECEIVER_16_011: [complete shall construct an HTTP request using information supplied by the caller, as follows:
DELETE <config.host>/devices/<config.deviceId>/messages/devicebound/<lockToken>?api-version=<version> HTTP/1.1
Authorization: <config.sharedAccessSignature>
If-Match: <lockToken>
Host: <config.host>]*/
path += azure_iot_common_1.endpoint.versionQueryString();
method = 'DELETE';
resultConstructor_1 = azure_iot_common_1.results.MessageCompleted;
}
/*Codes_SRS_NODE_DEVICE_HTTP_05_008: [If any Http method encounters an error before it can send the request, it shall invoke the done callback function and pass the standard JavaScript Error object with a text description of the error (err.message).]*/
var request = _this._http.buildRequest(method, path, httpHeaders, config.host, config.x509, function (err, body, response) {
if (done) {
if (!err && response.statusCode === 204) {
var result = new resultConstructor_1(response);
done(null, result);
}
else {
err.response = response;
err.responseBody = body;
done(err);
}
}
});
request.end();
}
});
request.end();
};

@@ -594,0 +631,0 @@ /** @private

{
"name": "azure-iot-device-http",
"version": "1.2.3",
"version": "1.3.0",
"description": "HTTP transport for Azure IoT device SDK",

@@ -10,5 +10,5 @@ "author": "Microsoft Corporation",

"dependencies": {
"azure-iot-common": "1.2.2",
"azure-iot-device": "1.2.2",
"azure-iot-http-base": "1.2.2",
"azure-iot-common": "1.3.0",
"azure-iot-device": "1.3.0",
"azure-iot-http-base": "1.3.0",
"debug": "^3.1.0",

@@ -18,3 +18,3 @@ "node-crontab": "^0.0.8"

"devDependencies": {
"azure-iothub": "1.2.1",
"azure-iothub": "1.2.3",
"chai": "^4.1.2",

@@ -21,0 +21,0 @@ "istanbul": "^0.4.4",

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