fix metadata and add redirects
add redirect, other fixes remove password clean up / final version clean up / final version
This commit is contained in:
parent
4d3ec97fa6
commit
56c9a1ab41
15 changed files with 164 additions and 85 deletions
|
@ -39,7 +39,11 @@
|
||||||
"react/jsx-indent": 0,
|
"react/jsx-indent": 0,
|
||||||
"react-hooks/exhaustive-deps": "warn",
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
"react-hooks/rules-of-hooks": "error",
|
"react-hooks/rules-of-hooks": "error",
|
||||||
"space-before-function-paren": ["error", "never"],
|
"space-before-function-paren": ["error", {
|
||||||
|
"anonymous": "never",
|
||||||
|
"named": "never",
|
||||||
|
"asyncArrow": "always"
|
||||||
|
}],
|
||||||
"standard/object-curly-even-spacing": 0,
|
"standard/object-curly-even-spacing": 0,
|
||||||
"standard/no-callback-literal": 0,
|
"standard/no-callback-literal": 0,
|
||||||
"react/display-name": 0,
|
"react/display-name": 0,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const config = {
|
const config = {
|
||||||
WEBPACK_WEB_PORT: 9090, // Also hardcoded in static/index.dev-web.html
|
WEBPACK_WEB_PORT: 9090,
|
||||||
WEBPACK_ELECTRON_PORT: 9091, // Also hardcoded in static/index.dev-electron.html
|
WEBPACK_ELECTRON_PORT: 9091,
|
||||||
WEB_SERVER_PORT: 1337,
|
WEB_SERVER_PORT: 1337,
|
||||||
DOMAIN: 'https://beta.lbry.tv',
|
DOMAIN: 'https://beta.lbry.tv',
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
{
|
{
|
||||||
"from": "dist/electron/static",
|
"from": "dist/electron/static",
|
||||||
"to": "./",
|
"to": "./",
|
||||||
"filter": ["!dist/!electron/!static/index.html"]
|
"filter": ["!dist/!electron/!static/index-electron.html"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"publish": [
|
"publish": [
|
||||||
|
|
|
@ -48,7 +48,9 @@
|
||||||
"electron-updater": "^4.1.2",
|
"electron-updater": "^4.1.2",
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
"if-env": "^1.0.4",
|
"if-env": "^1.0.4",
|
||||||
"keytar": "^4.4.1"
|
"keytar": "^4.4.1",
|
||||||
|
"mysql": "^2.17.1",
|
||||||
|
"nodemon": "^1.19.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.0.0",
|
"@babel/core": "^7.0.0",
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default appState => {
|
||||||
};
|
};
|
||||||
const lbryProto = 'lbry://';
|
const lbryProto = 'lbry://';
|
||||||
const lbryProtoQ = 'lbry://?';
|
const lbryProtoQ = 'lbry://?';
|
||||||
const rendererURL = isDev ? `http://localhost:${WEBPACK_ELECTRON_PORT}` : `file://${__dirname}/index.html`;
|
const rendererURL = isDev ? `http://localhost:${WEBPACK_ELECTRON_PORT}` : `file://${__dirname}/index-electron.html`;
|
||||||
|
|
||||||
let window = new BrowserWindow(windowConfiguration);
|
let window = new BrowserWindow(windowConfiguration);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,111 @@
|
||||||
|
const { parseURI } = require('lbry-redux');
|
||||||
const { WEB_SERVER_PORT } = require('../../config');
|
const { WEB_SERVER_PORT } = require('../../config');
|
||||||
|
const { readFileSync } = require('fs');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
const mysql = require('mysql');
|
||||||
|
|
||||||
|
const pool = mysql.createPool({
|
||||||
|
connectionLimit: 100,
|
||||||
|
host: 'chainquery.lbry.com',
|
||||||
|
user: 'lbrytv',
|
||||||
|
password: process.env.CHAINQUERY_MYSQL_PASSWORD,
|
||||||
|
database: 'chainquery',
|
||||||
|
});
|
||||||
|
|
||||||
|
const getClaim = (claimName, claimId, callback) => {
|
||||||
|
let params = [claimName];
|
||||||
|
|
||||||
|
let sql =
|
||||||
|
'SELECT channel_claim.name as channel, claim.claim_id, claim.name, claim.description, claim.language, claim.thumbnail_url, claim.title ' +
|
||||||
|
'FROM claim ' +
|
||||||
|
'LEFT JOIN claim channel_claim on claim.publisher_id = channel_claim.claim_id ' +
|
||||||
|
'WHERE claim.name = ?';
|
||||||
|
|
||||||
|
if (claimId) {
|
||||||
|
sql += ' AND claim.claim_id LIKE ?';
|
||||||
|
params.push(claimId + '%');
|
||||||
|
} else {
|
||||||
|
sql += ' AND claim.bid_state = "controlling"';
|
||||||
|
}
|
||||||
|
|
||||||
|
sql += ' LIMIT 1';
|
||||||
|
|
||||||
|
pool.query(sql, params, callback);
|
||||||
|
};
|
||||||
|
|
||||||
app.use(express.static(__dirname));
|
app.use(express.static(__dirname));
|
||||||
|
|
||||||
app.get('*', function(req, res) {
|
function truncateDescription(description) {
|
||||||
res.sendFile(path.join(__dirname, '/index.html'));
|
return description.length > 200 ? description.substr(0, 200) + '...' : description;
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertToHead(fullHtml, htmlToInsert) {
|
||||||
|
return fullHtml.replace('%%HEAD_TOKEN%%', htmlToInsert);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultHead =
|
||||||
|
'<title>lbry.tv</title>\n' +
|
||||||
|
'<meta property="og:url" content="https://beta.lbry.tv" />\n' +
|
||||||
|
'<meta property="og:title" content="LBRY On The Web" />\n' +
|
||||||
|
'<meta property="og:site_name" content="LBRY.tv"/>\n' +
|
||||||
|
'<meta property="og:description" content="All your favorite LBRY content in your browser." />\n' +
|
||||||
|
'<meta property="og:image" content="/og.png" />';
|
||||||
|
|
||||||
|
app.get('*', async (req, res) => {
|
||||||
|
let html = readFileSync(path.join(__dirname, '/index-web.html'), 'utf8');
|
||||||
|
const urlPath = req.path.substr(1); // trim leading slash
|
||||||
|
|
||||||
|
if (urlPath.match(/^([^@/:]+)\/([^:/]+)$/)) {
|
||||||
|
return res.redirect(301, req.url.replace(/([^/:]+)\/([^:/]+)/, '$1:$2')); // test against urlPath, but use req.url to retain parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlPath.length > 0 && urlPath[0] !== '$') {
|
||||||
|
const { isChannel, streamName, channelName, channelClaimId, streamClaimId } = parseURI(urlPath.replace(/:/g, '#'));
|
||||||
|
const claimName = isChannel ? '@' + channelName : streamName;
|
||||||
|
const claimId = isChannel ? channelClaimId : streamClaimId;
|
||||||
|
|
||||||
|
getClaim(claimName, claimId, (err, rows) => {
|
||||||
|
if (!err && rows && rows.length > 0) {
|
||||||
|
const claim = rows[0];
|
||||||
|
const title = claim.title ? claim.title : claimName;
|
||||||
|
const claimDescription =
|
||||||
|
claim.description && claim.description.length > 0
|
||||||
|
? truncateDescription(claim.description)
|
||||||
|
: `Watch ${title} on LBRY.tv`;
|
||||||
|
const claimLanguage = claim.language || 'en_US';
|
||||||
|
const claimThumbnail = claim.thumbnail_url || '/og.png';
|
||||||
|
const claimTitle =
|
||||||
|
claim.channel && !isChannel ? `${title} from ${claim.channel} on LBRY.tv` : `${title} on LBRY.tv`;
|
||||||
|
|
||||||
|
let head = '';
|
||||||
|
|
||||||
|
head += '<meta charset="utf8"/>';
|
||||||
|
head += `<meta name="description" content="${claimDescription}"/>`;
|
||||||
|
if (claim.tags) {
|
||||||
|
head += `<meta name="keywords" content="${claim.tags.toString()}"/>`;
|
||||||
|
}
|
||||||
|
head += `<meta name="twitter:image" content="${claimThumbnail}"/>`;
|
||||||
|
head += `<meta property="og:description" content="${claimDescription}"/>`;
|
||||||
|
head += `<meta property="og:image" content="${claimThumbnail}"/>`;
|
||||||
|
head += `<meta property="og:locale" content="${claimLanguage}"/>`;
|
||||||
|
head += `<meta property="og:site_name" content="LBRY.tv"/>`;
|
||||||
|
head += `<meta property="og:type" content="website"/>`;
|
||||||
|
// below should be canonical_url, but not provided by chainquery yet
|
||||||
|
head += `<meta property="og:url" content="https://beta.lbry.tv/${claim.name}:${claim.claim_id}"/>`;
|
||||||
|
head += `<title>${claimTitle}</title>`;
|
||||||
|
|
||||||
|
html = insertToHead(html, head);
|
||||||
|
} else {
|
||||||
|
html = insertToHead(html, defaultHead);
|
||||||
|
}
|
||||||
|
res.send(html);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.send(insertToHead(html, defaultHead));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.listen(WEB_SERVER_PORT, () => console.log(`UI server listening at http://localhost:${WEB_SERVER_PORT}`)); // eslint-disable-line
|
app.listen(WEB_SERVER_PORT, () => console.log(`UI server listening at http://localhost:${WEB_SERVER_PORT}`)); // eslint-disable-line
|
||||||
|
|
|
@ -168,7 +168,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
||||||
});
|
});
|
||||||
const success = () => {
|
const success = () => {
|
||||||
this.setState({ clearingCache: false });
|
this.setState({ clearingCache: false });
|
||||||
window.location.href = 'index.html';
|
window.location.reload();
|
||||||
};
|
};
|
||||||
const clear = () => this.props.clearCache().then(success);
|
const clear = () => this.props.clearCache().then(success);
|
||||||
|
|
||||||
|
|
12
static/index-electron.html
Normal file
12
static/index-electron.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>LBRY</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="text/javascript" src="ui.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
static/index-web.html
Normal file
12
static/index-web.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
%%HEAD_TOKEN%%
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="text/javascript" src="/ui.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,18 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>LBRY Dev</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Primary definition for this is in config.js as WEBPACK_ELECTRON_PORT
|
|
||||||
We can't access it here because webpack isn't running on this file
|
|
||||||
-->
|
|
||||||
<script type="text/javascript" src="http://localhost:9091/ui.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,18 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>LBRY Dev</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Primary definition for this is in webpack.web.config.js as WEBPACK_WEB_PORT
|
|
||||||
We can't access it here because webpack isn't running on this file
|
|
||||||
-->
|
|
||||||
<script type="text/javascript" src="http://localhost:9090/ui.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,34 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<!-- @if TARGET='app' -->
|
|
||||||
<title>LBRY</title>
|
|
||||||
<!-- @endif -->
|
|
||||||
<!-- @if TARGET='web' -->
|
|
||||||
<title>lbry.tv</title>
|
|
||||||
<meta property="og:url" content="https://beta.lbry.tv" />
|
|
||||||
<meta property="og:title" content="LBRY On The Web" />
|
|
||||||
<meta property="og:description" content="All your favorite LBRY content in your browser." />
|
|
||||||
<meta property="og:image" content="/og.png" />
|
|
||||||
<!-- @endif -->
|
|
||||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1" /> -->
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// Use relative path if we are in electron
|
|
||||||
let src = 'ui.js';
|
|
||||||
const userAgent = navigator.userAgent.toLowerCase();
|
|
||||||
|
|
||||||
if (userAgent.indexOf('electron') === -1) {
|
|
||||||
src = `/${src}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.setAttribute('src', src);
|
|
||||||
document.body.appendChild(script);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -46,11 +46,11 @@ let mainConfig = {
|
||||||
{
|
{
|
||||||
from: `${STATIC_ROOT}/`,
|
from: `${STATIC_ROOT}/`,
|
||||||
to: `${DIST_ROOT}/electron/static/`,
|
to: `${DIST_ROOT}/electron/static/`,
|
||||||
ignore: ['font/**/*', 'index.dev-web.html', 'index.html'],
|
ignore: ['font/**/*', 'index-electron.html'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: ifProduction(`${STATIC_ROOT}/index.html`, `${STATIC_ROOT}/index.dev-electron.html`),
|
from: `${STATIC_ROOT}/index-electron.html`,
|
||||||
to: `${DIST_ROOT}/electron/static/index.html`,
|
to: `${DIST_ROOT}/electron/static/index-electron.html`,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
|
|
@ -51,8 +51,8 @@ const webConfig = {
|
||||||
plugins: [
|
plugins: [
|
||||||
new CopyWebpackPlugin([
|
new CopyWebpackPlugin([
|
||||||
{
|
{
|
||||||
from: `${STATIC_ROOT}/index.html`,
|
from: `${STATIC_ROOT}/index-web.html`,
|
||||||
to: `${DIST_ROOT}/web/index.html`,
|
to: `${DIST_ROOT}/web/index-web.html`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: `${STATIC_ROOT}/img/favicon.ico`,
|
from: `${STATIC_ROOT}/img/favicon.ico`,
|
||||||
|
|
22
yarn.lock
22
yarn.lock
|
@ -1852,6 +1852,11 @@ big.js@^5.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||||
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
||||||
|
|
||||||
|
bignumber.js@7.2.1:
|
||||||
|
version "7.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
||||||
|
integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==
|
||||||
|
|
||||||
binary-extensions@^1.0.0:
|
binary-extensions@^1.0.0:
|
||||||
version "1.13.1"
|
version "1.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||||
|
@ -7751,6 +7756,16 @@ mux.js@5.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.1.1.tgz#0e95f048b4ac51d413c9ddc2d78e4cefad8d06de"
|
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.1.1.tgz#0e95f048b4ac51d413c9ddc2d78e4cefad8d06de"
|
||||||
integrity sha512-Mf/UYmh5b8jvUP+jmrTbETnyFZprMdbT0RxKm/lJ/4d2Q3xdc5GaHaRPI1zVV5D3+6uxArVPm78QEb1RsrmaQw==
|
integrity sha512-Mf/UYmh5b8jvUP+jmrTbETnyFZprMdbT0RxKm/lJ/4d2Q3xdc5GaHaRPI1zVV5D3+6uxArVPm78QEb1RsrmaQw==
|
||||||
|
|
||||||
|
mysql@^2.17.1:
|
||||||
|
version "2.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.17.1.tgz#62bba4a039a9b2f73638cd1652ce50fc6f682899"
|
||||||
|
integrity sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA==
|
||||||
|
dependencies:
|
||||||
|
bignumber.js "7.2.1"
|
||||||
|
readable-stream "2.3.6"
|
||||||
|
safe-buffer "5.1.2"
|
||||||
|
sqlstring "2.3.1"
|
||||||
|
|
||||||
nan@2.13.2:
|
nan@2.13.2:
|
||||||
version "2.13.2"
|
version "2.13.2"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
||||||
|
@ -9953,7 +9968,7 @@ read-pkg@^4.0.1:
|
||||||
parse-json "^4.0.0"
|
parse-json "^4.0.0"
|
||||||
pify "^3.0.0"
|
pify "^3.0.0"
|
||||||
|
|
||||||
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
"readable-stream@1 || 2", readable-stream@2.3.6, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
||||||
version "2.3.6"
|
version "2.3.6"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||||
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
|
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
|
||||||
|
@ -11017,6 +11032,11 @@ sprintf-js@~1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
|
sqlstring@2.3.1:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
|
||||||
|
integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||||
|
|
Loading…
Add table
Reference in a new issue