1
0
mirror of https://github.com/byulmaru/quesdon synced 2024-11-27 06:18:02 +09:00

서버 코드 ts3 붙이고 문법 내스타일로 정리

This commit is contained in:
DW 2019-11-06 15:05:17 +11:00
parent 1e20b4f186
commit f68e1678f2
25 changed files with 8756 additions and 625 deletions

View File

@ -29,7 +29,9 @@
"comma-dangle": ["warn", "never"],
"brace-style": ["error", "allman", { "allowSingleLine": true }],
"eqeqeq": ["error", "always"],
"require-atomic-updates": "off",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/camelcase": "off"
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/interface-name-prefix": ["error", { "prefixWithI": "always" }]
}
}

View File

@ -1,24 +1,25 @@
// インスタンス別ユーザー数ランキング
// RoboMongoで実行
// 인스턴스별 사용자 수 랭킹
// RoboMongo 사용
(function(){
(function()
{
let hostNames = db.getCollection('users').find({}, {acctLower: 1}).map(user => user.acctLower.split("@").pop()).filter(hostName => hostName)
let count = {}
var hostNames = db.getCollection('users').find({}, {acctLower: 1}).map(user => user.acctLower.split("@").pop()).filter(hostName => hostName)
var count = {}
hostNames.forEach(hostName =>
{
if (count[hostName] == null) count[hostName] = 0
count[hostName]++
})
hostNames.forEach(hostName => {
if (count[hostName] == null) count[hostName] = 0
count[hostName]++
})
let sortedCount = Object.keys(count).map(hostName => [hostName, count[hostName]]).sort((a, b) => b[1] - a[1])
var sortedCount = Object.keys(count).map(hostName => [hostName, count[hostName]]).sort((a, b) => b[1] - a[1])
count = {}
count = {}
sortedCount.forEach(a =>
{
count[a[0]] = a[1]
})
sortedCount.forEach(a => {
count[a[0]] = a[1]
})
return count
return count
})()

View File

@ -19,6 +19,7 @@
"author": "rinsuki",
"license": "AGPL-3.0+",
"devDependencies": {
"@types/common-tags": "^1.8.0",
"@types/dotenv": "^8.2.0",
"@types/koa": "^2.0.51",
"@types/koa-mount": "^4.0.0",
@ -26,15 +27,16 @@
"@types/koa-router": "^7.0.42",
"@types/koa-session": "^5.10.1",
"@types/koa-static": "^4.0.1",
"@types/mongoose": "^5.5.28",
"@types/node-fetch": "^2.5.2",
"@types/koa-static-cache": "^5.1.0",
"@types/mongoose": "^5.5.29",
"@types/node-fetch": "^2.5.3",
"@types/parse-link-header": "^1.0.0",
"@types/react": "^16.9.11",
"@types/react-dom": "^16.9.3",
"@types/react-router-dom": "^5.1.1",
"@types/react-router-dom": "^5.1.2",
"@types/reactstrap": "^8.0.6",
"@typescript-eslint/eslint-plugin": "^2.6.0",
"@typescript-eslint/parser": "^2.6.0",
"@typescript-eslint/eslint-plugin": "^2.6.1",
"@typescript-eslint/parser": "^2.6.1",
"babel-core": "^6.26.0",
"babel-loader": "^8.0.6",
"babel-preset-env": "^1.7.0",
@ -46,6 +48,7 @@
"fetch-defaults": "^1.0.0",
"file-loader": "^4.2.0",
"jquery": "^3.4.1",
"megalodon": "^2.0.0",
"moment": "^2.24.0",
"node-dev": "^4.0.0",
"npm-run-all": "^4.1.5",
@ -57,13 +60,14 @@
"reactstrap": "^8.1.1",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.1",
"typescript": "^3.6.4",
"typescript": "^3.7.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
},
"dependencies": {
"common-tags": "^1.8.0",
"dotenv": "^8.2.0",
"koa": "^2.11.0",
"koa-body": "^4.1.1",
@ -73,7 +77,7 @@
"koa-session": "^5.12.3",
"koa-static": "^5.0.0",
"koa-static-cache": "^5.1.1",
"mongoose": "^5.7.7",
"mongoose": "^5.7.8",
"mongoose-autopopulate": "^0.9.1",
"node-fetch": "^2.6.0",
"oauth-1.0a": "github:rinsuki/oauth-1.0a",

View File

@ -1,3 +1,5 @@
/* eslint @typescript-eslint/interface-name-prefix: 0 */
export interface APIQuestion
{
_id: string;

View File

@ -1,4 +1,4 @@
import * as Router from 'koa-router';
import Router from 'koa-router';
import webRouter from './web';
const router = new Router();

View File

@ -1,199 +1,254 @@
import * as Koa from 'koa';
import * as Router from 'koa-router';
import * as mongoose from 'mongoose';
import Koa from 'koa';
import Router from 'koa-router';
import fetch from 'node-fetch';
import * as parseLinkHeader from 'parse-link-header';
import { Link, Links } from 'parse-link-header';
import parseLinkHeader, { Link, Links } from 'parse-link-header';
import { Account } from 'megalodon';
import { oneLineTrim, stripIndents } from 'common-tags';
import { QUESTION_TEXT_MAX_LENGTH } from '../../../common/const';
import { BASE_URL, NOTICE_ACCESS_TOKEN, PUSHBULLET_CLIENT_ID, PUSHBULLET_CLIENT_SECRET } from '../../config';
import { Question, User } from '../../db/index';
const router = new Router();
router.get('/verify_credentials', async (ctx) =>
router.get('/verify_credentials', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
ctx.body = user;
});
router.get('/followers', async (ctx) =>
router.get('/followers', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (null == /^\d+$/.exec(ctx.query.max_id || '0')) return ctx.throw('max_id is num only', 400);
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
if (null === /^\d+$/.exec(ctx.query.max_id || '0'))
return ctx.throw('max_id is num only', 400);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
// twitter
if (user.hostName === 'twitter.com')
{
return {max_id: undefined, accounts: []};
}
return;
// return { max_id: undefined, accounts: [] };
// TODO: add logic for misskey
// mastodon
const instanceUrl = 'https://' + user.acct.split('@')[1];
const myInfo = await fetch(instanceUrl + '/api/v1/accounts/verify_credentials', {
headers: {
Authorization: 'Bearer ' + user.accessToken
}
}).then((r) => r.json());
const param = ctx.query.max_id ? '&max_id=' + ctx.query.max_id : '';
const followersRes = await fetch(
`${instanceUrl}/api/v1/accounts/${myInfo.id}/followers?limit=80${param}`,
const myInfo = await fetch(instanceUrl + '/api/v1/accounts/verify_credentials',
{
headers: {
Authorization: 'Bearer ' + user.accessToken
}
}
);
let followers: any[] = await followersRes.json();
followers = followers
.map((follower) => follower.acct as string)
headers: { Authorization: 'Bearer ' + user.accessToken }
}).then((r) => r.json());
const param = ctx.query.max_id ? '&max_id=' + ctx.query.max_id : '';
const followersRes = await fetch(`${instanceUrl}/api/v1/accounts/${myInfo.id}/followers?limit=80${param}`,
{
headers: { Authorization: 'Bearer ' + user.accessToken }
});
const followersRaw: Account[] = await followersRes.json();
const followers = followersRaw
.map((follower) => follower.acct)
.map((acct) => acct.includes('@') ? acct : (acct + '@' + user.acct.split('@')[1]))
.map((acct) => acct.toLowerCase());
.map((acct) => acct.toLowerCase()); // create a string[] of followers in 'lowercase@host.name' form
const followersObject = await User.find({acctLower: {$in: followers}});
const max_id = ((parseLinkHeader(followersRes.headers.get('Link')!) || {} as Links).next || {} as Link).max_id;
ctx.body = {
accounts: followersObject,
max_id
};
const max_id = ((parseLinkHeader(followersRes.headers.get('Link') ?? '') || {} as Links).next || {} as Link).max_id;
ctx.body =
{
accounts: followersObject,
max_id
};
});
router.post('/update', async (ctx) =>
router.post('/update', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
user.description = ctx.request.body.fields.description;
user.questionBoxName = ctx.request.body.fields.questionBoxName;
user.allAnon = !!ctx.request.body.fields.allAnon;
user.stopNewQuestion = !!ctx.request.body.fields.stopNewQuestion;
await user.save();
ctx.body = {status: 'ok'};
ctx.body = {status: 'ok'};
});
router.get('/id/:id', async (ctx) =>
router.get('/id/:id', async (ctx): Promise<never|void> =>
{
const user = await User.findById(ctx.params.id);
if (!user) return ctx.throw('not found', 404);
ctx.body = user;
if (!user)
return ctx.throw('not found', 404);
ctx.body = user;
});
router.get('/pushbullet/redirect', async (ctx) =>
router.get('/pushbullet/redirect', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
ctx.redirect('https://www.pushbullet.com/authorize'
+ '?client_id=' + PUSHBULLET_CLIENT_ID
+ '&redirect_uri=' + encodeURIComponent(BASE_URL + '/api/web/accounts/pushbullet/callback')
+ '&response_type=code'
+ '&scope=everything'
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
ctx.redirect(oneLineTrim`https://www.pushbullet.com/authorize
?client_id=${PUSHBULLET_CLIENT_ID}
&redirect_uri=${encodeURIComponent(BASE_URL + '/api/web/accounts/pushbullet/callback')}
&response_type=code
&scope=everything`
);
});
router.get('/pushbullet/callback', async (ctx) =>
router.get('/pushbullet/callback', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
const res = await fetch('https://api.pushbullet.com/oauth2/token', {
method: 'POST',
body: JSON.stringify({
client_id: PUSHBULLET_CLIENT_ID,
client_secret: PUSHBULLET_CLIENT_SECRET,
code: ctx.query.code,
grant_type: 'authorization_code'
}),
headers: {
'Content-Type': 'application/json'
}
}).then((r) => r.json());
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
const res = await fetch('https://api.pushbullet.com/oauth2/token',
{
method: 'POST',
body: JSON.stringify(
{
client_id: PUSHBULLET_CLIENT_ID,
client_secret: PUSHBULLET_CLIENT_SECRET,
code: ctx.query.code,
grant_type: 'authorization_code'
}),
headers: { 'Content-Type': 'application/json' }
}).then((r) => r.json());
if (res.error)
{
return ctx.throw(500, 'pushbullet error: ' + res.error.message);
}
user.pushbulletAccessToken = res.access_token;
await user.save();
ctx.redirect('/my/settings');
});
router.post('/pushbullet/disconnect', async (ctx) =>
router.post('/pushbullet/disconnect', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const user = await User.findById(ctx.session!.user);
if (!user) return ctx.throw('not found', 404);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const user = await User.findById(ctx.session.user);
if (!user)
return ctx.throw('not found', 404);
user.pushbulletAccessToken = null;
await user.save();
ctx.body = {status: 'ok'};
ctx.body = {status: 'ok'};
});
router.get('/:acct', async (ctx) =>
router.get('/:acct', async (ctx): Promise<never|void> =>
{
const user = await User.findOne({acctLower: ctx.params.acct.toLowerCase()});
if (!user) return ctx.throw('not found', 404);
ctx.body = user;
if (!user)
return ctx.throw('not found', 404);
ctx.body = user;
});
router.post('/:acct/question', async (ctx) =>
router.post('/:acct/question', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
const questionString = ctx.request.body.fields.question;
if (questionString.length < 1) return ctx.throw('please input question', 400);
if (questionString.length > QUESTION_TEXT_MAX_LENGTH) return ctx.throw('too long', 400);
if (questionString.length < 1)
return ctx.throw('please input question', 400);
if (questionString.length > QUESTION_TEXT_MAX_LENGTH)
return ctx.throw('too long', 400);
const user = await User.findOne({acctLower: ctx.params.acct.toLowerCase()});
if (!user) return ctx.throw('not found', 404);
if (user.stopNewQuestion) return ctx.throw(400, 'this user has stopped new question submit');
if (!user)
return ctx.throw('not found', 404);
if (user.stopNewQuestion)
return ctx.throw(400, 'this user has stopped new question submit');
const question = new Question();
question.question = questionString;
question.user = user;
if (ctx.request.body.fields.noAnon)
{
if (user.allAnon) return ctx.throw('all anon', 400);
if (!ctx.session!.user) return ctx.throw('please login', 403);
const questionUser = await User.findById(ctx.session!.user);
if (!questionUser) return ctx.throw('not found', 404);
if (user.allAnon)
return ctx.throw('all anon', 400);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const questionUser = await User.findById(ctx.sessions.user);
if (!questionUser)
return ctx.throw('not found', 404);
question.questionUser = questionUser;
}
await question.save();
ctx.body = {status: 'ok'};
if (user.pushbulletAccessToken)
{
fetch('https://api.pushbullet.com/v2/pushes', {
method: 'POST',
body: JSON.stringify({
type: 'link',
body: '새로운 질문이에요!\nQ. ' + question.question,
url: BASE_URL + '/my/questions'
}),
headers: {
'Access-Token': user.pushbulletAccessToken,
'Content-Type': 'application/json'
}
});
fetch('https://api.pushbullet.com/v2/pushes',
{
method: 'POST',
body: JSON.stringify(
{
type: 'link',
body: stripIndents`새로운 질문이에요!
Q. ${question.question}`,
url: BASE_URL + '/my/questions'
}),
headers:
{
'Access-Token': user.pushbulletAccessToken,
'Content-Type': 'application/json'
}
});
}
if (NOTICE_ACCESS_TOKEN)
{
fetch('https://planet.moe/api/v1/statuses', {
method: 'POST',
body: JSON.stringify({
status: '@' + user.acct + ' Quesdon@Planet - 새로운 질문이에요!\nQ. ' + question.question
+ '\n' + BASE_URL + '/my/questions',
visibility: 'direct'
}),
headers: {
'Authorization': 'Bearer ' + NOTICE_ACCESS_TOKEN,
'Content-Type': 'application/json'
}
});
fetch('https://planet.moe/api/v1/statuses',
{
method: 'POST',
body: JSON.stringify(
{
status: stripIndents`@${user.acct} Quesdon@Planet - 새로운 질문이에요!
Q. ${question.question}
${BASE_URL}/my/questions`,
visibility: 'direct'
}),
headers:
{
'Authorization': 'Bearer ' + NOTICE_ACCESS_TOKEN,
'Content-Type': 'application/json'
}
});
}
});
const getAnswers = async (ctx: Koa.Context) =>
const getAnswers = async (ctx: Koa.ParameterizedContext): Promise<void> =>
{
const user = await User.findOne({acctLower: ctx.params.acct.toLowerCase()});
if (!user) return ctx.throw('not found', 404);
const questions = await Question.find({
user,
answeredAt: {$ne: null},
isDeleted: {$ne: true}
}).sort('-answeredAt');
if (!user)
return ctx.throw('not found', 404);
const questions = await Question.find(
{
user,
answeredAt: {$ne: null},
isDeleted: {$ne: true}
}).sort('-answeredAt');
ctx.body = questions.map((question) =>
{
question.user = user;

View File

@ -1,16 +1,17 @@
import * as Router from 'koa-router';
import Koa from 'koa';
import Router from 'koa-router';
import accountsRouter from './accounts';
import oauthRouter from './oauth';
import questionsRouter from './questions';
const router = new Router();
router.use(async (ctx, next) =>
router.use(async (ctx: Koa.ParameterizedContext, next): Promise<void> =>
{
if (ctx.request.method !== 'GET')
{
if (ctx.session!.csrfToken !== ctx.request.headers['x-csrf-token']) return ctx.throw('invalid csrf token', 403);
}
if (ctx.session.csrfToken !== ctx.request.headers['x-csrf-token'])
return ctx.throw('invalid csrf token', 403);
await next();
});
@ -18,10 +19,10 @@ router.use('/oauth', oauthRouter.routes());
router.use('/accounts', accountsRouter.routes());
router.use('/questions', questionsRouter.routes());
router.get('/logout', async (ctx) =>
router.get('/logout', (ctx: Koa.ParameterizedContext) =>
{
ctx.session!.user = undefined;
ctx.body = {status: 'ok'};
ctx.session.user = undefined;
ctx.body = { status: 'ok' };
});
export default router;

View File

@ -1,4 +1,5 @@
import * as Router from 'koa-router';
import Koa from 'koa';
import Router from 'koa-router';
import fetch from 'node-fetch';
import rndstr from 'rndstr';
import { URL } from 'url';
@ -10,189 +11,213 @@ import twitterClient from '../../utils/twitterClient';
const router = new Router();
router.post('/get_url', async (ctx) =>
router.post('/get_url', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
const hostName = ctx.request.body.fields.instance
.replace(/.*@/, '').toLowerCase();
if (hostName.includes('/')) return ctx.reject(400, 'not use slash in hostname');
const hostName = ctx.request.body.fields.instance.replace(/.*@/, '').toLowerCase();
if (hostName.includes('/'))
return ctx.throw(400, 'not use slash in hostname');
const redirectUri = BASE_URL + '/api/web/oauth/redirect';
let url = '';
if (hostName !== 'twitter.com')
{ // Mastodon
let app = await MastodonApp.findOne({hostName, appBaseUrl: BASE_URL, redirectUri});
{
// Mastodon
// TODO: misskey support
let app = await MastodonApp.findOne( { hostName, appBaseUrl: BASE_URL, redirectUri } );
if (!app)
{
const res = await fetch('https://' + hostName + '/api/v1/apps', {
method: 'POST',
body: JSON.stringify({
client_name: 'Quesdon',
redirect_uris: redirectUri,
scopes: 'read write',
website: BASE_URL
}),
headers: {'Content-Type': 'application/json'}
}).then((r) => r.json());
const res = await fetch('https://' + hostName + '/api/v1/apps',
{
method: 'POST',
body: JSON.stringify(
{
client_name: 'Quesdon',
redirect_uris: redirectUri,
scopes: 'read write',
website: BASE_URL
}),
headers: { 'Content-Type': 'application/json' }
}).then((r) => r.json());
app = new MastodonApp();
app.clientId = res.client_id;
app.clientSecret = res.client_secret;
app.hostName = hostName;
app.appBaseUrl = BASE_URL;
app.redirectUri = redirectUri;
await app.save();
}
ctx.session!.loginState = rndstr() + '_' + app.id;
const params: {[key: string]: string} = {
client_id: app.clientId,
scope: 'read+write',
redirect_uri: redirectUri,
response_type: 'code',
state: ctx.session!.loginState
};
url = `https://${app.hostName}/oauth/authorize?${Object.entries(params).map((v) => v.join('=')).join('&')}`;
ctx.session.loginState = `${rndstr()}_${app.id}`;
const params: {[key: string]: string} =
{
client_id: app.clientId,
scope: 'read+write',
redirect_uri: redirectUri,
response_type: 'code',
state: ctx.session.loginState
};
url = `https://${app.hostName}/oauth/authorize?${Object.entries(params).map((v) => v.join('=')).join('&')}`;
}
else
{ // Twitter
ctx.session!.loginState = 'twitter';
const { TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET } = process.env;
if (TWITTER_CONSUMER_KEY == null || TWITTER_CONSUMER_SECRET == null)
{
ctx.throw(500, 'twitter not supported in this server.');
}
const requestTokenRes = await requestOAuth(twitterClient, {
url: 'https://api.twitter.com/oauth/request_token',
method: 'POST',
data: {}
}).then((r) => r.text()).then((r) => QueryStringUtils.decode(r));
const requestToken = {
token: requestTokenRes.oauth_token,
secret: requestTokenRes.oauth_token_secret
};
ctx.session!.twitterOAuth = requestToken;
url = `https://twitter.com/oauth/authenticate?oauth_token=${requestToken.token}`;
else // Twitter
{
ctx.session.loginState = 'twitter';
const { TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET } = process.env;
if (TWITTER_CONSUMER_KEY === null || TWITTER_CONSUMER_SECRET === null)
ctx.throw(500, 'twitter not supported in this server.');
const requestTokenRes = await requestOAuth(twitterClient,
{
url: 'https://api.twitter.com/oauth/request_token',
method: 'POST',
data: {}
}).then((r) => r.text()).then((r) => QueryStringUtils.decode(r));
const requestToken =
{
token: requestTokenRes.oauth_token,
secret: requestTokenRes.oauth_token_secret
};
ctx.session.twitterOAuth = requestToken;
url = `https://twitter.com/oauth/authenticate?oauth_token=${requestToken.token}`;
}
ctx.body = {
url
};
ctx.body = { url };
});
router.get('/redirect', async (ctx) =>
router.get('/redirect', async (ctx: Koa.ParameterizedContext) =>
{
let profile: {
id: string;
name: string;
screenName: string;
avatarUrl: string;
accessToken: string;
hostName: string;
url: string;
acct: string;
};
if (ctx.session!.loginState !== 'twitter')
{
if (ctx.query.state !== ctx.session!.loginState)
let profile:
{
ctx.redirect('/login?error=invalid_state');
return;
}
const app = await MastodonApp.findById(ctx.session!.loginState.split('_')[1]);
if (app == null)
{
ctx.redirect('/login?error=app_notfound');
return;
}
const res = await fetch('https://' + app.hostName + '/oauth/token', {
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
redirect_uri: app.redirectUri,
client_id: app.clientId,
client_secret: app.clientSecret,
code: ctx.query.code,
state: ctx.query.state
}),
headers: {'Content-Type': 'application/json'}
}).then((r) => r.json());
const myProfile = await fetch('https://' + app.hostName + '/api/v1/accounts/verify_credentials', {
headers: {Authorization: 'Bearer ' + res.access_token}
}).then((r) => r.json());
profile = {
id: myProfile.id,
name: myProfile.display_name || myProfile.username,
screenName: myProfile.username,
hostName: app.hostName,
avatarUrl: myProfile.avatar_static,
accessToken: res.access_token,
url: myProfile.url,
acct: myProfile.username + '@' + app.hostName
id: string;
name: string;
screenName: string;
avatarUrl: string;
accessToken: string;
hostName: string;
url: string;
acct: string;
};
if (ctx.session.loginState !== 'twitter')
{
// Mastodon
// TODO: handle misskey
if (ctx.query.state !== ctx.session.loginState)
return ctx.redirect('/login?error=invalid_state');
const app = await MastodonApp.findById(ctx.session.loginState.split('_')[1]);
if (app === null)
return ctx.redirect('/login?error=app_notfound');
const res = await fetch('https://' + app.hostName + '/oauth/token',
{
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
redirect_uri: app.redirectUri,
client_id: app.clientId,
client_secret: app.clientSecret,
code: ctx.query.code,
state: ctx.query.state
}),
headers: { 'Content-Type': 'application/json' }
}).then((r) => r.json());
const myProfile = await fetch('https://' + app.hostName + '/api/v1/accounts/verify_credentials',
{
headers: { Authorization: 'Bearer ' + res.access_token }
}).then((r) => r.json());
profile =
{
id: myProfile.id,
name: myProfile.display_name || myProfile.username,
screenName: myProfile.username,
hostName: app.hostName,
avatarUrl: myProfile.avatar_static,
accessToken: res.access_token,
url: myProfile.url,
acct: myProfile.username + '@' + app.hostName
};
}
else
{ // twitter
const requestToken: {
const requestToken:
{
token: string;
secret: string;
} | undefined = ctx.session!.twitterOAuth;
if (!requestToken) return ctx.redirect('/login?error=no_request_token');
if (requestToken.token !== ctx.query.oauth_token) return ctx.redirect('/login?error=invalid_request_token');
} | undefined = ctx.session.twitterOAuth;
if (!requestToken)
return ctx.redirect('/login?error=no_request_token');
if (requestToken.token !== ctx.query.oauth_token)
return ctx.redirect('/login?error=invalid_request_token');
let accessToken;
try
{
const accessTokenRes = await requestOAuth(twitterClient, {
url: 'https://api.twitter.com/oauth/access_token',
method: 'POST',
data: {oauth_verifier: ctx.query.oauth_verifier}
}, {
key: requestToken.token,
secret: requestToken.secret
}).then((r) => r.text()).then((r) => QueryStringUtils.decode(r));
accessToken = {
key: accessTokenRes.oauth_token,
secret: accessTokenRes.oauth_token_secret
};
const accessTokenRes = await requestOAuth(twitterClient,
{
url: 'https://api.twitter.com/oauth/access_token',
method: 'POST',
data: { oauth_verifier: ctx.query.oauth_verifier }
},
{
key: requestToken.token,
secret: requestToken.secret
}).then((r) => r.text()).then((r) => QueryStringUtils.decode(r));
accessToken =
{
key: accessTokenRes.oauth_token,
secret: accessTokenRes.oauth_token_secret
};
}
catch (e)
{
return ctx.redirect('/login?error=failed_access_token_fetch');
}
let a;
let resp;
try
{
a = await requestOAuth(twitterClient, {
url: 'https://api.twitter.com/1.1/account/verify_credentials.json',
method: 'GET',
data: {}
}, accessToken).then((r) => r.json());
resp = await requestOAuth(twitterClient,
{
url: 'https://api.twitter.com/1.1/account/verify_credentials.json',
method: 'GET',
data: {}
}, accessToken).then((r) => r.json());
}
catch (e)
{
return ctx.redirect('/login?error=failed_user_profile_fetch');
}
profile = {
id: a.id_str,
name: a.name,
screenName: a.screen_name,
profile =
{
id: resp.id_str,
name: resp.name,
screenName: resp.screen_name,
hostName: 'twitter.com',
avatarUrl: a.profile_image_url_https.replace('_normal.', '_400x400.'),
avatarUrl: resp.profile_image_url_https.replace('_normal.', '_400x400.'),
accessToken: accessToken.key + ':' + accessToken.secret,
url: 'https://twitter.com/' + a.screen_name,
acct: a.screen_name + ':' + a.id_str + '@twitter.com'
url: 'https://twitter.com/' + resp.screen_name,
acct: resp.screen_name + ':' + resp.id_str + '@twitter.com'
};
}
if (!profile) return;
const acct = profile.acct;
let user;
if (profile.hostName !== 'twitter.com')
{ // Mastodon
{
// Mastodon
// TODO: misskey
user = await User.findOne({acctLower: acct.toLowerCase()});
}
else
{
user = await User.findOne({upstreamId: profile.id, hostName: profile.hostName});
}
if (user == null)
{
if (user === null)
user = new User();
}
user.acct = acct;
user.acctLower = acct.toLowerCase();
user.name = profile.name;
@ -202,8 +227,10 @@ router.get('/redirect', async (ctx) =>
user.url = profile.url;
user.upstreamId = profile.id;
await user.save();
ctx.session!.user = user.id;
ctx.redirect('/my');
ctx.session.user = user.id;
ctx.redirect('/my');
});
export default router;

View File

@ -1,6 +1,8 @@
import * as Router from 'koa-router';
import * as mongoose from 'mongoose';
import Koa from 'koa';
import Router from 'koa-router';
import mongoose from 'mongoose';
import fetch from 'node-fetch';
import { stripIndents } from 'common-tags';
import { BASE_URL } from '../../config';
import { IMastodonApp, IUser, Question, QuestionLike, User } from '../../db/index';
import { cutText } from '../../utils/cutText';
@ -9,176 +11,224 @@ import twitterClient from '../../utils/twitterClient';
const router = new Router();
router.get('/', async (ctx) =>
router.get('/', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const questions = await Question.find({
user: mongoose.Types.ObjectId(ctx.session!.user),
answeredAt: null,
isDeleted: {$ne: true}
});
if (!ctx.session.user)
return ctx.throw('please login', 403);
const questions = await Question.find(
{
user: mongoose.Types.ObjectId(ctx.session.user),
answeredAt: null,
isDeleted: {$ne: true}
});
ctx.body = JSON.stringify(questions);
});
router.get('/count', async (ctx) =>
router.get('/count', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
const count = await Question.find({
user: mongoose.Types.ObjectId(ctx.session!.user),
answeredAt: null,
isDeleted: {$ne: true}
}).count();
ctx.body = {count};
if (!ctx.session.user)
return ctx.throw('please login', 403);
const count = await Question.find(
{
user: mongoose.Types.ObjectId(ctx.session!.user),
answeredAt: null,
isDeleted: {$ne: true}
}).count();
ctx.body = { count };
});
router.get('/latest', async (ctx) =>
{
const questions = await Question.find({
answeredAt: {$ne: null},
isDeleted: {$ne: true}
}).limit(20).sort('-answeredAt');
const questions = await Question.find(
{
answeredAt: {$ne: null},
isDeleted: {$ne: true}
}).limit(20).sort('-answeredAt');
ctx.body = questions;
});
router.post('/:id/answer', async (ctx) =>
router.post('/:id/answer', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const question = await Question.findById(ctx.params.id);
if (!question) return ctx.throw('not found', 404);
if (question.isDeleted) return ctx.throw('not found', 404);
// tslint:disable-next-line:triple-equals
if (question.user._id != ctx.session!.user) return ctx.throw('not found', 404);
if (question.answeredAt) return ctx.throw('alread answered', 400);
question.answer = ctx.request.body.fields.answer;
if (question.answer!.length < 1) return ctx.throw('please input answer', 400);
if (!question)
return ctx.throw('not found', 404);
if (question.isDeleted)
return ctx.throw('not found', 404);
if (question.user._id != ctx.session.user) // eslint-disable-line eqeqeq
return ctx.throw('not found', 404);
if (question.answeredAt)
return ctx.throw('alread answered', 400);
question.answer = ctx.request.body.fields.answer as string;
if (question.answer.length < 1)
return ctx.throw('please input answer', 400);
question.answeredAt = new Date();
if (ctx.request.body.fields.isNSFW) question.isNSFW = true;
if (ctx.request.body.fields.isNSFW)
question.isNSFW = true;
await question.save();
ctx.body = {status: 'ok'};
const user = await User.findById(ctx.session!.user);
if (!['public', 'unlisted', 'private'].includes(ctx.request.body.fields.visibility)) return;
if (!user) return;
ctx.body = { status: 'ok' };
const user = await User.findById(ctx.session.user);
if (!['public', 'unlisted', 'private'].includes(ctx.request.body.fields.visibility))
return;
if (!user)
return;
const isTwitter = user.hostName === 'twitter.com';
const answerCharMax = isTwitter ? (110 - question.question.length) : 200;
const answerUrl = BASE_URL + '/@' + user.acct + '/questions/' + question.id;
const answerUrl = `${BASE_URL}/@${user.acct}/questions/${question.id}`;
if (!isTwitter)
{ // Mastodon
const body = {
spoiler_text: 'Q. ' + question.question + ' #quesdon',
status: [
'A. ',
(question.answer!.length > 200
? question.answer!.substring(0, 200) + '...'
: question.answer),
'\n#quesdon ',
answerUrl
].join(''),
visibility: ctx.request.body.fields.visibility
};
{
// Mastodon
// TODO: misskey
const body =
{
spoiler_text: `Q. ${question.question} #quesdon`,
status: `A. ${question.answer.length > 200 ? `${question.answer.substring(0, 200)}...` : question.answer}
#quesdon ${answerUrl}`,
visibility: ctx.request.body.fields.visibility
};
if (question.questionUser)
{
let questionUserAcct = '@' + question.questionUser.acct;
let questionUserAcct = `@${question.questionUser.acct}`;
if (question.questionUser.hostName === 'twitter.com')
{
questionUserAcct = 'https://twitter.com/' + question.questionUser.acct.replace(/:.+/, '');
}
body.status = '질문자: ' + questionUserAcct + '\n' + body.status;
questionUserAcct = `https://twitter.com/${question.questionUser.acct.replace(/:.+/, '')}`;
body.status = stripIndents`질문자: ${questionUserAcct}
${body.status}`;
}
if (question.isNSFW)
{
body.status = 'Q. ' + question.question + '\n' + body.status;
body.status = `Q. ${question.question}
${body.status}`;
body.spoiler_text = '⚠ 이 질문은 답변자가 NSFW하다고 했어요. #quesdon';
}
fetch('https://' + user.acct.split('@')[1] + '/api/v1/statuses', {
method: 'POST',
body: JSON.stringify(body),
headers: {
'Authorization': 'Bearer ' + user.accessToken,
'Content-Type': 'application/json'
}
});
fetch('https://' + user.acct.split('@')[1] + '/api/v1/statuses',
{
method: 'POST',
body: JSON.stringify(body),
headers:
{
'Authorization': 'Bearer ' + user.accessToken,
'Content-Type': 'application/json'
}
});
}
else
{
const strQ = cutText(question.question, 60);
const strA = cutText(question.answer!, 120 - strQ.length);
const strA = cutText(question.answer, 120 - strQ.length);
const [key, secret] = user.accessToken.split(':');
const body = 'Q. ' + strQ + '\nA. ' + strA + '\n#quesdon ' + answerUrl;
requestOAuth(twitterClient, {
url: 'https://api.twitter.com/1.1/statuses/update.json',
method: 'POST',
data: {status: body}
}, {
key, secret
});
const body = `Q. ${strQ}
A. ${strA}
#quesdon ${answerUrl}`;
requestOAuth(twitterClient,
{
url: 'https://api.twitter.com/1.1/statuses/update.json',
method: 'POST',
data: { status: body }
}, { key, secret });
}
});
router.post('/:id/delete', async (ctx) =>
router.post('/:id/delete', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const question = await Question.findById(ctx.params.id);
if (!question) return ctx.throw('not found', 404);
// tslint:disable-next-line:triple-equals
if (question.user._id != ctx.session!.user) return ctx.throw('not found', 404);
if (!question)
return ctx.throw('not found', 404);
if (question.user._id != ctx.session.user) // eslint-disable-line eqeqeq
return ctx.throw('not found', 404);
question.isDeleted = true;
await question.save();
ctx.body = {status: 'ok'};
ctx.body = { status: 'ok' };
});
router.post('/:id/like', async (ctx) =>
router.post('/:id/like', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const question = await Question.findById(ctx.params.id);
if (!question) return ctx.throw('not found', 404);
if (!question.answeredAt) return ctx.throw('not found', 404);
if (await QuestionLike.findOne({question})) return ctx.throw('already liked', 400);
if (!question)
return ctx.throw('not found', 404);
if (!question.answeredAt)
return ctx.throw('not found', 404);
if (await QuestionLike.findOne({question}))
return ctx.throw('already liked', 400);
const like = new QuestionLike();
like.question = question;
like.user = mongoose.Types.ObjectId(ctx.session!.user);
like.user = mongoose.Types.ObjectId(ctx.session.user);
await like.save();
question.likesCount = await QuestionLike.find({question}).count();
await question.save();
ctx.body = {status: 'ok'};
ctx.body = { status: 'ok' };
});
router.post('/:id/unlike', async (ctx) =>
router.post('/:id/unlike', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
if (!ctx.session.user)
return ctx.throw('please login', 403);
const question = await Question.findById(ctx.params.id);
const user = mongoose.Types.ObjectId(ctx.session!.user);
if (!question) return ctx.throw('not found', 404);
if (!question.answeredAt) return ctx.throw('not found', 404);
const user = mongoose.Types.ObjectId(ctx.session.user);
if (!question)
return ctx.throw('not found', 404);
if (!question.answeredAt)
return ctx.throw('not found', 404);
const like = await QuestionLike.findOne({question, user});
if (!like) return ctx.throw('not liked', 400);
if (!like)
return ctx.throw('not liked', 400);
await like.remove();
question.likesCount = await QuestionLike.find({question}).count();
await question.save();
ctx.body = {status: 'ok'};
ctx.body = { status: 'ok' };
});
router.get('/:id', async (ctx) =>
router.get('/:id', async (ctx): Promise<never|void> =>
{
const question = await Question.findById(ctx.params.id);
if (!question) return ctx.throw('not found', 404);
if (!question.answeredAt) return ctx.throw('not found', 404);
if (question.isDeleted) return ctx.throw('not found', 404);
if (!question)
return ctx.throw('not found', 404);
if (!question.answeredAt)
return ctx.throw('not found', 404);
if (question.isDeleted)
return ctx.throw('not found', 404);
ctx.body = question;
});
router.post('/all_delete', async (ctx) =>
router.post('/all_delete', async (ctx: Koa.ParameterizedContext): Promise<never|void> =>
{
if (!ctx.session!.user) return ctx.throw('please login', 403);
await Question.update({
user: mongoose.Types.ObjectId(ctx.session!.user)
}, {
$set: {
isDeleted: true
}
}, {
multi: true
});
ctx.body = {status: 'ok'};
if (!ctx.session.user)
return ctx.throw('please login', 403);
await Question.update(
{ user: mongoose.Types.ObjectId(ctx.session.user) },
{
$set: { isDeleted: true }
},
{ multi: true });
ctx.body = { status: 'ok' };
});
export default router;

View File

@ -13,7 +13,7 @@ export const MONGODB_URL = process.env.MONGODB_URL || 'mongodb://localhost/quesd
export const SECRET_KEY = process.env.SECRET_KEY || 'shibuyarin16544';
export var GIT_COMMIT = execSync('git rev-parse HEAD').toString().trim();
export const GIT_COMMIT = execSync('git rev-parse HEAD').toString().trim();
export const PUSHBULLET_CLIENT_ID = process.env.PUSHBULLET_CLIENT_ID;
export const PUSHBULLET_CLIENT_SECRET = process.env.PUSHBULLET_CLIENT_SECRET;

View File

@ -1,16 +1,16 @@
import * as mongoose from 'mongoose';
const schema = new mongoose.Schema({
hostName: {type: String, required: true},
clientId: {type: String, required: true},
clientSecret: {type: String, required: true},
appBaseUrl: {type: String, required: true},
redirectUri: {type: String, required: true}
}, {
timestamps: true
});
const schema = new mongoose.Schema(
{
hostName: {type: String, required: true},
clientId: {type: String, required: true},
clientSecret: {type: String, required: true},
appBaseUrl: {type: String, required: true},
redirectUri: {type: String, required: true}
}, { timestamps: true });
export interface IMastodonApp extends mongoose.Document {
export interface IMastodonApp extends mongoose.Document
{
hostName: string;
clientId: string;
clientSecret: string;
@ -18,4 +18,4 @@ export interface IMastodonApp extends mongoose.Document {
redirectUri: string;
}
export default mongoose.model('mastodon_apps', schema);
export default mongoose.model<IMastodonApp>('mastodon_apps', schema);

View File

@ -3,7 +3,7 @@ import { MONGODB_URL } from '../config';
mongoose.connect(MONGODB_URL).catch((e) =>
{
console.error('MongoDB Error: ' + e.message);
console.error('MongoDB Error: ' + e.message); // eslint-disable-line no-console
process.exit(1);
});

View File

@ -0,0 +1,5 @@
declare module 'mongoose-autopopulate'
{
import { Schema } from 'mongoose';
export default function autopopulate(schema: Schema): void;
}

View File

@ -1,16 +1,16 @@
import * as mongoose from 'mongoose';
import { IQuestion, IUser } from './index';
const schema = new mongoose.Schema({
user: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'users'},
question: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'questions'}
}, {
timestamps: true
});
const schema = new mongoose.Schema(
{
user: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'users' },
question: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'questions' }
}, { timestamps: true });
export interface IQuestionLike extends mongoose.Document {
export interface IQuestionLike extends mongoose.Document
{
user: IUser | mongoose.Types.ObjectId;
question: IQuestion | mongoose.Types.ObjectId;
}
export default mongoose.model('question_likes', schema);
export default mongoose.model<IQuestionLike>('question_likes', schema);

View File

@ -1,23 +1,22 @@
import * as mongoose from 'mongoose';
import { IUser } from './index';
// tslint:disable-next-line:no-var-requires
const autopopulate = require('mongoose-autopopulate'); // @types/がないのでしかたない
import autopopulate from 'mongoose-autopopulate';
const schema = new mongoose.Schema({
user: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'users', autopopulate: true},
question: {type: String, required: true},
answer: String,
answeredAt: Date,
isDeleted: {type: Boolean, default: false},
likesCount: {type: Number, default: 0},
isNSFW: {type: Boolean, default: false},
questionUser: {type: mongoose.Schema.Types.ObjectId, ref: 'users', autopopulate: true}
}, {
timestamps: true
});
const schema = new mongoose.Schema(
{
user: {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'users', autopopulate: true},
question: {type: String, required: true},
answer: String,
answeredAt: Date,
isDeleted: {type: Boolean, default: false},
likesCount: {type: Number, default: 0},
isNSFW: {type: Boolean, default: false},
questionUser: {type: mongoose.Schema.Types.ObjectId, ref: 'users', autopopulate: true}
}, { timestamps: true });
schema.plugin(autopopulate);
export interface IQuestion extends mongoose.Document {
export interface IQuestion extends mongoose.Document
{
user: IUser;
question: string;
answer: string | null;
@ -28,4 +27,4 @@ export interface IQuestion extends mongoose.Document {
questionUser: IUser;
}
export default mongoose.model('questions', schema);
export default mongoose.model<IQuestion>('questions', schema);

View File

@ -1,27 +1,26 @@
import * as mongoose from 'mongoose';
import mongoose from 'mongoose';
import setTransformer from '../utils/setTransformer';
import { IMastodonApp } from './';
const schema = new mongoose.Schema({
acct: {type: String, required: true},
acctLower: {type: String, required: true, unique: true},
app: {type: mongoose.Schema.Types.ObjectId, ref: 'mastodon_apps'},
name: {type: String, required: true},
avatarUrl: {type: String, required: true},
accessToken: {type: String, required: true},
url: {type: String},
description: {type: String, default: ''},
questionBoxName: {type: String, default: '질문 상자'},
pushbulletAccessToken: {type: String},
allAnon: {type: Boolean, default: false},
upstreamId: {type: String},
hostName: {type: String},
stopNewQuestion: {type: Boolean}
}, {
timestamps: true
});
const schema = new mongoose.Schema(
{
acct: { type: String, required: true },
acctLower: { type: String, required: true, unique: true },
app: { type: mongoose.Schema.Types.ObjectId, ref: 'mastodon_apps' },
name: { type: String, required: true },
avatarUrl: { type: String, required: true },
accessToken: { type: String, required: true },
url: { type: String },
description: { type: String, default: '' },
questionBoxName: { type: String, default: '질문 상자' },
pushbulletAccessToken: { type: String },
allAnon: { type: Boolean, default: false },
upstreamId: { type: String },
hostName: { type: String },
stopNewQuestion: { type: Boolean }
}, { timestamps: true });
setTransformer(schema, (doc: IUser, ret: any) =>
setTransformer(schema, (doc: IUser, ret: any) => // eslint-disable-line @typescript-eslint/no-explicit-any
{
ret.hostName = ret.acctLower.split('@').reverse()[0];
delete ret.app;
@ -52,4 +51,4 @@ export interface IUser extends mongoose.Document {
stopNewQuestion: boolean | null;
}
export default mongoose.model('users', schema);
export default mongoose.model<IUser>('users', schema);

View File

@ -1,10 +1,11 @@
import * as Koa from 'koa';
import * as koaBody from 'koa-body';
import * as mount from 'koa-mount';
import * as Pug from 'koa-pug';
import * as Router from 'koa-router';
import * as session from 'koa-session';
import * as path from 'path';
import Koa from 'koa';
import koaBody from 'koa-body';
import mount from 'koa-mount';
import Pug from 'koa-pug';
import Router from 'koa-router';
import session from 'koa-session';
import koaStaticCache from 'koa-static-cache';
import path from 'path';
import rndstr from 'rndstr';
import apiRouter from './api';
import { GIT_COMMIT, PORT, SECRET_KEY } from './config';
@ -14,47 +15,34 @@ const app = new Koa();
app.keys = [SECRET_KEY];
new Pug({
viewPath: path.join(__dirname, '../../views')
}).use(app);
app.use(koaBody({
multipart: true
}));
app.use(session({
}, app));
new Pug( { viewPath: path.join(__dirname, '../../views') } ).use(app);
app.use(koaBody( { multipart: true } ));
app.use(session({}, app));
// tslint:disable-next-line:no-var-requires
app.use(mount('/assets', require('koa-static-cache')(__dirname + '/../client')));
app.use(mount('/assets', koaStaticCache(__dirname + '/../client')));
const router = new Router();
router.use('/api', apiRouter.routes());
router.get('/*', async (ctx) =>
router.get('/*', async (ctx: Koa.ParameterizedContext) =>
{
let user;
if (ctx.session!.user)
if (ctx.session.user)
{
user = await User.findById(ctx.session!.user);
user = JSON.stringify(user).replace(/[\u0080-\uFFFF]/g, (chr) =>
{
return '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).substr(-4);
});
user = await User.findById(ctx.session.user);
user = JSON.stringify(user).replace(/[\u0080-\uFFFF]/g, (chr) => '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).substr(-4) );
user = new Buffer(user, 'binary').toString('base64');
}
if (!ctx.session!.csrfToken)
{
ctx.session!.csrfToken = rndstr();
}
ctx.render('index.pug', {
GIT_COMMIT,
user,
csrfToken: ctx.session!.csrfToken
});
if (!ctx.session.csrfToken)
ctx.session.csrfToken = rndstr();
ctx.render('index.pug',
{
GIT_COMMIT,
user,
csrfToken: ctx.session.csrfToken
});
});
app.use(router.routes());
app.listen(PORT, () =>
{
console.log('listen for http://localhost:' + PORT);
});
app.listen(PORT, () => console.log('listen for http://localhost:' + PORT) ); // eslint-disable-line no-console

View File

@ -1,11 +1,7 @@
export function cutText(s: string, l: number)
export function cutText(s: string, l: number): string
{
if (s.length <= l)
{
return s;
}
else
{
return s.slice(0, l - 1) + '…';
}
}

View File

@ -2,16 +2,14 @@ import * as OAuth from 'oauth-1.0a';
export default new class QueryStringUtils
{
decode(query: string)
decode(query: string): { [key: string]: string }
{
const res: {[key: string]: string} = {};
query.split('&').map((q) =>
{
const splitedQuery = q.split('=');
if (splitedQuery.length < 2)
{
return;
}
const name = splitedQuery[0];
const value = splitedQuery.slice(1).join('=');
res[name] = decodeURIComponent(value);
@ -19,11 +17,10 @@ export default new class QueryStringUtils
return res;
}
encode(params: {[key: string]: any})
encode(params: {[key: string]: any}): string // eslint-disable-line @typescript-eslint/no-explicit-any
{
return Object.keys(params).map((key) =>
{
return encodeURIComponent(key) + '=' + OAuth.prototype.percentEncode(params[key]);
}).join('&');
return Object.keys(params).map(
(key) => encodeURIComponent(key) + '=' + OAuth.prototype.percentEncode(params[key])
).join('&');
}
}();

View File

@ -2,23 +2,27 @@ import fetch, { Response } from 'node-fetch';
import * as OAuth from 'oauth-1.0a';
import QueryStringUtils from './queryString';
export function requestOAuth(oauth: OAuth, options: OAuth.RequestOptions, token?: OAuth.Token)
export function requestOAuth(oauth: OAuth, options: OAuth.RequestOptions, token?: OAuth.Token): Promise<Response>
{
const opt = {
const opt =
{
url: options.url,
method: options.method,
body: QueryStringUtils.encode(options.data),
headers: {
...oauth.toHeader(oauth.authorize(options, token)),
'Content-Type': 'application/x-www-form-urlencoded'
}
headers:
{
...oauth.toHeader(oauth.authorize(options, token)),
'Content-Type': 'application/x-www-form-urlencoded'
}
};
if (options.method === 'GET')
{
opt.url += '?' + opt.body;
delete opt.body;
delete opt.headers['Content-Type'];
}
return fetch(opt.url, opt).then((r) =>
{
if (!r.ok)

View File

@ -1,14 +1,16 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
/* eslint @typescript-eslint/explicit-function-return-type: 0 */
/* eslint eqeqeq: 0 */
import * as mongoose from 'mongoose';
export default (schema: mongoose.Schema, transformer: (doc: any, ret: any) => any) =>
{
if ((schema as any).options.toObject == null)
{
(schema as any).options.toObject = {};
}
if ((schema as any).options.toJSON == null)
{
(schema as any).options.toJSON = {};
}
(schema as any).options.toObject.transform = transformer;
(schema as any).options.toJSON.transform = transformer;
};

View File

@ -1,17 +1,21 @@
import * as crypto from 'crypto';
import * as OAuth from 'oauth-1.0a';
import OAuth from 'oauth-1.0a';
const twitterClient = new OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY!,
secret: process.env.TWITTER_CONSUMER_SECRET!
},
signature_method: 'HMAC-SHA1',
hash_function(baseString, key)
const twitterClient = new OAuth(
{
return crypto.createHmac('sha1', key).update(baseString).digest('base64');
},
realm: ''
});
consumer:
{
key: process.env.TWITTER_CONSUMER_KEY ?? '',
secret: process.env.TWITTER_CONSUMER_SECRET ?? ''
},
signature_method: 'HMAC-SHA1',
hash_function(baseString, key): string
{
return crypto.createHmac('sha1', key).update(baseString).digest('base64');
},
realm: ''
});
export default twitterClient;

View File

@ -1,24 +1,24 @@
doctype html
html
head
meta(name="viewport",content="width=device-width")
if user
script window.USER=JSON.parse(atob("!{user}"))
else
script window.USER=undefined
script window.CSRF_TOKEN="#{csrfToken}"
script window.GIT_VERSION="#{GIT_COMMIT}"
script(src="https://cdn.polyfill.io/v2/polyfill.js?features=fetch")
script(src="/assets/bundle.js?version="+GIT_COMMIT)
body
#root
p ...어? 혹시 페이지가 나오지 않나요??
p 불편을 끼쳐 드려 죄송해요. 새로고침을 해 보시고, 만약 그래도 이 화면만 계속 뜬다면 아래 동작 환경을 충족하는지 확인 후 Mastodon @planet@planet.moe 에 문의해 주세요.
h2 동작 환경
ul
li iOS
del 9.3.5
| &nbsp;10 이상 (추천: iOS 11.2.2 이상)
li Chrome 63 이상
li Firefox 57 이상
p Edge, Internet Explorer는 지원 대상이 아니라서 오류가 발생할 수 있어요. Firefox나 Google Chrome을 추천드려요.
head
meta(name="viewport",content="width=device-width")
if user
script window.USER=JSON.parse(atob("!{user}"))
else
script window.USER=undefined
script window.CSRF_TOKEN="#{csrfToken}"
script window.GIT_VERSION="#{GIT_COMMIT}"
script(src="https://cdn.polyfill.io/v2/polyfill.js?features=fetch")
script(src="/assets/bundle.js?version="+GIT_COMMIT)
body
#root
p ...어? 혹시 페이지가 나오지 않나요??
p 불편을 끼쳐 드려 죄송해요. 새로고침을 해 보시고, 만약 그래도 이 화면만 계속 뜬다면 아래 동작 환경을 충족하는지 확인 후 Mastodon @planet@planet.moe 에 문의해 주세요.
h2 동작 환경
ul
li iOS
del 9.3.5
| &nbsp;10 이상 (추천: iOS 11.2.2 이상)
li Chrome 63 이상
li Firefox 57 이상
p Edge, Internet Explorer는 지원 대상이 아니라서 오류가 발생할 수 있어요. Firefox나 Google Chrome을 추천드려요.

7587
yarn-error.log Normal file

File diff suppressed because it is too large Load Diff

562
yarn.lock
View File

@ -19,9 +19,9 @@
js-tokens "^4.0.0"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.4.0":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f"
integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==
version "7.7.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.1.tgz#b223497bbfbcbbb38116673904debc71470ca528"
integrity sha512-SQ0sS7KUJDvgCI2cpZG0nJygO6002oTbhgSuw4WcocsnbxLwL5Q8I3fqbJdyBAc3uFrWZiR2JomseuxSuci3SQ==
dependencies:
regenerator-runtime "^0.13.2"
@ -59,6 +59,16 @@
dependencies:
"@types/node" "*"
"@types/caseless@*":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==
"@types/common-tags@^1.8.0":
version "1.8.0"
resolved "https://registry.yarnpkg.com/@types/common-tags/-/common-tags-1.8.0.tgz#79d55e748d730b997be5b7fce4b74488d8b26a6b"
integrity sha512-htRqZr5qn8EzMelhX/Xmx142z218lLyGaeZ3YR8jlze4TATRU9huKKvuBmAJEW4LCC4pnY1N6JAm6p85fMHjhg==
"@types/connect@*":
version "3.4.32"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28"
@ -94,17 +104,17 @@
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/express-serve-static-core@*":
version "4.16.10"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.10.tgz#3c1313c6e6b75594561b473a286f016a9abf2132"
integrity sha512-gM6evDj0OvTILTRKilh9T5dTaGpv1oYiFcJAfgSejuMJgGJUsD9hKEU2lB4aiTNy4WwChxRnjfYFuBQsULzsJw==
version "4.16.11"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.11.tgz#46e8cb091de19d51731a05c2581e515855979dad"
integrity sha512-K8d2M5t3tBQimkyaYTXxtHYyoJPUEhy2/omVRnTAKw5FEdT+Ft6lTaTOpoJdHeG+mIwQXXtqiTcYZ6IR8LTzjQ==
dependencies:
"@types/node" "*"
"@types/range-parser" "*"
"@types/express@*":
version "4.17.1"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.1.tgz#4cf7849ae3b47125a567dfee18bfca4254b88c5c"
integrity sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w==
version "4.17.2"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.2.tgz#a0fb7a23d8855bac31bc01d5a58cadd9b2173e6c"
integrity sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
@ -190,6 +200,13 @@
"@types/cookies" "*"
"@types/koa" "*"
"@types/koa-static-cache@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/koa-static-cache/-/koa-static-cache-5.1.0.tgz#37c33f877ecd92c13065ed402184632ab18da326"
integrity sha512-9n89fpWYyhfdpjDmHYJikeah6r2F3LC8F+dm+nuCrKd+7R4CiCnlYbNR1AfB3H/1b7Ndz+uucrAycwi9u7QtRA==
dependencies:
"@types/koa" "*"
"@types/koa-static@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.1.tgz#b740d80a549b0a0a7a3b38918daecde88a7a50ec"
@ -221,32 +238,39 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/mongodb@*":
version "3.3.7"
resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.3.7.tgz#f11fbad6ea48135634bce7e70080031cb35c5c84"
integrity sha512-X/yDgFAgn3ypXN/CcckHe3nzxaliGtvrJ52kW2k9MAHDfYpc83wvvqHECfmx88pfrrquxFgRWqCTXprqABPfbw==
version "3.3.8"
resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.3.8.tgz#a6023ff343a90478c0e22b2b5d35e56964c3ba60"
integrity sha512-hsLcKRBFVeam4FyJOU6bwklvsNHzmUBI5SIxQ2meZu+RZgTDzrv+W19YAHgDIuiTn6UqHrVolweLMk0RpKEbxg==
dependencies:
"@types/bson" "*"
"@types/node" "*"
"@types/mongoose@^5.5.28":
version "5.5.28"
resolved "https://registry.yarnpkg.com/@types/mongoose/-/mongoose-5.5.28.tgz#8f52367c7d05ada15086a50c6f087f13c8949906"
integrity sha512-1VPsBwiJeYDe4E9h8XIL+c3w3q+RzNQwd2R7tnQ8XO7UDOoLOIK4oIRNTUjQY7PFBWAZpzjOggvNDwUkPIDSDQ==
"@types/mongoose@^5.5.29":
version "5.5.29"
resolved "https://registry.yarnpkg.com/@types/mongoose/-/mongoose-5.5.29.tgz#611cb2eaed58d8d12d3f6338d8811290a4407f0f"
integrity sha512-bIlJfCIg/pPhORc35hGs14gmDjPLIPffcs20UgMZFB8bw0WPIAkDRTZJlBLpuZ0UgHTOOxcSt56exkUv7f/1Yw==
dependencies:
"@types/mongodb" "*"
"@types/node" "*"
"@types/node-fetch@^2.5.2":
version "2.5.2"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.2.tgz#76906dea5b3d6901e50e63e15249c9bcd6e9676e"
integrity sha512-djYYKmdNRSBtL1x4CiE9UJb9yZhwtI1VC+UxZD0psNznrUj80ywsxKlEGAE+QL1qvLjPbfb24VosjkYM6W4RSQ==
"@types/node-fetch@^2.5.3":
version "2.5.3"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.3.tgz#b84127facd93642b1fb6439bc630ba0612e3ec50"
integrity sha512-X3TNlzZ7SuSwZsMkb5fV7GrPbVKvHc2iwHmslb8bIxRKWg2iqkfm3F/Wd79RhDpOXR7wCtKAwc5Y2JE6n/ibyw==
dependencies:
"@types/node" "*"
"@types/node@*":
version "12.12.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.3.tgz#ebfe83507ac506bc3486314a8aa395be66af8d23"
integrity sha512-opgSsy+cEF9N8MgaVPnWVtdJ3o4mV2aMHvDq7thkQUFt0EuOHJon4rQpJfhjmNHB+ikl0Cd6WhWIErOyQ+f7tw==
version "12.12.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.6.tgz#a47240c10d86a9a57bb0c633f0b2e0aea9ce9253"
integrity sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==
"@types/oauth@^0.9.0":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.1.tgz#e17221e7f7936b0459ae7d006255dff61adca305"
integrity sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==
dependencies:
"@types/node" "*"
"@types/parse-link-header@^1.0.0":
version "1.0.0"
@ -270,10 +294,10 @@
dependencies:
"@types/react" "*"
"@types/react-router-dom@^5.1.1":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.1.tgz#77a2dae8ba6ff1df51d27517f7646127a51a1a3e"
integrity sha512-yXqWGaehta/cdmjvEQfCbHFX6l1c7QHuE5n2OfhcJ33ufbt55xhAKqQ0BmT24YM3s7OKwrrUUgY3FaSzO7be3Q==
"@types/react-router-dom@^5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.2.tgz#853f229f1f297513c0be84f7c914a08b778cfdf5"
integrity sha512-kRx8hoBflE4Dp7uus+j/0uMHR5uGTAvQtc4A3vOTWKS+epe0leCuxEx7HNT7XGUd1lH53/moWM51MV2YUyhzAg==
dependencies:
"@types/history" "*"
"@types/react" "*"
@ -303,6 +327,16 @@
"@types/react" "*"
popper.js "^1.14.1"
"@types/request@^2.47.0":
version "2.48.3"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.3.tgz#970b8ed2317568c390361d29c555a95e74bd6135"
integrity sha512-3Wo2jNYwqgXcIz/rrq18AdOZUQB8cQ34CXZo+LUwPJNpvRAL86+Kc2wwI8mqpz9Cr1V+enIox5v+WZhy/p3h8w==
dependencies:
"@types/caseless" "*"
"@types/node" "*"
"@types/tough-cookie" "*"
form-data "^2.5.0"
"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
@ -311,46 +345,59 @@
"@types/express-serve-static-core" "*"
"@types/mime" "*"
"@typescript-eslint/eslint-plugin@^2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.6.0.tgz#e82ed43fc4527b21bfe35c20a2d6e4ed49fc7957"
integrity sha512-iCcXREU4RciLmLniwKLRPCOFVXrkF7z27XuHq5DrykpREv/mz6ztKAyLg2fdkM0hQC7659p5ZF5uStH7uzAJ/w==
"@types/tough-cookie@*":
version "2.3.5"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d"
integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==
"@types/ws@^6.0.1":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.3.tgz#b772375ba59d79066561c8d87500144d674ba6b3"
integrity sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==
dependencies:
"@typescript-eslint/experimental-utils" "2.6.0"
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.6.1.tgz#e34972a24f8aba0861f9ccf7130acd74fd11e079"
integrity sha512-Z0rddsGqioKbvqfohg7BwkFC3PuNLsB+GE9QkFza7tiDzuHoy0y823Y+oGNDzxNZrYyLjqkZtCTl4vCqOmEN4g==
dependencies:
"@typescript-eslint/experimental-utils" "2.6.1"
eslint-utils "^1.4.2"
functional-red-black-tree "^1.0.1"
regexpp "^2.0.1"
tsutils "^3.17.1"
"@typescript-eslint/experimental-utils@2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.0.tgz#ed70bef72822bff54031ff0615fc888b9e2b6e8a"
integrity sha512-34BAFpNOwHXeqT+AvdalLxOvcPYnCxA5JGmBAFL64RGMdP0u65rXjii7l/nwpgk5aLEE1LaqF+SsCU0/Cb64xA==
"@typescript-eslint/experimental-utils@2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.1.tgz#eddaca17a399ebf93a8628923233b4f93793acfd"
integrity sha512-EVrrUhl5yBt7fC7c62lWmriq4MIc49zpN3JmrKqfiFXPXCM5ErfEcZYfKOhZXkW6MBjFcJ5kGZqu1b+lyyExUw==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/typescript-estree" "2.6.0"
"@typescript-eslint/typescript-estree" "2.6.1"
eslint-scope "^5.0.0"
"@typescript-eslint/parser@^2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.6.0.tgz#5106295c6a7056287b4719e24aae8d6293d5af49"
integrity sha512-AvLejMmkcjRTJ2KD72v565W4slSrrzUIzkReu1JN34b8JnsEsxx7S9Xx/qXEuMQas0mkdUfETr0j3zOhq2DIqQ==
"@typescript-eslint/parser@^2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.6.1.tgz#3c00116baa0d696bc334ca18ac5286b34793993c"
integrity sha512-PDPkUkZ4c7yA+FWqigjwf3ngPUgoLaGjMlFh6TRtbjhqxFBnkElDfckSjm98q9cMr4xRzZ15VrS/xKm6QHYf0w==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
"@typescript-eslint/experimental-utils" "2.6.0"
"@typescript-eslint/typescript-estree" "2.6.0"
"@typescript-eslint/experimental-utils" "2.6.1"
"@typescript-eslint/typescript-estree" "2.6.1"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/typescript-estree@2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.0.tgz#d3e9d8e001492e2b9124c4d4bd4e7f03c0fd7254"
integrity sha512-A3lSBVIdj2Gp0lFEL6in2eSPqJ33uAc3Ko+Y4brhjkxzjbzLnwBH22CwsW2sCo+iwogfIyvb56/AJri15H0u5Q==
"@typescript-eslint/typescript-estree@2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz#fb363dd4ca23384745c5ea4b7f4c867432b00d31"
integrity sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==
dependencies:
debug "^4.1.1"
glob "^7.1.4"
is-glob "^4.0.1"
lodash.unescape "4.0.1"
semver "^6.3.0"
tsutils "^3.17.1"
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
@ -553,6 +600,20 @@ acorn@^7.1.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
dependencies:
es6-promisify "^5.0.0"
agent-base@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies:
es6-promisify "^5.0.0"
ajv-errors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
@ -563,7 +624,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2:
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
@ -740,6 +801,18 @@ asn1.js@^4.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
assert@^1.1.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
@ -763,7 +836,7 @@ async-each@^1.0.0, async-each@^1.0.1:
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
async-limiter@~1.0.0:
async-limiter@^1.0.0, async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
@ -775,11 +848,34 @@ async@^2.6.2:
dependencies:
lodash "^4.17.14"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
atob@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
axios@^0.18.1:
version "0.18.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3"
integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==
dependencies:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@ -1329,6 +1425,13 @@ batch@0.6.1:
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@ -1629,9 +1732,14 @@ camelcase@^5.0.0, camelcase@^5.3.1:
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
caniuse-lite@^1.0.30000844:
version "1.0.30001006"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001006.tgz#5b6e8288792cfa275f007b2819a00ccad7112655"
integrity sha512-MXnUVX27aGs/QINz+QG1sWSLDr3P1A3Hq5EUWoIt0T7K24DuvMxZEnh3Y5aHlJW6Bz2aApJdSewdYLd8zQnUuw==
version "1.0.30001008"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz#b8841b1df78a9f5ed9702537ef592f1f8772c0d9"
integrity sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
center-align@^0.1.1:
version "0.1.3"
@ -1829,11 +1937,23 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
commander@^2.20.0, commander@~2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
common-tags@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@ -1922,9 +2042,9 @@ content-type@^1.0.4, content-type@~1.0.4:
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
convert-source-map@^1.5.1:
version "1.6.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
dependencies:
safe-buffer "~5.1.1"
@ -1968,7 +2088,7 @@ core-js@^2.4.0, core-js@^2.5.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
core-util-is@^1.0.2, core-util-is@~1.0.0:
core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
@ -2104,6 +2224,13 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
dateformat@~1.0.4-1.2.3:
version "1.0.12"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
@ -2124,7 +2251,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@3.1.0, debug@~3.1.0:
debug@3.1.0, debug@=3.1.0, debug@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
@ -2232,6 +2359,11 @@ del@^4.1.1:
pify "^4.0.1"
rimraf "^2.6.3"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@ -2362,15 +2494,23 @@ dynamic-dedupe@^0.3.0:
dependencies:
xtend "^4.0.0"
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.47:
version "1.3.296"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz#a1d4322d742317945285d3ba88966561b67f3ac8"
integrity sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ==
version "1.3.304"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.304.tgz#49b47d961f8143116174c2f70fbfee3aabf43015"
integrity sha512-a5mqa13jCdBc+Crgk3Gyr7vpXCiFWfFq23YDCEmrPYeiDOQKZDVE6EX/Q4Xdv97n3XkcjiSBDOY0IS19yP2yeA==
elliptic@^6.0.0:
version "6.5.1"
@ -2474,6 +2614,18 @@ es-to-primitive@^1.2.0:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"
escape-html@^1.0.3, escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@ -2721,6 +2873,11 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
@ -2751,6 +2908,16 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
@ -2928,6 +3095,13 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.0.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f"
@ -2947,6 +3121,29 @@ for-own@^0.1.4:
dependencies:
for-in "^1.0.1"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
formidable@^1.1.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659"
@ -3072,6 +3269,13 @@ get-value@^2.0.3, get-value@^2.0.6:
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
glob-base@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@ -3198,6 +3402,19 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.0:
version "5.1.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
dependencies:
ajv "^6.5.5"
har-schema "^2.0.0"
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
@ -3406,11 +3623,28 @@ http-proxy@^1.17.0:
follow-redirects "^1.0.0"
requires-port "^1.0.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
https-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
https-proxy-agent@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81"
integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@ -3623,6 +3857,11 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@^2.0.2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
@ -3855,6 +4094,11 @@ is-type-of@^1.0.0:
is-class-hotfix "~0.0.6"
isstream "~0.1.2"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
@ -3930,6 +4174,11 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
jsesc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
@ -3950,11 +4199,21 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
json3@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
@ -3979,6 +4238,16 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.2.3"
verror "1.10.0"
jstransformer@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3"
@ -4345,6 +4614,23 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
megalodon@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/megalodon/-/megalodon-2.0.0.tgz#7dd484787fa07d2ff836f944e2666ace016d6178"
integrity sha512-UDreCcc6ULNr/6+6ev1QVozjmxyWgBo5ESC1xcYsiXIPVOJFqLRfGC+MuMMVsPD+fOyWiyo5lhfnomJVQgH2sQ==
dependencies:
"@types/oauth" "^0.9.0"
"@types/request" "^2.47.0"
"@types/ws" "^6.0.1"
axios "^0.18.1"
https-proxy-agent "^3.0.0"
moment "^2.24.0"
oauth "^0.9.15"
request "^2.87.0"
socks-proxy-agent h3poteto/node-socks-proxy-agent#master
typescript "^3.4.5"
ws "^7.0.1"
mem@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
@ -4470,7 +4756,7 @@ mime-db@1.40.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
mime-types@^2.1.18, mime-types@^2.1.8, mime-types@~2.1.17, mime-types@~2.1.24:
mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.8, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
version "2.1.24"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
@ -4600,10 +4886,10 @@ mongoose-legacy-pluralize@1.0.2:
resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4"
integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==
mongoose@^5.7.7:
version "5.7.7"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.7.7.tgz#038b47d10434ea6cc9ec9b45d88bfcf9ab401a1a"
integrity sha512-FU59waB4LKBa9KOnqBUcCcMIVRc09TFo1F8nMxrzSiIWATaJpjxxSSH5FBVUDxQfNdJLfg9uFHxaTxhhwjsZOQ==
mongoose@^5.7.8:
version "5.7.8"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.7.8.tgz#ae86bff72687e8950dd95690a5eb3365ad9d57a0"
integrity sha512-GsFXYo7z3ebnIDdnqlDJYQXQFqEGS+yxfdY9G0B7fxpvUJchDpwLGuGJdVd1QbGxu2l0DscCYBO0ntl3G6OACA==
dependencies:
bson "~1.1.1"
kareem "2.3.1"
@ -4900,6 +5186,16 @@ number-is-nan@^1.0.0:
version "2.2.3"
resolved "https://codeload.github.com/rinsuki/oauth-1.0a/tar.gz/b6a8b9cfd4f9621c03a57379f4f04ce79e2f4248"
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
oauth@^0.9.15:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@ -5271,6 +5567,11 @@ pbkdf2@^3.0.3:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
picomatch@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.0.tgz#0fd042f568d08b1ad9ff2d3ec0f0bfb3cb80e177"
@ -5454,6 +5755,11 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
psl@^1.1.24:
version "1.4.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2"
integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==
public-encrypt@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@ -5601,7 +5907,7 @@ punycode@1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@^1.2.4:
punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
@ -5621,6 +5927,11 @@ qs@^6.4.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.0.tgz#d1297e2a049c53119cb49cca366adbbacc80b409"
integrity sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@ -5956,6 +6267,32 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
request@^2.87.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.0"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.4.3"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@ -6132,7 +6469,7 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3":
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@ -6337,6 +6674,11 @@ sliced@1.0.1:
resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41"
integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=
smart-buffer@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@ -6387,6 +6729,21 @@ sockjs@0.3.19:
faye-websocket "^0.10.0"
uuid "^3.0.1"
socks-proxy-agent@h3poteto/node-socks-proxy-agent#master:
version "4.0.2"
resolved "https://codeload.github.com/h3poteto/node-socks-proxy-agent/tar.gz/5be42d4a3f98c5a156d713ea88a54b825f26d1f3"
dependencies:
agent-base "~4.2.1"
socks "~2.3.2"
socks@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==
dependencies:
ip "^1.1.5"
smart-buffer "4.0.2"
source-list-map@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
@ -6501,6 +6858,21 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
@ -6881,6 +7253,14 @@ token-stream@0.0.1:
resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a"
integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=
tough-cookie@~2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
dependencies:
psl "^1.1.24"
punycode "^1.4.1"
trim-newlines@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
@ -6924,6 +7304,18 @@ tty-browserify@0.0.0:
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@ -6954,10 +7346,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^3.6.4:
version "3.6.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==
typescript@^3.4.5, typescript@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
uglify-js@^2.6.1:
version "2.8.29"
@ -6970,9 +7362,9 @@ uglify-js@^2.6.1:
uglify-to-browserify "~1.0.0"
uglify-js@^3.6.0:
version "3.6.5"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.5.tgz#b0ee796d2ae7e25672e04f65629b997cd4b30bd6"
integrity sha512-7L3W+Npia1OCr5Blp4/Vw83tK1mu5gnoIURtT1fUVfQ3Kf8WStWV6NJz0fdoBJZls0KlweruRTLVe6XLafmy5g==
version "3.6.7"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.7.tgz#15f49211df6b8a01ee91322bbe46fa33223175dc"
integrity sha512-4sXQDzmdnoXiO+xvmTzQsfIiwrjUCSA95rSP4SEd8tDb51W2TiDOlL76Hl+Kw0Ie42PSItCW8/t6pBNCF2R48A==
dependencies:
commander "~2.20.3"
source-map "~0.6.1"
@ -7144,10 +7536,19 @@ vary@^1.1.2, vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
verror@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
vm-browserify@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
void-elements@^2.0.1:
version "2.0.1"
@ -7388,6 +7789,13 @@ ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
ws@^7.0.1:
version "7.2.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.0.tgz#422eda8c02a4b5dba7744ba66eebbd84bcef0ec7"
integrity sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==
dependencies:
async-limiter "^1.0.0"
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"