Socket
Socket
Sign inDemoInstall

wittycli

Package Overview
Dependencies
80
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.8 to 0.1.0

66

lib/commands/test.js

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

const fs_1 = require("fs");
const lodash_1 = require("lodash");
const chalk_1 = tslib_1.__importDefault(require("chalk"));

@@ -20,2 +21,3 @@ const bottleneck_1 = tslib_1.__importDefault(require("bottleneck"));

});
// testing intents
const actualIntent = result.intents[0];

@@ -26,3 +28,3 @@ const expectedIntent = testRule.intents[0];

testRule,
error: new Error(`Test "${text}" returned incorrect intent. Expected :"${expectedIntent.name}". Actual: "${actualIntent.name}"`),
error: new Error(`Test "${text}" returned incorrect intent. Expected: "${expectedIntent.name}". Actual: "${actualIntent.name}"`),
};

@@ -33,5 +35,63 @@ }

testRule,
error: new Error(`Test "${text}" confidence degraded. Expected :"${expectedIntent.confidence}". Actual: "${actualIntent.confidence}"`),
error: new Error(`Test "${text}" confidence degraded. Expected: "${expectedIntent.confidence}". Actual: "${actualIntent.confidence}"`),
};
}
// testing entities
if (!testRule.entities) {
// no need to test entities if they are not provided.
return { testRule };
}
const actualEntities = result.entities;
const expectedEntities = testRule.entities;
const actualEntitiesKeys = Object.keys(actualEntities);
const expectedEntitiesKeys = Object.keys(expectedEntities);
const actualEntitiesJSON = JSON.stringify(actualEntities);
const expectedEntitiesJSON = JSON.stringify(expectedEntities);
const entitiesErrorMessagePart = `Expected entitites: ${expectedEntitiesJSON}.\nActual entities: ${actualEntitiesJSON}`;
if (actualEntitiesKeys.length !== expectedEntitiesKeys.length) {
return {
testRule,
error: new Error(`Test "${text}" entities mismatch. Different amount of entity types. Expected :"${expectedEntitiesKeys.length}". Actual: "${actualEntitiesKeys.length}.\n${entitiesErrorMessagePart}"`),
};
}
for (const actualEntityKey of actualEntitiesKeys) {
if (!(actualEntityKey in expectedEntities)) {
return {
testRule,
error: new Error(`Test "${text}" entities mismatch. ${actualEntityKey} is not in expected entities ${JSON.stringify(expectedEntitiesKeys)}. Expected :"${expectedEntitiesKeys.length}". Actual: "${actualEntitiesKeys.length}.\n${entitiesErrorMessagePart}"`),
};
}
const actualEntityList = actualEntities[actualEntityKey];
const expectedEntityList = expectedEntities[actualEntityKey];
if (actualEntityList.length !== expectedEntityList.length) {
return {
testRule,
error: new Error(`Test "${text}" entities mismatch. Entity ${actualEntityKey} has incorect amount of entities. Expected :"${expectedEntityList.length}". Actual: "${actualEntityList.length}.\n${entitiesErrorMessagePart}"`),
};
}
for (let i = 0; i < actualEntityList.length; i++) {
const actualEntity = actualEntityList[i];
const expectedEntity = expectedEntityList[i];
for (const expectedEntityField of Object.keys(expectedEntity)) {
/* eslint max-depth: ["error", 6] */
if (expectedEntityField === 'confidence') {
if (actualEntity.confidence < expectedEntity.confidence) {
return {
testRule,
error: new Error(`Test "${text}" entities mismatch. Confidence for entity ${actualEntityKey} degraded. Expected: "${expectedEntity.confidence}". Actual: "${actualEntity.confidence}"\n${entitiesErrorMessagePart}`),
};
}
continue;
}
const actualEntityFieldValue = actualEntity[expectedEntityField];
const expectedEntityFieldValue = expectedEntity[expectedEntityField];
if (!lodash_1.isEqual(actualEntityFieldValue, expectedEntityFieldValue)) {
return {
testRule,
error: new Error(`Test "${text}" entities mismatch. Field "${expectedEntityField}" for entity "${actualEntityKey}" has unexpected value. Expected: "${JSON.stringify(expectedEntityFieldValue)}". Actual: "${JSON.stringify(actualEntityFieldValue)}"\n${entitiesErrorMessagePart}`),
};
}
}
}
}
return { testRule };

@@ -92,3 +152,3 @@ }

exports.default = Test;
Test.description = 'Tests the wittycli app with the provided file of expected utterances.';
Test.description = 'Tests the wittycli app with the provided file of expected utterances and entities.';
Test.examples = [`$ wittycli test --file="./example/test.json"`];

@@ -95,0 +155,0 @@ Test.flags = Object.assign(Object.assign({}, commonFlagsWithoutDot), { file: command_1.flags.string({

@@ -49,2 +49,5 @@ /// <reference types="node" />

app_id: string;
entities: {
[key: string]: MessageGetEntity[];
};
}

@@ -51,0 +54,0 @@ export interface AppsPostBody {

2

oclif.manifest.json

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

{"version":"0.0.8","commands":{"export":{"id":"export","description":"Exports Get a URL where you can download a ZIP file containing all of your app data. This ZIP file can be used to create a new app with the same data.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli export --output=\"./app.zip\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"output":{"name":"output","type":"option","char":"o","description":"Path of the output file. If set this command will download a ZIP file to a provided path.","required":false},"dir":{"name":"dir","type":"option","char":"d","description":"Path of the output directory. If set this command will download a ZIP file and unzip to a provided directory.","required":false}},"args":[]},"import":{"id":"import","description":"Create a new app with all the app data from the exported app.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli import --name=witapp --private --file ./app.zip"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"file":{"name":"file","type":"option","char":"f","description":"Path of the import file. A ZIP file containing all of your app data.","required":false},"dir":{"name":"dir","type":"option","char":"d","description":"Path of the import directory. If set this command will ZIP provided directory and import it.","required":false},"name":{"name":"name","type":"option","char":"n","description":"Name of the new app.","required":true},"private":{"name":"private","type":"boolean","char":"p","description":"Private if flag provided.","required":false,"allowNo":false},"wait":{"name":"wait","type":"boolean","char":"w","description":"If true the cli will wait for the app training to complete via long polling.","required":false,"allowNo":false}},"args":[]},"message":{"id":"message","description":"Returns the extracted meaning from a sentence, based on the app data.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli message --query=\"Set temperature to 70 degrees\" --numberofintents=8"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"query":{"name":"query","type":"option","char":"q","description":"User's query, between 0 and 280 characters.","required":true},"tag":{"name":"tag","type":"option","char":"t","description":"A specific tag you want to use for the query. See GET /apps/:app/tags.","required":false},"numberofintents":{"name":"numberofintents","type":"option","char":"n","description":"The maximum number of n-best intents and traits you want to get back. The default is 1, and the maximum is 8.","required":false,"default":1}},"args":[]},"test":{"id":"test","description":"Tests the wittycli app with the provided file of expected utterances.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli test --file=\"./example/test.json\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"file":{"name":"file","type":"option","char":"f","description":"Filepath of the file with utterances in format of the Array<ResponseOfTheMessageAPI>","required":true},"parallel":{"name":"parallel","type":"option","char":"p","description":"Max amount of parallel requests","required":false,"default":10}},"args":[]},"apps:post":{"id":"apps:post","description":"Creates a new app for an existing user.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli apps create --name=witapp --lang=en --private --timezone=Europe/Brussels"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"name":{"name":"name","type":"option","char":"n","description":"Name of the new app.","required":true},"lang":{"name":"lang","type":"option","char":"l","description":"Language code, in the ISO 639-1 format.","required":true},"private":{"name":"private","type":"boolean","char":"p","description":"Private if flag provided.","required":false,"allowNo":false},"timezone":{"name":"timezone","type":"option","char":"t","description":"Default timezone of your app. Defaults to America/Los_Angeles.","required":false}},"args":[]}}}
{"version":"0.1.0","commands":{"export":{"id":"export","description":"Exports Get a URL where you can download a ZIP file containing all of your app data. This ZIP file can be used to create a new app with the same data.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli export --output=\"./app.zip\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"output":{"name":"output","type":"option","char":"o","description":"Path of the output file. If set this command will download a ZIP file to a provided path.","required":false},"dir":{"name":"dir","type":"option","char":"d","description":"Path of the output directory. If set this command will download a ZIP file and unzip to a provided directory.","required":false}},"args":[]},"import":{"id":"import","description":"Create a new app with all the app data from the exported app.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli import --name=witapp --private --file ./app.zip"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"file":{"name":"file","type":"option","char":"f","description":"Path of the import file. A ZIP file containing all of your app data.","required":false},"dir":{"name":"dir","type":"option","char":"d","description":"Path of the import directory. If set this command will ZIP provided directory and import it.","required":false},"name":{"name":"name","type":"option","char":"n","description":"Name of the new app.","required":true},"private":{"name":"private","type":"boolean","char":"p","description":"Private if flag provided.","required":false,"allowNo":false},"wait":{"name":"wait","type":"boolean","char":"w","description":"If true the cli will wait for the app training to complete via long polling.","required":false,"allowNo":false}},"args":[]},"message":{"id":"message","description":"Returns the extracted meaning from a sentence, based on the app data.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli message --query=\"Set temperature to 70 degrees\" --numberofintents=8"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"query":{"name":"query","type":"option","char":"q","description":"User's query, between 0 and 280 characters.","required":true},"tag":{"name":"tag","type":"option","char":"t","description":"A specific tag you want to use for the query. See GET /apps/:app/tags.","required":false},"numberofintents":{"name":"numberofintents","type":"option","char":"n","description":"The maximum number of n-best intents and traits you want to get back. The default is 1, and the maximum is 8.","required":false,"default":1}},"args":[]},"test":{"id":"test","description":"Tests the wittycli app with the provided file of expected utterances and entities.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli test --file=\"./example/test.json\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"file":{"name":"file","type":"option","char":"f","description":"Filepath of the file with utterances in format of the Array<ResponseOfTheMessageAPI>","required":true},"parallel":{"name":"parallel","type":"option","char":"p","description":"Max amount of parallel requests","required":false,"default":10}},"args":[]},"apps:post":{"id":"apps:post","description":"Creates a new app for an existing user.","pluginName":"wittycli","pluginType":"core","aliases":[],"examples":["$ wittycli apps create --name=witapp --lang=en --private --timezone=Europe/Brussels"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"auth":{"name":"auth","type":"option","char":"a","description":"Wit.ai uses OAuth2 as an authorization layer. As such, every API request must contain an Authorize HTTP header with a token. Access tokens are app and user specific. Please do not share the token with anyone, nor post it publicly. You can obtain one in Settings for your app. Alternatively you can set WIT_AUTH_TOKEN environment variable.","required":true},"version":{"name":"version","type":"option","char":"v","description":"Every request requires a version parameter either in the URL or in the headers. This parameter is a date that represents the \"version\" of the Wit API. We'll try to minimize backwards-incompatible changes we make to the API, but when we do make these changes, this parameter will allow you to continue to use the API as before and give you time to transition to the new implementation if you want. As of June 1st, 2014, requests that do not include a version parameter will hit the latest version of our API.","required":false},"dot":{"name":"dot","type":"option","description":"Use dot notation (https://github.com/rhalff/dot-object#pick-a-value-using-dot-notation) to retrieve a value from json response.","required":false},"name":{"name":"name","type":"option","char":"n","description":"Name of the new app.","required":true},"lang":{"name":"lang","type":"option","char":"l","description":"Language code, in the ISO 639-1 format.","required":true},"private":{"name":"private","type":"boolean","char":"p","description":"Private if flag provided.","required":false,"allowNo":false},"timezone":{"name":"timezone","type":"option","char":"t","description":"Default timezone of your app. Defaults to America/Los_Angeles.","required":false}},"args":[]}}}
{
"name": "wittycli",
"description": "Wit.ai CLI",
"version": "0.0.8",
"version": "0.1.0",
"bin": {

@@ -16,2 +16,3 @@ "wittycli": "./bin/run"

"dot-object": "^2.1.4",
"lodash": "^4.17.20",
"node-fetch": "^2.6.1",

@@ -18,0 +19,0 @@ "tslib": "^1.14.1"

@@ -22,3 +22,3 @@ wittycli

$ wittycli (-v|--version|version)
wittycli/0.0.8 win32-x64 node-v12.19.0
wittycli/0.1.0 win32-x64 node-v12.19.0
$ wittycli --help [COMMAND]

@@ -84,3 +84,3 @@ USAGE

_See code: [src\commands\apps\post.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.0.8/src\commands\apps\post.ts)_
_See code: [src\commands\apps\post.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.1.0/src\commands\apps\post.ts)_

@@ -126,3 +126,3 @@ ## `wittycli export`

_See code: [src\commands\export.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.0.8/src\commands\export.ts)_
_See code: [src\commands\export.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.1.0/src\commands\export.ts)_

@@ -194,3 +194,3 @@ ## `wittycli help [COMMAND]`

_See code: [src\commands\import.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.0.8/src\commands\import.ts)_
_See code: [src\commands\import.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.1.0/src\commands\import.ts)_

@@ -240,7 +240,7 @@ ## `wittycli message`

_See code: [src\commands\message.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.0.8/src\commands\message.ts)_
_See code: [src\commands\message.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.1.0/src\commands\message.ts)_
## `wittycli test`
Tests the wittycli app with the provided file of expected utterances.
Tests the wittycli app with the provided file of expected utterances and entities.

@@ -278,3 +278,3 @@ ```

_See code: [src\commands\test.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.0.8/src\commands\test.ts)_
_See code: [src\commands\test.ts](https://github.com/ShyykoSerhiy/wittycli/blob/v0.1.0/src\commands\test.ts)_
<!-- commandsstop -->
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc