Socket
Socket
Sign inDemoInstall

@platform/cell.client

Package Overview
Dependencies
Maintainers
1
Versions
271
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@platform/cell.client - npm Package Compare versions

Comparing version 0.3.66 to 0.3.67

lib/Client.http/HttpClientCellDb.d.ts

42

lib/Client.http/HttpClientCell.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpClientCell = void 0;
var tslib_1 = require("tslib");
var common_1 = require("../common");
var HttpClientCellFile_1 = require("./HttpClientCellFile");
var HttpClientCellDb_1 = require("./HttpClientCellDb");
var HttpClientCellFs_1 = require("./HttpClientCellFs");

@@ -11,4 +9,4 @@ var HttpClientCellLinks_1 = require("./HttpClientCellLinks");

var uri = args.uri, urls = args.urls, http = args.http;
var file;
var fs;
var db;
var links;

@@ -20,6 +18,6 @@ var api = {

},
get file() {
if (file)
return file;
return (file = HttpClientCellFile_1.HttpClientCellFile({ parent: parent, urls: urls, http: http }));
get db() {
if (db)
return db;
return (db = HttpClientCellDb_1.HttpClientCellDb({ parent: parent, urls: urls, http: http }));
},

@@ -29,3 +27,3 @@ get fs() {

return fs;
return (fs = HttpClientCellFs_1.HttpClientCellFs.create({ parent: parent, urls: urls, http: http }));
return (fs = HttpClientCellFs_1.HttpClientCellFs({ parent: parent, urls: urls, http: http }));
},

@@ -39,29 +37,7 @@ get links() {

exists: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, http.get(api.url.info.toString())];
case 1:
res = _a.sent();
return [2, res.status.toString().startsWith('2')];
}
});
});
return api.db.exists();
},
info: function (options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var url, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
url = api.url.info.query(options).toString();
return [4, http.get(url)];
case 1:
res = _a.sent();
return [2, common_1.util.fromHttpResponse(res).toClientResponse()];
}
});
});
return api.db.read(options);
},

@@ -68,0 +44,0 @@ toString: function () { return uri.toString(); },

@@ -6,2 +6,3 @@ import { t } from '../common';

http: t.IHttp;
path: string;
}): t.IHttpClientCellFile;

@@ -7,91 +7,87 @@ "use strict";

function HttpClientCellFile(args) {
var parent = args.parent, urls = args.urls, http = args.http;
var parent = args.parent, urls = args.urls, http = args.http, path = args.path;
var api = {
name: function (path) {
var file = {
info: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var linkRes, link, url, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, getCellLinkByFilename(parent, path)];
case 1:
linkRes = _a.sent();
if (linkRes.error) {
return [2, linkRes.error];
}
if (!linkRes.link) {
throw new Error("Link should exist.");
}
link = linkRes.link;
url = urls.file(link.uri).info;
return [4, http.get(url.toString())];
case 2:
res = _a.sent();
return [2, common_1.util.fromHttpResponse(res).toClientResponse()];
path: path,
info: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var linkRes, link, url, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, getCellLinkByFilename(parent, path)];
case 1:
linkRes = _a.sent();
if (linkRes.error) {
return [2, linkRes.error];
}
});
});
},
exists: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var info;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, file.info()];
case 1:
info = _a.sent();
return [2, info.ok && info.body.exists];
if (!linkRes.link) {
throw new Error("Link should exist.");
}
});
});
},
download: function (options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var expires, linkRes, link, hash, url, res, mime_1, bodyType, message, httpError, error;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
expires = options.expires;
return [4, getCellLinkByFilename(parent, path)];
case 1:
linkRes = _a.sent();
if (linkRes.error)
return [2, linkRes.error];
if (!linkRes.link) {
throw new Error("Link should exist.");
}
link = linkRes.link;
hash = link.query.hash || undefined;
url = parent.url.file
.byFileUri(link.uri.toString(), link.ext)
.query({ hash: hash, expires: expires })
.toString();
return [4, http.get(url)];
case 2:
res = _a.sent();
if (res.ok) {
mime_1 = (res.headers['content-type'] || '').toString().trim();
bodyType = toBodyType(mime_1);
return [2, common_1.util.fromHttpResponse(res).toClientResponse({ bodyType: bodyType })];
}
else {
message = "Failed while downloading file \"" + parent.uri.toString() + "\".";
httpError = res.contentType.is.json ? res.json : undefined;
if (httpError) {
error = message + " " + httpError.message;
return [2, common_1.util.toError(res.status, httpError.type, error)];
}
else {
return [2, common_1.util.toError(res.status, common_1.ERROR.HTTP.SERVER, message)];
}
}
return [2];
link = linkRes.link;
url = urls.file(link.uri).info;
return [4, http.get(url.toString())];
case 2:
res = _a.sent();
return [2, common_1.util.fromHttpResponse(res).toClientResponse()];
}
});
});
},
exists: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var info;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, api.info()];
case 1:
info = _a.sent();
return [2, info.ok && info.body.exists];
}
});
});
},
download: function (options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var expires, linkRes, link, hash, url, res, mime_1, bodyType, message, httpError, error;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
expires = options.expires;
return [4, getCellLinkByFilename(parent, path)];
case 1:
linkRes = _a.sent();
if (linkRes.error)
return [2, linkRes.error];
if (!linkRes.link) {
throw new Error("Link should exist.");
}
});
});
},
};
return file;
link = linkRes.link;
hash = link.query.hash || undefined;
url = parent.url.file
.byFileUri(link.uri.toString(), link.ext)
.query({ hash: hash, expires: expires })
.toString();
return [4, http.get(url)];
case 2:
res = _a.sent();
if (res.ok) {
mime_1 = (res.headers['content-type'] || '').toString().trim();
bodyType = toBodyType(mime_1);
return [2, common_1.util.fromHttpResponse(res).toClientResponse({ bodyType: bodyType })];
}
else {
message = "Failed while downloading file \"" + parent.uri.toString() + "\".";
httpError = res.contentType.is.json ? res.json : undefined;
if (httpError) {
error = message + " " + httpError.message;
return [2, common_1.util.toError(res.status, httpError.type, error)];
}
else {
return [2, common_1.util.toError(res.status, common_1.ERROR.HTTP.SERVER, message)];
}
}
return [2];
}
});
});
},

@@ -98,0 +94,0 @@ };

import { t } from '../common';
declare type IClientCellFsArgs = {
export declare function HttpClientCellFs(args: {
parent: t.IHttpClientCell;
urls: t.IUrls;
http: t.IHttp;
};
export declare class HttpClientCellFs implements t.IHttpClientCellFs {
static create(args: IClientCellFsArgs): t.IHttpClientCellFs;
private static parsePath;
private constructor();
private readonly args;
private readonly uri;
urls(): Promise<t.IHttpClientResponse<t.IHttpClientCellFileUrl[]>>;
map(): Promise<t.IHttpClientResponse<{
[key: string]: t.IFileData | undefined;
}>>;
list(options?: {
filter?: string;
}): Promise<t.IHttpClientResponse<t.IHttpClientFileData[]>>;
upload(input: t.IHttpClientCellFileUpload | t.IHttpClientCellFileUpload[], options?: {
changes?: boolean;
}): t.IHttpClientCellFsUploadPromise;
delete(filename: string | string[]): Promise<t.IHttpClientResponse<t.IResDeleteCellFsData>>;
unlink(filename: string | string[]): Promise<t.IHttpClientResponse<t.IResDeleteCellFsData>>;
copy(files: t.IHttpClientCellFileCopy | t.IHttpClientCellFileCopy[], options?: t.IHttpClientCellFsCopyOptions): Promise<t.IHttpClientResponse<t.IResPostCellFsCopyData>>;
private base;
}
export {};
}): t.IHttpClientCellFs;

@@ -6,134 +6,14 @@ "use strict";

var common_1 = require("../common");
var HttpClientCellFile_1 = require("./HttpClientCellFile");
var HttpClientCellFs_copy_1 = require("./HttpClientCellFs.copy");
var HttpClientCellFs_delete_1 = require("./HttpClientCellFs.delete");
var HttpClientCellFs_upload_1 = require("./HttpClientCellFs.upload");
var HttpClientCellFs_delete_1 = require("./HttpClientCellFs.delete");
var HttpClientCellFs_copy_1 = require("./HttpClientCellFs.copy");
var HttpClientCellFs = (function () {
function HttpClientCellFs(args) {
this.args = args;
this.uri = args.parent.uri;
}
HttpClientCellFs.create = function (args) {
return new HttpClientCellFs(args);
};
HttpClientCellFs.parsePath = function (path) {
var index = path.lastIndexOf('/');
var filename = index < 0 ? path : path.substring(index + 1);
var dir = index < 0 ? '' : path.substring(0, index);
return { path: path, filename: filename, dir: dir };
};
HttpClientCellFs.prototype.urls = function () {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getError, base, ok, status, error, toUrl, body;
var _this = this;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
getError = function () { return "Failed to get file URLs for [" + _this.uri.toString() + "]"; };
return [4, this.base({ getError: getError })];
case 1:
base = _b.sent();
ok = base.ok, status = base.status, error = base.error;
if (!ok) {
return [2, common_1.util.toClientResponse(status, {}, { error: error })];
}
toUrl = function (args) {
var path = args.path, uri = args.uri, url = args.url;
var _a = HttpClientCellFs.parsePath(path), filename = _a.filename, dir = _a.dir;
var res = { uri: uri, filename: filename, dir: dir, path: path, url: url };
return res;
};
body = (_a = base.body.urls) === null || _a === void 0 ? void 0 : _a.files.map(function (item) { return toUrl(item); });
return [2, common_1.util.toClientResponse(status, body || [])];
}
});
});
};
HttpClientCellFs.prototype.map = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getError, base, ok, status, body, error;
var _this = this;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
getError = function () { return "Failed to get file map for [" + _this.uri.toString() + "]"; };
return [4, this.base({ getError: getError })];
case 1:
base = _a.sent();
ok = base.ok, status = base.status;
body = ok ? base.body.files : {};
error = base.error;
return [2, common_1.util.toClientResponse(status, body, { error: error })];
}
});
});
};
HttpClientCellFs.prototype.list = function (options) {
var _a;
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var filter, getError, base, status_1, body_1, error, urls, map, ns, body;
var _this = this;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
filter = options.filter;
getError = function () { return "Failed to get file list for [" + _this.uri.toString() + "]"; };
return [4, this.base({ getError: getError, filter: filter })];
case 1:
base = _b.sent();
if (!base.ok) {
status_1 = base.status;
body_1 = {};
error = base.error;
return [2, common_1.util.toClientResponse(status_1, body_1, { error: error })];
}
urls = ((_a = base.body.urls) === null || _a === void 0 ? void 0 : _a.files) || [];
map = base.body.files || {};
ns = this.uri.ns;
body = Object.keys(map).reduce(function (acc, fileid) {
var value = map[fileid];
if (value) {
var uri_1 = common_1.Schema.Uri.create.file(ns, fileid);
var url = urls.find(function (item) { return item.uri === uri_1; });
if (url) {
var _a = HttpClientCellFs.parsePath(url.path), path = _a.path, filename = _a.filename, dir = _a.dir;
acc.push(tslib_1.__assign({ uri: uri_1, path: path, filename: filename, dir: dir }, value));
}
}
return acc;
}, []);
return [2, common_1.util.toClientResponse(200, body)];
}
});
});
};
HttpClientCellFs.prototype.upload = function (input, options) {
if (options === void 0) { options = {}; }
var changes = options.changes;
var _a = this.args, http = _a.http, urls = _a.urls;
var cellUri = this.uri.toString();
return HttpClientCellFs_upload_1.uploadFiles({ input: input, http: http, urls: urls, cellUri: cellUri, changes: changes });
};
HttpClientCellFs.prototype.delete = function (filename) {
var http = this.args.http;
var urls = this.args.parent.url;
return HttpClientCellFs_delete_1.deleteFiles({ http: http, urls: urls, filename: filename, action: 'DELETE' });
};
HttpClientCellFs.prototype.unlink = function (filename) {
var http = this.args.http;
var urls = this.args.parent.url;
return HttpClientCellFs_delete_1.deleteFiles({ http: http, urls: urls, filename: filename, action: 'UNLINK' });
};
HttpClientCellFs.prototype.copy = function (files, options) {
if (options === void 0) { options = {}; }
var changes = options.changes, permission = options.permission;
var http = this.args.http;
var urls = this.args.parent.url;
return HttpClientCellFs_copy_1.copyFiles({ http: http, urls: urls, files: files, changes: changes, permission: permission });
};
HttpClientCellFs.prototype.base = function (args) {
function HttpClientCellFs(args) {
var _this = this;
var parent = args.parent, urls = args.urls, http = args.http;
var uri = parent.uri;
var getBase = function (args) {
if (args === void 0) { args = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var filter, getError, http, parent, url, files, status_2, type, message, body;
return tslib_1.__awaiter(_this, void 0, void 0, function () {
var filter, getError, url, files, status_1, type, message, body;
return tslib_1.__generator(this, function (_a) {

@@ -143,4 +23,2 @@ switch (_a.label) {

filter = args.filter, getError = args.getError;
http = this.args.http;
parent = this.args.parent;
url = parent.url.files.list.query({ filter: filter }).toString();

@@ -151,8 +29,8 @@ return [4, http.get(url)];

if (!files.ok) {
status_2 = files.status;
type = status_2 === 404 ? common_1.ERROR.HTTP.NOT_FOUND : common_1.ERROR.HTTP.SERVER;
status_1 = files.status;
type = status_1 === 404 ? common_1.ERROR.HTTP.NOT_FOUND : common_1.ERROR.HTTP.SERVER;
message = getError
? getError({ status: status_2 })
: "Failed to get files data for '" + this.uri.toString() + "'.";
return [2, common_1.util.toError(status_2, type, message)];
? getError({ status: status_1 })
: "Failed to get files data for '" + uri.toString() + "'.";
return [2, common_1.util.toError(status_1, type, message)];
}

@@ -165,4 +43,120 @@ body = files.json;

};
return HttpClientCellFs;
}());
var api = {
uri: uri,
toString: function () { return uri.toString(); },
file: function (path) {
return HttpClientCellFile_1.HttpClientCellFile({ parent: parent, urls: urls, http: http, path: path });
},
urls: function () {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getError, base, ok, status, error, body;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
getError = function () { return "Failed to get file URLs for [" + uri.toString() + "]"; };
return [4, getBase({ getError: getError })];
case 1:
base = _b.sent();
ok = base.ok, status = base.status, error = base.error;
if (!ok)
return [2, common_1.util.toClientResponse(status, {}, { error: error })];
body = (_a = base.body.urls) === null || _a === void 0 ? void 0 : _a.files.map(function (item) { return toFileUrl(item); });
return [2, common_1.util.toClientResponse(status, body || [])];
}
});
});
},
map: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var getError, base, ok, status, body, error;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
getError = function () { return "Failed to get file map for [" + uri.toString() + "]"; };
return [4, getBase({ getError: getError })];
case 1:
base = _a.sent();
ok = base.ok, status = base.status;
body = ok ? base.body.files : {};
error = base.error;
return [2, common_1.util.toClientResponse(status, body, { error: error })];
}
});
});
},
list: function (options) {
var _a;
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var filter, getError, base, status_2, body_1, error, urls, map, ns, body;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
filter = options.filter;
getError = function () { return "Failed to get file list for [" + uri.toString() + "]"; };
return [4, getBase({ getError: getError, filter: filter })];
case 1:
base = _b.sent();
if (!base.ok) {
status_2 = base.status;
body_1 = {};
error = base.error;
return [2, common_1.util.toClientResponse(status_2, body_1, { error: error })];
}
urls = ((_a = base.body.urls) === null || _a === void 0 ? void 0 : _a.files) || [];
map = base.body.files || {};
ns = uri.ns;
body = Object.keys(map).reduce(function (acc, fileid) {
var value = map[fileid];
if (value) {
var uri_1 = common_1.Schema.Uri.create.file(ns, fileid);
var url = urls.find(function (item) { return item.uri === uri_1; });
if (url) {
var _a = parsePath(url.path), path = _a.path, filename = _a.filename, dir = _a.dir;
acc.push(tslib_1.__assign({ uri: uri_1, path: path, filename: filename, dir: dir }, value));
}
}
return acc;
}, []);
return [2, common_1.util.toClientResponse(200, body)];
}
});
});
},
upload: function (input, options) {
if (options === void 0) { options = {}; }
var changes = options.changes;
var cellUri = uri.toString();
return HttpClientCellFs_upload_1.uploadFiles({ input: input, http: http, urls: urls, cellUri: cellUri, changes: changes });
},
delete: function (filename) {
var urls = parent.url;
return HttpClientCellFs_delete_1.deleteFiles({ http: http, urls: urls, filename: filename, action: 'DELETE' });
},
unlink: function (filename) {
var urls = parent.url;
return HttpClientCellFs_delete_1.deleteFiles({ http: http, urls: urls, filename: filename, action: 'UNLINK' });
},
copy: function (files, options) {
if (options === void 0) { options = {}; }
var changes = options.changes, permission = options.permission;
var urls = parent.url;
return HttpClientCellFs_copy_1.copyFiles({ http: http, urls: urls, files: files, changes: changes, permission: permission });
},
};
return api;
}
exports.HttpClientCellFs = HttpClientCellFs;
function parsePath(path) {
var index = path.lastIndexOf('/');
var filename = index < 0 ? path : path.substring(index + 1);
var dir = index < 0 ? '' : path.substring(0, index);
return { path: path, filename: filename, dir: dir };
}
var toFileUrl = function (args) {
var path = args.path, uri = args.uri, url = args.url;
var _a = parsePath(path), filename = _a.filename, dir = _a.dir;
var res = { uri: uri, filename: filename, dir: dir, path: path, url: url };
return res;
};

@@ -31,5 +31,6 @@ "use strict";

function toLink(args) {
var http = args.http, urls = args.urls, key = args.key, value = args.value;
var http = args.http, urls = args.urls, value = args.value;
var uri = common_1.Uri.parse(value);
var type = uri.parts.type;
var key = common_1.Schema.Ref.Links.parseKey(args.key).path;
if (type === 'FILE') {

@@ -36,0 +37,0 @@ var client_1;

@@ -13,2 +13,5 @@ "use strict";

var api = {
get uri() {
return uri.toString();
},
read: function () {

@@ -34,24 +37,19 @@ return tslib_1.__awaiter(this, void 0, void 0, function () {

},
write: function (input, options) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var list, links, ns;
var _a;
return tslib_1.__generator(this, function (_b) {
list = Array.isArray(input) ? input : [input];
links = list
.map(function (link) { return (tslib_1.__assign(tslib_1.__assign({}, link), { key: RefLinks.toKey(link.key) })); })
.reduce(function (acc, next) {
acc[next.key] = (next.value || '').trim();
return acc;
}, {});
ns = HttpClientNs_1.HttpClientNs({ uri: common_1.Uri.ns(uri.ns), urls: urls, http: http });
return [2, ns.write({ cells: (_a = {}, _a[uri.key] = { links: links }, _a) }, options)];
});
});
write: function (link, options) {
var _a;
var list = Array.isArray(link) ? link : [link];
var links = list
.map(function (link) { return (tslib_1.__assign(tslib_1.__assign({}, link), { key: RefLinks.toKey(link.key) })); })
.reduce(function (acc, next) {
acc[next.key] = (next.value || '').trim();
return acc;
}, {});
var ns = HttpClientNs_1.HttpClientNs({ uri: common_1.Uri.ns(uri.ns), urls: urls, http: http });
return ns.write({ cells: (_a = {}, _a[uri.key] = { links: links }, _a) }, options);
},
delete: function (input, options) {
delete: function (key, options) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var keys, links;
return tslib_1.__generator(this, function (_a) {
keys = Array.isArray(input) ? input : [input];
keys = Array.isArray(key) ? key : [key];
links = keys.map(function (key) { return ({ key: key, value: '' }); });

@@ -62,2 +60,19 @@ return [2, api.write(links, options)];

},
exists: function (key) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var wanted, links, linked, exists;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
wanted = Array.isArray(key) ? key : [key];
return [4, api.read()];
case 1:
links = (_a.sent()).body;
linked = links.list.map(function (link) { return common_1.Schema.Ref.Links.parseKey(link.key).path; });
exists = linked.some(function (linkedKey) { return wanted.includes(linkedKey); });
return [2, exists];
}
});
});
},
};

@@ -64,0 +79,0 @@ return api;

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

name: '@platform/cell.client',
version: '0.3.66',
version: '0.3.67',
dependencies: {
'@platform/cell.schema': '0.5.76',
'@platform/cell.types': '0.5.73',
'@platform/cell.typesystem': '0.0.195',
'@platform/cell.schema': '0.5.77',
'@platform/cell.types': '0.5.74',
'@platform/cell.typesystem': '0.0.196',
'@platform/http': '0.14.19',

@@ -13,0 +13,0 @@ '@platform/http.types': '0.2.42',

{
"name": "@platform/cell.client",
"version": "0.3.66",
"version": "0.3.67",
"description": "A strongly typed HTTP client for operating with a CellOS service end-point.",

@@ -16,5 +16,5 @@ "main": "lib/index",

"dependencies": {
"@platform/cell.schema": "0.5.76",
"@platform/cell.types": "0.5.73",
"@platform/cell.typesystem": "0.0.195",
"@platform/cell.schema": "0.5.77",
"@platform/cell.types": "0.5.74",
"@platform/cell.typesystem": "0.0.196",
"@platform/http": "0.14.19",

@@ -21,0 +21,0 @@ "@platform/http.types": "0.2.42",

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